Is there an example similar to the python sca3000 app-note for python ljm? (https://labjack.com/support/app-notes/sca3000-3-axis-accelerometer-spi)
I am specifically looking for how to write and read from a specific address on the chip using ljm python. I am not familiar with SPI so its possible I am missing something obvious.
Thanks
There is not a completed app-note for communicating with the SCA3000 with the python LJM wrapper. We have a basic SPI example in the python LJM wrapper .zip file that shows you what (T7) registers you have to read/write to to use the SPI functionality "/Python_LJM/Examples/SPI/spi.py". That example should have you connect the MISO and MOSI lines together and have you clock data out and read it back demonstrating that the SPI functionality is working properly.
From there, you should look at the T7 SPI documentation page. You will need to read through the app-note and determine the appropriate configurations and then translate that code into LJM code. The variable names in the app-note that get passed into the UD python library should translate into register names for the LJM python library.
If you believe you are super close to having something work but are struggling with verifying the SPI communication interface, we highly recommend the use of a digital logic analyzer. You can get some pretty cheap ones and they will help a lot as you try to get started with SPI.
Attached is a very basic python script that communicates with the adxl362 accelerometer using SPI. This should provide a good python-ljm SPI example for real hardware. This isn't polished by any means. In the process of developing this I have learned a lot about SPI, digitial communication, and the python-ljm library but would have saved a lot of time if an example like this was available.
I tested this on the sparkfun and the Analogue Devices breakout boards. For some reason I had to power the VS and VDD with the 1.25V line on the EB37 board in order to get logical readings. I used a logic analyzer as suggested to make sure I was reading the signal correctly. I believe the labjack T7 Pro is a 3.3v logic device and this sensor accepts up to 3.6v according to the datasheet. I tested this on multiple sparkfun breakout boards and found the same behavior. The AD breakout board also behaved similarly. There seems to be a ground or supply voltage issue I am not finding correctly. All of these measurements were done from pins on the EB37.
If anyone has any suggestions regarding the Vs / Vdd voltage I would appreciate them.
Thanks for creating and sharing this python example.
I'm not sure why you had to power the sensor using the 1.25V line on the EB37 and you are correct about the T7 being a 3.3V logic device. I would have expected you to be able to use the 3.3V screw terminal. The VS terminal on the T7 supplies 5V.
Is it possible to read & write in the same SPI transaction? My initial attempt was to use the eNames function (see below). I have a logic analyzer and I am seeing non-zero responses from the MISO line but its not coming through to the data parameter.
the 20, 20 is overwritten with 0,0 so its doing something, but not returning what I am seeing in the logic analyzer (202, 63)
aNames = ["SPI_DATA_TX", "SPI_DATA_RX"]aWrites = [1, 0]
aNumValues = [2,2]
data = [0, 0, 20, 20]
err_address = 0
data = ljm.eNames(handle, 2, aNames, aWrites, aNumValues, data)
ljm.eWriteName(handle, "SPI_GO", 1)
Writing 1 to SPI_GO tells the T7 to perform the SPI TX transfer and then the RX transfer. SPI_DATA_RX gets the RX data from the T7, and the RX transfer was performed earlier. Currently with your code you are trying to read the RX data before the SPI transfers. The order of writing and reading needs to be:
write SPI_NUM_BYTES
write SPI_DATA_TX
write SPI_GO
read SPI_DATA_RX
Using one Modbus command-response to the T7 would look something like:
numBytes = 2
aNames = ["SPI_NUM_BYTES", "SPI_DATA_TX", "SPI_GO", "SPI_DATA_RX"]
aWrites = [ljm.constants.WRITE, ljm.constants.WRITE, ljm.constants.WRITE, ljm.constants.READ]
aNumValues = [1, numBytes, 1, numBytes]
aValues = [numBytes, 11, 254, 1, 20, 20]
aValuesRet = ljm.eNames(handle, len(aNames), aNames, aWrites, aNumValues, aValues)
#aValuesRet[4] and aValuesRet[5] is the two byte response
That is very helpful thank you.
This might be asking a bit much but is there a way to effectively stream SPI commands where the labjack would repeat an SPI command, collect the response in a buffer registry at a fixed time interval and then we access that buffer and clear it out every so often through the ljm interface? I could see loading up the eNames array with up to 240? requests but those would be very close together and then there would be a relatively long break until the next set of requests.
The sensor I am currently working with (as5048a 14-bit magnetic rotary encoder) does not have its own built-in buffer. However, it is setup so that a chip-select with no command from the MOSI will tell the sensor to return the angle measurement. To read the angle I just need to send 0x0 over the MOSI line repeatedly. Ideally I would like to do this using the labjack micro controller to control the spacing between samples. In the code I have the USB communication (eNames) appears to be the bottle neck for the speeds I would like to take recordings (100- 500 Hz).
Any suggestions?
You should be able to do 100 Hz over USB no problem, and can usually even do your upper speed of 500 Hz:
https://labjack.com/support/datasheets/t7/appendix-a-1
... but really what you are describing is a typical use of the unique Lua scripting feature of the T7:
https://labjack.com/support/datasheets/t7/scripting
I will have someone else follow up with examples that are similar to what you want.
The "SPI Example" and "Lua IO USER RAM FIFO" built into Kipling are good lua script examples to look at. Another good source of information is the readme in this github repository: Lua SPI FIFO Triggered DIO State Machine Example. The github example isn't exactly what you want, but it does provide some extra insight as to how to use the SPI and FIFO registers exposed by the T7.
The github example was able to collect and report data through FIFOs to a LabVIEW program that pulled data out of the FIFOs up to about 980Hz so your 100-500Hz requirement should be possible.
When I ran the single eNames command per read in my code (as suggested above) without any time throttling i'm getting about 800Hz over ~2000 samples. However, the sample-to-sample spacing is all over the place. When I throttle it using time.sleep() to try and hit 100Hz I am still seeing >20% variation in sampling rates. I don't know if the variation I am measuring is just due to the communication or issues with the PC clock not really being accurate enough and the time.time() and time.perf_counter() being too dependent on the CPU speed (which is probably varying).
Ill take a look at the lua scripting. Looks promising. I hope that using the labjack clock to control sample timing will reduce the variation.
Thanks for all the help!
Do you see similar time variations if you run the Testing/c-r_speed_test.py example? It performs 1000 readings (eNames) on AIN0 and provides the average, min and max times for a reading. It can be easily adjusted for more analog inputs or none, digital write/reads, DAC readings and more readings than 1000.
Regarding delays, USB communications factor in as well and can vary command-response times since there is no guaranteed latency with transfers (USB bulk).
In your sample loop are you running other code which could be a time factor?