Go Down

Topic: Unable to communicate with LSM6DS3 via SPI (Read 363 times) previous topic - next topic

azelogose

Hello everyone,

   I have a LSM6DS3 sensor connected via I2C that works perfectly. Nowadays I'm working on a new project based on SPI protocol but I cannot establish any communication with the sensor.

Facts:
1) I use MODE3 because the following is mentioned in its datasheet
"Those lines are driven at the falling edge of SPC and should be captured at the rising edge of SPC."

2) When reading from sensor, MSB should be '1'. I copy from datasheet
"bit 0: READ bit. The value is 1.
bit 1-7: address AD(6:0). This is the address field of the indexed register.
bit 8-15: data DO(7:0) (read mode). This is the data that will be read from the device (MSb first).
bit 16-...: data DO(...-8). Further data in multiple byte reads.
"

3) The simplest communication is via register 0x0F which is tagged as WHO_AM_I and should return 0x69.
"WHO_AM_I (0Fh).
Who_AM_I register (r). This register is a read-only register. Its value is fixed at 69h
"

4) I use a barebone 328P (bootloaded as Lilypad 8MHz with no external resonator) on a breadboard.
Only SPI(D10-D13, vcc, gnd) and USART(tx, rx, vcc, gnd) pins are used at this timepoint.

5)
I have no access to an oscilloscope neither to a logic analyzer

6) Using Adafruit's library is depreciated.

So here I am:
Code: [Select]

#include <SPI.h>

void setup(){
  Serial.begin(9600);
  setup_spi();
}


void loop(){}

void setup_spi(){
 const    uint8_t WHO_ADR  = (1<<7)|0x0F;
 const    uint8_t LSM_SSP  =          10;
          uint8_t lsm      =           0;  //only for debugging
          uint8_t raw      =           0;

  Serial.print(F("SPI start\n"));
  pinMode(LSM_SSP, OUTPUT);
  digitalWrite(LSM_SSP, HIGH);
  SPI.begin();

  SPI.beginTransaction(SPISettings(250000, MSBFIRST, SPI_MODE3));
  digitalWrite(LSM_SSP, LOW );

  lsm = SPI.transfer(WHO_ADR);
  raw = SPI.transfer(WHO_ADR);

  digitalWrite(LSM_SSP, HIGH);
  SPI.endTransaction();

  SPI.end();

  Serial.print(F("reg_address")); Serial.print(F("\t"));
  Serial.print(WHO_ADR, HEX); Serial.print(F("\t"));
  Serial.print(WHO_ADR, BIN); Serial.print(F("\n"));
  Serial.print(F("should_get")); Serial.print(F("\t"));
  Serial.print(0x69, HEX); Serial.print(F("\t"));
  Serial.print(0x69, BIN); Serial.print(F("\n"));
  Serial.print(F("debug_lsm")); Serial.print(F("\t"));
  Serial.print(lsm, HEX); Serial.print(F("\t"));
  Serial.print(lsm, BIN); Serial.print(F("\n"));
  Serial.print(F("true_raw")); Serial.print(F("\t"));
  Serial.print(raw, HEX); Serial.print(F("\t"));
  Serial.print(raw, BIN); Serial.print(F("\n"));
  Serial.print(F("true_buffer")); Serial.print(F("\t"));
  Serial.print(SPDR, HEX); Serial.print(F("\t"));
  Serial.print(SPDR, BIN); Serial.print(F("\n"));
  Serial.print(F("SPI End\n\n"));
  while(true);  //only for debugging
}


and what I get is:
Code: [Select]

SPI start
reg_address 8F 10001111
should_get 69 1101001
debug_lsm FF 11111111
true_raw 7F 1111111
true_buffer 7F 1111111
SPI End


i) I've tried different speed from 4MHz to 62.5KHz, according to CLOCK_DIVx pattern.
ii) When I tried swapping MISO with MOSI I got only 0xFF.
iii) I've even tried using MODE0-MODE2 with no positive result.
iv) Even when I've tried the following code my AVR have frozen.
Code: [Select]
while(!(SPSR & (1 << SPIF)));

What am I missing?



pylon

That chips runs on 1.8 to 3.6V, I guess you provide 3.3V to it. What type of level converter do you use for the SPI bus lines (the UNO runs on 5V)? Post a wiring diagram!

azelogose

#2
Sep 17, 2018, 07:51 pm Last Edit: Sep 17, 2018, 07:55 pm by azelogose Reason: Explanation
In first place thank you for your response.

Now as I mentioned I don't use any UNO or any other Arduino board, but I run my project on a
ATmega328P-PU with Lilypad 8MHz, internal oscillator bootloader

No caps used, just one resistor for reset pin.

I use a PL2303HX to connect to IDE which provides a 3v3 level (checked with DMM)

I'm posting 2 attachments, one colorful in breadboard-style and one less colorful in schematic-style

Of course I don't connect both sensor simultaneously. In fact there is only one sensor and I just want to show you how I connect it in TWI and SPI mode respectively.  

And once again I underline the fact that in I2C normal-mode (100kHz) it works great with a 10m twisted-pair cable

Edit:
There is a connection between ATmega pin8(GND) and pin22(GND) which I missed in the diagram

pylon

Quote
No caps used, just one resistor for reset pin.
Post complete schematics. You need at least decoupling capacitors.

Quote
I use a PL2303HX to connect to IDE which provides a 3v3 level (checked with DMM)
Did you check if the voltage regulator of this chip is able to provide enough current for your setup?

Quote
And once again I underline the fact that in I2C normal-mode (100kHz) it works great with a 10m twisted-pair cable
Which is remarkable. I hope you don't use a cabling of the same length for the SPI connection. But buses (SPI and I2C) are local buses, the complete bus length should never exceed 50cm.

azelogose

Post complete schematics. You need at least decoupling capacitors.
Schematics represent reality. I just wrote what you see. I only missed to show in Fritzing the jumper connection between pin 8 with pin 22.
Why I2C at 100kHz is working with no decoupling capacitors and SPI aat 62.5kHz is not?

Did you check if the voltage regulator of this chip is able to provide enough current for your setup?
I didn't and I can't.
I didn't check it and I can't believe that there could be a power issue with such a simple circuitry.
What I just measured was power consumption of this LSM module which consumes no more than 1350uA.
I also used an uSD module while I2C protocol testings and there was no problem with the comparatively 'massive' power needs of that setup.

Which is remarkable. I hope you don't use a cabling of the same length for the SPI connection. But buses (SPI and I2C) are local buses, the complete bus length should never exceed 50cm.
To be honest I read a lot of papers and posts about this issue.
My intentions are to achieve a reliable SPI connection over a bus-line that stretches over 20 meters, even sacrificing speed over power consumption.
This is why I'm speaking for kHz and not for MHz.
Anyhow all this will come after I manage to overcome my current problem (aka one step at tthe time).

pylon

Quote
Why I2C at 100kHz is working with no decoupling capacitors and SPI aat 62.5kHz is not?
I2C uses pull-up resistors to hold the idle state while SPI switches the pins to GND or Vcc. You get much steeper edges. And in the posted sketch you use 250kHz and not 62.5kHz.
I don't say this is the reason for the failure but it might be. At least the setup is not correct and that may result in many other problems. The decoupling capacitors are not optional, they are part of every serious design. Take a look at the MOSI signal with a scope. Do you get a more or less rectangular wave at the slave? BTW, the slaves should have decoupling capacitors too.

Quote
My intentions are to achieve a reliable SPI connection over a bus-line that stretches over 20 meters, even sacrificing speed over power consumption.
I strongly advise against that. You might get it working at 5m at low frequencies and good shielding but I won't expect a 20 meter connection to work with these signals reliably.

azelogose

I have no access to oscilloscope; otherwise it would more easier for me to debug.
Anyhow I see your point and I will try again using decoupling caps this time.

Thank you.

azelogose

I tried with one soldered 0.1 uF capacitor between VCC and GND and one 0.1 uF between AVCC and GND but nothing changed.

Then I tried removing that 10-cm cale and plug the module directly to the breadboard. Nothing happened.


I start thinking to rollback to the I2C and use a switch with buffer capabilities.
My problem began when I had to use more than 2 sensors.
Since LSM6DS3 has only 1-byte LSB tolerance in setting desired address I thought switching to SPI would be better.

Off-topic:
Except Analog Devices LTC4312 and LTC4305 is there any other producer that has in his portfolio a switch with integrated bus buffer?
TI for example doesn't mentioned anything. Should I assume that since I use only one channel at a time the capacitance of the other bus-line will be excluded/isolated or not?

pylon

Quote
Should I assume that since I use only one channel at a time the capacitance of the other bus-line will be excluded/isolated or not?
I don't know what exactly you meant by this sentence, but on I2C (and SPI) bus capacitance is always calculated as the sum of all capacitances on the bus (chips and wires). There is no isolation, this is a bus.

azelogose

I don't know what exactly you meant by this sentence, but on I2C (and SPI) bus capacitance is always calculated as the sum of all capacitances on the bus (chips and wires). There is no isolation, this is a bus.
OK, lets assume we have two I2C devices with identical address, eg. 0x6B.
If we want to use them both at the same bus a solution is using an I2C switch like TCA9548.
In this situation you still have one bus? TI claims that there are 8 channels.
And here comes the question; when I enable one channel only should I include to my calculation the capacitance of the other 7 channels?

pylon

Quote
If we want to use them both at the same bus a solution is using an I2C switch like TCA9548.
Which has one input bus and two output buses.

Quote
In this situation you still have one bus? TI claims that there are 8 channels.
Yes, you'll have 8 separate buses (electrically).

Quote
And here comes the question; when I enable one channel only should I include to my calculation the capacitance of the other 7 channels?
No.

azelogose


Go Up