Closed SparkyDK closed 5 years ago
Hi, please try the pigpio branch, if this works, there is something wrong with your wiringpi version. HTH, Ulrich
Yes, works with pigpio branch ... or, at least, it reads without a segmentation fault. It reads a value of 0 for the ID though (not 3) and then reads a value of 0 for the analog value too.... so, I might still be having some issues... time to get out the logic analyzer or the data sheet.
I think that this is probably the same issue as JWebster's issue ( #12 ). Are you missing a line in your config file, in the branch version of the default config file (SPI_FLAGS = 0b0000000000000011100001).
Thanks for your help (so quick!). I wonder what's wrong with wiringpi (latest version 1.24.0).
@SparkyDK were you ever able to make progress with pigpio? I ran into the same problems.
Yes, it still misses the odd read of the status register, but it generally reads a sensible value from my A/D now. The pigpio daemon is not the most reliable and can sometimes take 10's of seconds to die, if killed, which seems to be necessary (periodically) with the code. I would much rather have used the wiringpi version, but was never quite able to get that going on my machine. Good luck.
The reason for the segfault is because in python3 there is a difference between strings and bytes. The wiringpi python documentation suggests using
buf = bytes([your data here])
retlen, retdata = wiringpi.wiringPiSPIDataRW(0, buf)
The problem with that is that in python3 buf = bytes([1])
sets buf to b'1'
, whereas in python2 it sets buf to '[1]'
. I tried fixing this using buf = bytes(bytearray([1]))
which seems to do the same thing in both python2 and python3. With those changes, the example scripts seems to be fully working for python3 but I'm running into issues with python2. If I remove the while loop in the example.py file, python2 prints out correct voltages, however with the while loop all the voltages end up being zero.
I haven't figured out what's going on when run with python2 yet.
My changes are here
Hi, I looked into this again.
Indeed, in Python 3, wiringpi.wiringPiSPIDataRW() expects the second argument as a bytes object instead of a single-character string: This causes the segmentation fault.
Why can't the bytes object be used under Python 2 (where it is treated as a string) and under Python 3?
This really still seems to be the issue explained in https://github.com/WiringPi/WiringPi-Python/issues/25
In detail, what wiringPi does is treat the second argument as a mutable argument, i.e. it is treated as a pointer and new data is returned and written to its address. This is OK in the original C implementation, but it is a bug in wiringPi-Python, because in Python this is not ever expected to happen to a string argument.
For Python 2, we have a workaround with the "%s" % string_input string formatting expression, which results in a memory copy of string_input.
However, if we run this string formatting expression in python 3, we get a different result than in python 2, i.e. the workaround does not work:
Python 2: str1 = 'a' str2 = "%s" % str1
str1 => 'a'
str2 => 'a'
id(str1) => some memory address
id(str2) => some other address
Whereas running the same in Python 3, id(str1) and id(str2) yield the same address.
This behaviour does not change when using bytes(bytearray([byte])).
Maybe there is a workaround that works for both Python 2 /and/ Python 3 without modification, but this really should be fixed in wiringPi.
I will add a comment in the Readme that the wiringpi version only runs in Python 2.7.
Hi, the code from the master branch should now work with both Python3 and Python2.
def _send_uint8(self, *vals):
# Reads integers in range (0, 255), sends as uint-8 via the SPI bus
wp.wiringPiSPIDataRW(self.SPI_CHANNEL, struct.pack("{}B.format(len(vals))", *vals))
# Python3 only:
# wp.wiringPiSPIDataRW(self.SPI_CHANNEL, bytes(vals))
Please feel free to test this and let me know if there are still issues.
Ulrich/All, I am trying to get the High-Speed ADC (Waveshare product based on the 1256) working on a Raspberry Pi 3 using python3 and this code. Using example.py module, pin setup and mode configuration seems to work and code execution gets to the first pipyadc 'send_byte' of xFE (reset) and then gives me a "Segmentation Fault".
My experience with segmentation faults in other languages like C is that there is some kind of memory addressing error. Perhaps this is because I have not set up something in the kernel properly. I have a line 'dtparam=spi=on' in /boot/config.txt but no other device tree overlays). lsmod | grep spi shows 'spidev' and 'spi_bcm2835'. Maybe there is some other reason (improper PI GPIO SPI pin configuration?). I have not pulled out a logic analyzer. It doesn't seem to be worthwhile yet. I am apparently been able to read ADC values using pigpio (https://www.raspberrypi.org/forums/viewtopic.php?t=134270&start=25) . Wiringpi Gpio commands also seem to work fine (e.g. I can set bit port outputs on my Pi and can see the pins go high and low, as they should). However, the combination of SPI bus and wiringpi and your code doesn't yet work for me, in terms of reading the ADC on SPI input channel 0.
Any suggestions? / David