Teensy 4.0 : strange behavior of CS lines on an SPI bus

Zter

Member
Good morning, Miss, Mister.
My name is Florent Mosnier, and I am (still) working on a project where I need to log the measures of 9 accelerometers on an SD card in real time.
I firstly made progress, but a glitch of the board has stopped my project for 10 months already :
when putting too many devices on the same SPI bus, the transactions are dropped (the CS line goes back to high before the transaction's end) (see the chronograms below : yellow is Sck, purple is MOSI, blue is MISO and green is a CS line)

My system is centered around a teensy4.0, that I picked for it's two SPI ports (one for the sensors and the other for the SD card).
Every sensor is an LSM6DSOX module made by adafruit : https://www.adafruit.com/product/4438
They are all connected on the secondary SPI bus (SCK on pin 27, MOSI on pin 26, and MISO on pin 1)
I made a dedicated pcb to hold every component in place, and made extra care to decrease noise sources on the spi bus :
ground planes, spi lines sandwiched between ground tracks, CS tracks sandwiched between ground tracks,
for the simplicty of making the pcb on a CNC, it's single faced and ground plane part connected to the others every 3cm (or even more often) with gage 30 wire (I used some wire wrapping wire)
lastly, the power delivered to the sensors by another pcb that connects to the main one with pin headers.

The issues appear systematically when more than two sensors are connected on the bus, it's not a matter of where the sensors are placed, everything place works beautifully when there is only one sensor on the bus, every one of my sensors works reliably when it is alone on the bus or in pairs, but when they are 3 or more, every SPI transaction is dropped by the MCU, with the same program running in the two cases, and strangely, the teensy4.0 heats up the more sensors there is on the bus

I use the code below to test if every place for a sensor responds and gives a proper response when reading the WHO_AM_I register,
I tried increasing the bus frequency to 10 MHz, no results, lowering it to 1 MHz, always the same issue, modifying the sensor boards to remove all the level-shifting components (I power them with 3.3V from the teensy anyway), no improovements

If anyone has some ideas to improve the situation, it would be greatly appreciated
 

Attachments

  • normal behavior.png
    normal behavior.png
    23.6 KB · Views: 9
  • dropped transaction.png
    dropped transaction.png
    24.4 KB · Views: 11
  • spi_scope.ino
    3.4 KB · Views: 8
Your clock is the wrong polarity if you look at the datasheet - this is important for devices that support SPI and I2C on the same pins - get the clock wrong and you are triggering the I2C interface all the time \CS is high. I'd fix that first.

I've also encountered I2C/SPI interfaces that cannot work with more than one sharing an SPI bus because the MISO pin doesn't float on \CS going high, hopefully that's not the case here.
 
A hazard here is that the target uses the CS pin to select between I2C and SPI. Which means that the devices that aren't selected are looking for I2C things to be happening. Depending on what clock and data are doing, that could be a problem.

Some devices with dual mode interface and shared pins have a bit you can set in a register to disable the I2C bus.
 
Thank you both for your answers,
MarkT, If I am reading correctly the LSM6DSOX's datasheet, it seems that my SPI clocking needs to have a polarity of 1 (to idle at logic high), and a phase of 1 to read at rising edges, which would mean SPI_MODE3 in the SPISettings ?
UhClem, in order to avoid sensors disturbing the SPI bus with an I2C understanding, should I write to all sensors at the same time the CTRL4_C register by pulling all CS lines at the same time, this way none would try to understand the sequence as an I2C transaction.
I don't see another way as if I am correct, the registers go back to their default values when being powered on.
Should I add some fast switching diodes (I was thinking about the 1N4148) between the bus and every sensor on the MOSI line to avoid return by sensors using it as an SDA line ?

(edit 15 min later)
I implemented the above-mentioned changes, I don't have a regression, I can easily interact with two brand-new sensors, but it still doesn't work with three.
I also tried interfacing sensors which I removed every unnecessary component (ie all the level-shifting transistors, diodes and voltage regulator) which work a little bit better, I can put two of them on the bus and a brand-new one in a third spot.
I still don't have rotted the issue but I think I am getting onto something.
A nice bonus, is that beforehand, when I only added the simplified sensors, I got a reading of 0xFF on every empty sensor spot, now I have a correct reading of 0x00.

To be frank, 4 of the 9 intended sensors are located on secondary PCBs which aren't finished. As of now, I can only use 3 of the main pcb's five spots : the last spot is meant for an LSM9DS1 (in order to also integrate a compass), and another one is unusable due to a partial short-circuit made by a bad solder (I don't have a frank short-circuit, but a resistor between 60 and 200 ohms between the CS line and ground).

My theory at the moment is that I am exceeding the teensy current limits (due to the short-circuit, all the polarising resistors of the level shifters, and current returns due to cross-talking in I2C other the SPI line), that would explain :
How I can have two simplified sensors and an original one, but nether three originals
How my current pcb is performing worse than the precedent version (that could handle 4 sensors) but had really weird glitches and was really battered in places due to a lot of desoldering and resoldering.
Why the teensy is heating up evrytime I put too much sensors on the bus

I will repair the remaining spot and salvage some simplified sensors to test with 4 sensrs tomorrow, I will keep you updated
 

Attachments

  • datasheet.JPG
    datasheet.JPG
    70.6 KB · Views: 3
  • datasheet_pg57.JPG
    datasheet_pg57.JPG
    60.4 KB · Views: 3
Last edited:
UhClem, in order to avoid sensors disturbing the SPI bus with an I2C understanding, should I write to all sensors at the same time the CTRL4_C register by pulling all CS lines at the same time, this way none would try to understand the sequence as an I2C transaction.
That should work.
 
The situation becomes even weirder, I didn't have time to prepare four simplified sensors, but I could remove the short-circuit.
I have several sensors from different orders (one from September 2023, the second from June 2024 and the last from this month).
Just for your information, my first order seems to comes from a different production batch then the two later ones, as the first order sensors features black qwiic connectors and the sensors form the second and third order features white ones .
As far as my test go for the moment, I can communicate with four sensors from the first batch on my testing PCB, but I can't even communicate reliably with three sensors form either the second or third batch. I am really considering it an issue laying with the level-shifting transistors, as as they aren't such critical components, a swap with a different model from different production batches might explain the phenomena.

It's really nice when components that should be identical aren't and you are stuck to pick the good ones in the production dispersion.
 
Back
Top