Jordan Kuehn Posted June 10, 2020 Report Share Posted June 10, 2020 After some googling and looking at the LINX Source Code I could find, it seems like the SPI functions do not make use of the CE lines on the Raspberry Pi and perhaps default to CE0 in parallel with whatever GPIO line is selected by the user. The device I'm looking to connect to uses CE1 and I'm having some trouble finding a way to make this work, short of breadboarding the thing and making the connections manually. Does anyone have any insight here? Quote //Default To Mode 0 With No CS (LINX Uses GPIO When Performing Write) unsigned long spi_Mode = SPI_MODE_0; if(ioctl(SpiHandles[channel], SPI_IOC_WR_MODE, &spi_Mode) < 0) Link to comment
Rolf Kalbermatter Posted June 11, 2020 Report Share Posted June 11, 2020 (edited) 19 hours ago, Jordan Kuehn said: After some googling and looking at the LINX Source Code I could find, it seems like the SPI functions do not make use of the CE lines on the Raspberry Pi and perhaps default to CE0 in parallel with whatever GPIO line is selected by the user. The device I'm looking to connect to uses CE1 and I'm having some trouble finding a way to make this work, short of breadboarding the thing and making the connections manually. Does anyone have any insight here? The note in the C source code is in my opinion false. Unless you add the SPI_NO_CS flag to the SPI mode byte the SPI driver will use the default CS pin that it is assigned by the standard setup. For /dev/spidev0.0 this would be the CE0 signal and for /dev/spidev0.1 this would be CE1. However the Linx driver for the Raspberry Pi only allows for /dev/spidev0.1 to be instantiated. I've been hacking on the liblinxdevice.so driver myself and have added the /dev/spidev0.0 to the allowable SPI channels and also modified the SPIReadWrite() function to skip the custom CS handshake handling when the CS pin is set to 0, which makes more sense to me. It should be possible to disable the standard CS pin too by adding 0x40 (SPI_NO_CS flag) to the mode value that you use to set the SPI mode from your LabVIEW program. The current liblinxdevice.so driver on my github clone is actually even further altered and at the moment in an highly untested state, but I'm planning to spend some time on that over the weekend. I basically redesigned part of the class hierarchy to use a common Linux specific ancestor class for both Raspberry Pi and BeagleBoneBlack devices since they are both very much Linux based. The main difference is only during the initialization where both drivers need to do different initialization routines, and enumerate and enable specific resources. Once that is done the functionality is very much the same for both devices. I also did some preparation for a remoteable interface to the liblinxdevice shared library that would make the whole LabVIEW VI interface implementation a lot simpler and the remote communcation more stable. Edited June 11, 2020 by Rolf Kalbermatter Link to comment
Jordan Kuehn Posted June 11, 2020 Author Report Share Posted June 11, 2020 I also noticed after looking around some more that it was a static call to spidev0.1. Ironically this is what I think I need so I may have another issue. It sounds like you are making some serious updates to the code. I agree that if there is no arbitrary CS pin selected it shouldn't force you to pick one and toggle it for no reason. Are you planning to submit these changes as part of a contribution to the github or release the changes at all? Link to comment
Rolf Kalbermatter Posted June 11, 2020 Report Share Posted June 11, 2020 56 minutes ago, Jordan Kuehn said: I also noticed after looking around some more that it was a static call to spidev0.1. Ironically this is what I think I need so I may have another issue. It sounds like you are making some serious updates to the code. I agree that if there is no arbitrary CS pin selected it shouldn't force you to pick one and toggle it for no reason. Are you planning to submit these changes as part of a contribution to the github or release the changes at all? I will create a pull request for the minor fixes to the Makerhub repo. The current changes are much bigger and restructure quite some code for the BeagleBone and Raspberry Pi. They will also provide the true Pi Model string as Device Name, rather than the current static fixed string. And support two SPI channels and maybe even support for reading the EEPROM I2C on the hat connector, but that may not be something I can easily add from the user space environment the shared library is running in. There will also be a more robust listener and also a client implementation for serial and TCP directly in the shared library. I even found information on how to access the onchip OTP memory but that may not be so helpful. As it is OTP you can't program it multiple times really but you could read some of the device configuration information that way. Link to comment
Jordan Kuehn Posted June 16, 2020 Author Report Share Posted June 16, 2020 At risk of derailing my own topic I'd like to see if someone might be able to shed some light on my original problem. Below is a snippet of code that I've put together in an attempt to replicate a python routine that is not functioning properly. It works fine in python. Address is 1 and I have tried a variety of CS pins, modes, bit order, and asserting the Frame line or not. And the Python routine attached, relevant sections below. This is for a RELAYPlate hat. GPIO.setmode(GPIO.BCM) RELAYbaseADDR=24 ppFRAME = 25 ppINT = 22 GPIO.setup(ppFRAME,GPIO.OUT) GPIO.output(ppFRAME,False) #Initialize FRAME signal time.sleep(.001) #let Pi-Plate reset SPI engine if necessary GPIO.setup(ppINT, GPIO.IN, pull_up_down=GPIO.PUD_UP) spi = spidev.SpiDev() spi.open(0,1) localPath=site.getsitepackages()[0] helpPath=localPath+'/piplates/RELAYhelp.txt' #helpPath='RELAYhelp.txt' #for development only RPversion=1.1 # Version 1.0 - initial release # Version 1.1 - adjusted timing on command functions to compensate for RPi SPI changes def getID(addr): global RELAYbaseADDR VerifyADDR(addr) addr=addr+RELAYbaseADDR id="" arg = list(range(4)) resp = [] arg[0]=addr; arg[1]=0x1; arg[2]=0; arg[3]=0; ppFRAME = 25 GPIO.output(ppFRAME,True) null=spi.xfer(arg,300000,60) #null = spi.writebytes(arg) count=0 # time.sleep(.01) while (count<20): dummy=spi.xfer([00],500000,20) if (dummy[0] != 0): num = dummy[0] id = id + chr(num) count = count + 1 else: count=20 GPIO.output(ppFRAME,False) return id RELAYplate.py Link to comment
Rolf Kalbermatter Posted June 16, 2020 Report Share Posted June 16, 2020 (edited) Well, one problem is that your Python script uses GPIO pin numbers while Linx uses connector pin numbers. Now the GPIO25 happens to be Linx pin 22, so you got that right. But the GPIO22 pin is the Linx pin 15 and you configure that as custom CS signal. This is wrong. The Python script sets this explicitly to be an input and with pullup resistor. The Linx custom CS handling will set this as output and actively drive it, asserting it before every frame and deasserting it afterwards. This is likely going to conflict with whatever your hat is trying to do. There are two things you can try: - Set the custom CS pin for the SPI ReadWrite function to a pin number that is not connected to any pin on your hardware. That will make sure it doesn't conflict with your hardware. Call before the Digital Write for pin 22 an explicit Digital Read for pin 15. This will make sure the digital pin is configured as input. Unfortunately Linx does not allow you currently to configure a pullup/pulldown pinstate, but it may be enough to let your hardware work. Edited June 16, 2020 by Rolf Kalbermatter Link to comment
Jordan Kuehn Posted June 19, 2020 Author Report Share Posted June 19, 2020 On 6/16/2020 at 12:33 PM, Rolf Kalbermatter said: Well, one problem is that your Python script uses GPIO pin numbers while Linx uses connector pin numbers. Now the GPIO25 happens to be Linx pin 22, so you got that right. But the GPIO22 pin is the Linx pin 15 and you configure that as custom CS signal. This is wrong. The Python script sets this explicitly to be an input and with pullup resistor. The Linx custom CS handling will set this as output and actively drive it, asserting it before every frame and deasserting it afterwards. This is likely going to conflict with whatever your hat is trying to do. There are two things you can try: - Set the custom CS pin for the SPI ReadWrite function to a pin number that is not connected to any pin on your hardware. That will make sure it doesn't conflict with your hardware. Call before the Digital Write for pin 22 an explicit Digital Read for pin 15. This will make sure the digital pin is configured as input. Unfortunately Linx does not allow you currently to configure a pullup/pulldown pinstate, but it may be enough to let your hardware work. Thank you for the pointers. Unfortunately that didn't work either. Does the ioctrl c command behave differently than spidev in python? I may be able to give this a shot again in some time, but for now I was able to use a combination of the SSH trick and calling python commands from the CLI to get things working, albeit slowly. Figured I would at least leave a note here for now. Link to comment
Rolf Kalbermatter Posted June 22, 2020 Report Share Posted June 22, 2020 (edited) On 6/19/2020 at 7:33 PM, Jordan Kuehn said: Thank you for the pointers. Unfortunately that didn't work either. Does the ioctrl c command behave differently than spidev in python? I may be able to give this a shot again in some time, but for now I was able to use a combination of the SSH trick and calling python commands from the CLI to get things working, albeit slowly. Figured I would at least leave a note here for now. I'm not sure which Python interface you use but the one I have seen really just uses a shared library to access those things too and uses exactly that function too. Edited June 22, 2020 by Rolf Kalbermatter Link to comment
Recommended Posts
Please sign in to comment
You will be able to leave a comment after signing in
Sign In Now