Go Down

Topic: Trouble with SPI and LIS3DH accelerometer (Read 3212 times) previous topic - next topic

7elEvan

Hello!  I've been working with the Adafruit M0 Adalogger and the Adafruit LIS3DH breakout board for a while, but recently found that the library is no longer sufficient for what I need the LIS3DH to do... so, I've been trying to do some basic communication via SPI between the accelerometer and the microcontroller.  All I want to do is write to one registers (CTRL_REG1) to take it out of the default powerdown mode, then read the WHO_AM_I register.  Right now, whenever I run the code, I get FFh as the value of the register.  I tried the same thing reading CTRL_REG1, and got the same value.  I think I'm missing something pretty basic...


Code: [Select]
/*
 * WHO AM I?
 * The ultimate question for an LIS3DH...
 */

#include <SPI.h>

#define DATAOUT 11      //MOSI
#define DATAIN 12       //MISO
#define SPICLOCK 6      //sck
#define SLAVESELECT 10  //ss

void setup() {
 
  while (!Serial)
  Serial.begin(9600);

  SPI.begin();
 
  // Set SPI pin modes
  pinMode(SPICLOCK, OUTPUT);
  pinMode(DATAOUT, OUTPUT);
  pinMode(DATAIN, INPUT);
  pinMode(SLAVESELECT,OUTPUT);

  // Initialize SPI bus settings
  SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE3));
 
  digitalWrite(SLAVESELECT, HIGH); //disable device

  delay(10);

  // Write to CTRL_REG1 to take out of power down mode
  digitalWrite(SLAVESELECT, LOW); //enable device
  SPI.transfer(0x20);
  SPI.transfer(0x8F);
  digitalWrite(SLAVESELECT, HIGH);

  delay(10);

  // Read and print WHO_AM_I register
  digitalWrite(SLAVESELECT, LOW); //enable device
  // WHO_AM_I address with bit 0 set to "1" as the LIS3DH read command
  SPI.transfer(0x8F);
  uint8_t deviceid = SPI.transfer(0x00);
  digitalWrite(SLAVESELECT, HIGH);

  SPI.endTransaction();

  Serial.println(deviceid, HEX);
 
}

void loop() {
  // put your main code here, to run repeatedly:

}


Because of my set-up, the standard pin 13 for sck is now pin 6.

In the long term, I need to at least enable the high-pass filter, and preferably enable the FIFO as well.  Once I get the basic SPI communication, I think I can get the rest of it...

Thanks for the help!

7elEvan

Also, in case anyone needs it, here are the links to the LIS3DH datasheet and application note:

https://cdn-shop.adafruit.com/datasheets/LIS3DH.pdf
https://cdn-shop.adafruit.com/datasheets/LIS3DHappnote.pdf

jremington

There are four possible SPI modes. Try them all, or study the SPI communications timing diagram in the device data sheet carefully to determine which one is correct.

cattledog

#3
Feb 09, 2017, 08:22 am Last Edit: Feb 09, 2017, 08:23 am by cattledog
From Figure 3 in the data sheet, I agree with your selection of mode 3. and I don't see anything obviously wrong in your code.


I do question the custom SPI set up on the MO Feather with D3 as SCK, and whether or not you actually have an SPI bus correctly on the pins you wanted.

Do you have a logic analyzer to sort this all out?

7elEvan

Thanks for the replies.  I tried all four SPI modes, and all resulted in the same value.

Also, I re-wired the set-up to use pin 13 rather than 6 for SCK, and it returned the same result.  I will have access to an oscilloscope tomorrow, but not a dedicated logic analyzer.

I should also mention I do have an UNO I could troubleshoot some of this with, but will need the M0 in the long run... is it worth a shot to set that up?  The only other idea I have now is inserting small delays between the SPI.transfer commands to ensure I'm not sending multiple commands during a clock cycle (I think that is a thing...?).  Thanks again!

cattledog

Quote
I should also mention I do have an UNO I could troubleshoot some of this with, but will need the M0 in the long run... is it worth a shot to set that up?
In my opinion it is worth it. If you can get it to run on the UNO you know you are not fighting issues with your code, or the sensor. SPI with the AT328 is well known ground and there are alot of people with experince. The Zero or Feather, not so much.

There is a section on this forum for the Zero and you might want to post something in that section, but it is not heavily trafficed. http://forum.arduino.cc/index.php?board=98.0




7elEvan

So, I tried it on the UNO, and after removing the delays and the "while(!Serial)" line, it does work.  I'm off to try and figure out what is happening with the M0... thanks for all your help and the suggestions!

brooke31

I had this same problem myself and finally figured it out. You need to remove 3 of your 4 pinModes--keep the slaveSelect pin mode, but delete the rest. Turns out the SPI library sets up the other pins for you (at least, pins 11, 12, and 13. I'm not sure about pin 6 being used as a clock in your case). By declaring them in a pinMode, it somehow messes the program up and gives you FF for the WHO_AM_I register. After deleting, you should get 33 (in hex), which is correct according to the spec sheet.

Go Up