I have 3 sensors on a board I built (328p-au, 16MHz crystal), all 3 sensors by ST Microelectronics:
(1) L3GD20 Gyro (datasheet)
(1) H3LIS331DL Accelerometer (datasheet)
(1) LIS331DH Accelerometer (datasheet)
Since I am running the 328p at 16MHz/5V, I am using a SN74AHC244 to level-shift the MOSI, SCK, and CS from 5V down to 3.3V. I also have the MISO line running through the level-shifter (yes, not necessary...). I've attached a capture of the portion of the circuit in question (there are 2 other SPI devices not shown, I am setting those CS pins to High and not using them here).
-
All 3 devices report the proper device IDs when the "Who_Am_I" register (0x0F) is sent (0xD4 for the gyro, 0x32 for both accelerometers).
-
I can set the configuration registers, and reading back the registers afterwards reveals the newly-set values
-
The gyro also seems to return more-or-less reasonable values (smaller than +/- 1dps on all 3 axes when sitting on my desk at +/-250dps scaling), increasing in magnitude when I rotate it about any of the 3 axes.
-
But neither accelerometer is returning at all reasonable values:
-
The high-G accelerometer (H3LIS331DL, set to +/-100g scaling) is returning a couple of g magnitude (1-10 mostly) on X and Y axes, and a couple dozen g magnitude (24-40 g) on the Z axis.
-
The low-G accelerometer (LIS331DLH, set to +/-2g scaling) is returning roughly 1/10 of a g on the X and y axes (sometimes a little more but under 1 g, it might be slightly tilted, but not such as to give a 1/4-g reading on such a fine scale setting), but 16g on the z-axis!
I've printed out the untouched MSB and LSB to see if the problem was in my re-assembly of the MSB and LSB, but the individual bytes were definitely supporting the high g-values I am seeing.
Also, my disassembly/re-assembly of the micros() time seems to be wrong, as the value bounces all over the map.
Any thoughts as to what the problem might be? Code is below.
#include <SPI.h>
#define L3G4200_CS 8
#define H3LIS331_CS 6
#define LIS331_CS 7
#define BUFFERS_PIN 4
int L3G4200_range = 250;
int H3LIS331_range = 100;
int LIS331_range = 2;
float L3G4200_scaling;
float H3LIS331_scaling;
float LIS331_scaling;
byte dataArray[22];
unsigned long theTime;
float tempVar;
byte SPIRead8(byte ssPin, byte reg)
{
// read a byte from register "reg" on SPI device on "ssPin"
byte data;
digitalWrite(ssPin, LOW);
SPI.transfer(reg | 0x80); // register to read
data = SPI.transfer(0xFF); // clock in data from device by clocking out a dummy data byte (ignored)
digitalWrite (ssPin, HIGH);
return data;
}
void SPIWrite8(byte ssPin, byte reg, byte data)
{
// write a byte "data" to register "reg" on SPI device on "ssPin"
digitalWrite(ssPin, LOW);
SPI.transfer(reg); // register to write to
SPI.transfer(data); // data to write to register
digitalWrite (ssPin, HIGH);
}
void setup()
{
Serial.begin(115200);
/* ------------------- INITIALIZATION --------------------*/
Serial.println("Initializing...");
// Set CS pins for sensors to output and ensure they are all high
pinMode(L3G4200_CS, OUTPUT);
pinMode(H3LIS331_CS, OUTPUT);
pinMode(LIS331_CS, OUTPUT);
pinMode(BUFFERS_PIN, OUTPUT);
digitalWrite(L3G4200_CS, HIGH);
digitalWrite(H3LIS331_CS, HIGH);
digitalWrite(LIS331_CS, HIGH);
// Set CS pins for other SPI devices to output and set high to ensure no cross-talk
pinMode(9, OUTPUT);
digitalWrite(9, HIGH);
pinMode(10, OUTPUT);
digitalWrite(10, HIGH);
// Initialize SPI settings
SPI.begin();
SPI.setBitOrder(MSBFIRST); // MSBFirst for these sensors
SPI.setDataMode(SPI_MODE3); // Proper SPI mode for these sensors
//SPI.setClockDivider(SPI_CLOCK_DIV16); // Set SPI clock speed
digitalWrite(BUFFERS_PIN, LOW); // enable the SN74AHC244 buffer
Serial.print("Gyro Device ID on pin ");
Serial.print(L3G4200_CS);
Serial.print(" ");
Serial.println(SPIRead8(L3G4200_CS, 0x0F), HEX);
Serial.print("High-G Device ID on pin ");
Serial.print(H3LIS331_CS);
Serial.print(" ");
Serial.println(SPIRead8(H3LIS331_CS, 0x0F), HEX);
Serial.print("Low-G Device ID on pin ");
Serial.print(LIS331_CS);
Serial.print(" ");
Serial.println(SPIRead8(LIS331_CS, 0x0F), HEX);
switch(L3G4200_range)
{
case 250:
SPIWrite8(L3G4200_CS, 0x23, 0x00); // set Gyro scaling to 250dps
L3G4200_scaling = 0.00875;
break;
case 500:
SPIWrite8(L3G4200_CS, 0x23, 0x10); // set Gyro scaling to 500dps
L3G4200_scaling = 0.01750;
break;
case 2000:
SPIWrite8(L3G4200_CS, 0x23, 0x20); // set Gyro scaling to 2000dps;
L3G4200_scaling = 0.07000;
break;
}
switch(H3LIS331_range)
{
case 100:
SPIWrite8(H3LIS331_CS, 0x23, 0x00); // set Accel scaling to 100g
H3LIS331_scaling = 0.049;
break;
case 200:
SPIWrite8(H3LIS331_CS, 0x23, 0x10); // set Accel scaling to 200g
H3LIS331_scaling = 0.098;
break;
case 400:
SPIWrite8(H3LIS331_CS, 0x23, 0x30); // set Accel scaling to 400g
H3LIS331_scaling = 0.195;
break;
}
switch(LIS331_range)
{
case 2:
SPIWrite8(LIS331_CS, 0x23, 0x00); // set Accel scaling to 2g
LIS331_scaling = 0.001;
break;
case 4:
SPIWrite8(LIS331_CS, 0x23, 0x10); // set Accel scaling to 4g
LIS331_scaling = 0.002;
break;
case 8:
SPIWrite8(LIS331_CS, 0x23, 0x30); // set Accel scaling to 8g
LIS331_scaling = 0.0039;
break;
}
SPIWrite8(H3LIS331_CS, 0x20, B00111111); // set accelerometer to normal mode, 1000Hz ODR, enable all axes
SPIWrite8(LIS331_CS, 0x20, B00111111); // set accelerometer to normal mode, 1000Hz ODR, enable all axes
SPIWrite8(L3G4200_CS, 0x20, B11001111); // set gyro to 760Hz ODR, 30 CutOff, enable all axes, normal mode, enable all axes
/* -------------- END INITIALIZATION --------------*/
Serial.print("L3G4200 Scaling: "); Serial.println(L3G4200_scaling,5);
Serial.print("H3LIS331 Scaling: "); Serial.println(H3LIS331_scaling,5);
Serial.print("LIS331 Scaling: "); Serial.println(LIS331_scaling,5);
}
void loop()
{
theTime = micros();
dataArray[0] = theTime;
dataArray[1] = theTime >> 8;
dataArray[2] = theTime >> 16;
dataArray[3] = theTime >> 24;
dataArray[4] = SPIRead8(L3G4200_CS, 0x28); // gyro x LSB
dataArray[5] = SPIRead8(L3G4200_CS, 0x29); // gyro x MSB
dataArray[6] = SPIRead8(L3G4200_CS, 0x2A); // gyro y LSB
dataArray[7] = SPIRead8(L3G4200_CS, 0x2B); // gyro y MSB
dataArray[8] = SPIRead8(L3G4200_CS, 0x2C); // gyro z LSB
dataArray[9] = SPIRead8(L3G4200_CS, 0x2D); // gyro z MSB
dataArray[10] = SPIRead8(H3LIS331_CS, 0x28); // accel x LSB
dataArray[11] = SPIRead8(H3LIS331_CS, 0x29); // accel x MSB
dataArray[12] = SPIRead8(H3LIS331_CS, 0x2A); // accel y LSB
dataArray[13] = SPIRead8(H3LIS331_CS, 0x2B); // accel y MSB
dataArray[14] = SPIRead8(H3LIS331_CS, 0x2C); // accel z LSB
dataArray[15] = SPIRead8(H3LIS331_CS, 0x2D); // accel z MSB
dataArray[16] = SPIRead8(LIS331_CS, 0x28); // accel x LSB
dataArray[17] = SPIRead8(LIS331_CS, 0x29); // accel x MSB
dataArray[18] = SPIRead8(LIS331_CS, 0x2A); // accel y LSB
dataArray[19] = SPIRead8(LIS331_CS, 0x2B); // accel y MSB
dataArray[20] = SPIRead8(LIS331_CS, 0x2C); // accel z LSB
dataArray[21] = SPIRead8(LIS331_CS, 0x2D); // accel z MSB
theTime = ((unsigned long)dataArray[0] << 24) + ((unsigned long)dataArray[1] << 16) + ((unsigned long)dataArray[2] << 8) + (unsigned long)dataArray[3];
Serial.print("Time: "); Serial.println(theTime);
tempVar = (((int)dataArray[5] << 8) + dataArray[4]) * L3G4200_scaling;
Serial.print(" Gyro---X: "); Serial.print(tempVar);
tempVar = (((int)dataArray[7] << 8) + dataArray[6]) * L3G4200_scaling;
Serial.print(" Y: "); Serial.print(tempVar);
tempVar = (((int)dataArray[9] << 8) + dataArray[8]) * L3G4200_scaling;
Serial.print(" Z: "); Serial.println(tempVar);
tempVar = (((int)dataArray[11] << 8) + dataArray[10]) * H3LIS331_scaling;
Serial.print("High-Accel---X: "); Serial.print(tempVar);
tempVar = (((int)dataArray[13] << 8) + dataArray[12]) * H3LIS331_scaling;
Serial.print(" Y: "); Serial.print(tempVar);
tempVar = (((int)dataArray[15] << 8) + dataArray[14]) * H3LIS331_scaling;
Serial.print(" Z: "); Serial.println(tempVar);
tempVar = (((int)dataArray[17] << 8) + dataArray[16]) * LIS331_scaling;
Serial.print(" Low-Accel---X: "); Serial.print(tempVar);
tempVar = (((int)dataArray[19] << 8) + dataArray[18]) * LIS331_scaling;
Serial.print(" Y: "); Serial.print(tempVar);
tempVar = (((int)dataArray[21] << 8) + dataArray[20]) * LIS331_scaling;
Serial.print(" Z: "); Serial.println(tempVar);
Serial.println(" ");
delay(1000);
}