I am trying to connect an Arduino to a digital accelerometer. The Arduino receives commands from a mobile app and transmits over Bluetooth through hardware serial. I also posted this question here.
Code:
#include < SPI.h >
const int X8 = 0x06;
const int Y8 = 0x07;
const int Z8 = 0x08;
/*
bits
1 0 mode 00: standby, 01: measurement
5 1: spi 3 wire, 0: 4 wire
4 self test
3 2 glevel: 01 2g
1 0 mode, 00 standby, 01 measurement
*/
const int MODE = 0x16;
const int STATUS = 0x09;
//7 digital filter band width, 0 62.5 Hz, 1 125 Hz
const int CONTROL = 0x18;
bool isTesting = false;
const int chipSelectPin = 7;
void setup() {
Serial.begin(9600);
SPI.begin();
pinMode(chipSelectPin, OUTPUT);
//set up standby, spi 4 wire, 2g range,
writeRegister(MODE, 0x04);
//set up speed
writeRegister(CONTROL, 0x00);
delay(100);
}
void loop() {
if (getSerial() == 't') {
isTesting = true;
writeRegister(MODE, 0x05); // 0000 0101- 0001 0101 0x15
testing();
}
}
void testing() {
while (isTesting) {
if ((readRegister(STATUS) & 1) == 1) {
Serial.print((char) readRegister(X8), DEC);
Serial.print("x");
Serial.print((char) readRegister(Y8), DEC);
Serial.print("y");
Serial.print((char) readRegisterChar(Z8), DEC);
Serial.print("z");
}
if (getSerial() == 'u') {
isTesting = false;
writeRegister(MODE, 0x04);
}
}
}
char getSerial() {
if (Serial.available()) {
char c = Serial.read();
return c;
}
return 'x';
}
byte readRegister(byte thisRegister) {
byte inByte = 0;
SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0)); // 500khz clock
digitalWrite(chipSelectPin, LOW);
SPI.transfer(thisRegister << 1);
inByte = SPI.transfer(0x00);
digitalWrite(chipSelectPin, HIGH);
return inByte;
}
char readRegisterChar(byte thisRegister) {
char inChar = 0;
SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0)); // 500khz clock
digitalWrite(chipSelectPin, LOW);
SPI.transfer(thisRegister << 1);
inChar = SPI.transfer(0x00);
digitalWrite(chipSelectPin, HIGH);
return inChar;
}
void writeRegister(byte thisRegister, byte value) {
SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0)); // 500khz clock
digitalWrite(chipSelectPin, LOW);
SPI.transfer(128 | thisRegister << 1);
SPI.transfer(value);
digitalWrite(chipSelectPin, HIGH);
}
The sensor allows for data values of 10 bits but for simplicity I am getting only the 8 bit data. The data received when the sensor is on a flat surface is:
x y z
5 -11 74
4 -19 74
2 -9 69
0 -8 68
7 -16 68
7 -11 73
When the self test is run, the results are:
-5 -20 122
-4 -22 122
-1 -20 123
-4 -20 123
-5 -21 121
-3 -18 123
-8 -22 127
From the data sheet: "When the self-test function is initiated through the mode control register ($16), accessing the "self-test" bit, an electrostatic force is applied to each axis to cause it to deflect. The Z-axis is trimmed to deflect 1g."
Is the data correct? How is it interpreted? If the z data during self test is 1g, shouldn't it have the same magnitude as when it is on a flat surface?
I adapted to code to get the 10 bits of data:
const int X10_LSB = 0x00;
const int X10_MSB = 0x01;
const int Y10_LSB = 0x02;
const int Y10_MSB = 0x03;
const int Z10_LSB = 0x04;
const int Z10_MSB = 0x05;
//[...]
void testing() {
while (isTesting) {
if ((readRegister(STATUS) & 1) == 1) {
int xData = (readRegister(X10_MSB) << 8) | readRegister(X10_LSB);
// checks if bit 9 is 1 and sign extends
if ((xData & 512) == 512)
xData = (0b1111110000000000 | xData);
int yData = (readRegister(Y10_MSB) << 8) | readRegister(Y10_LSB);
if ((yData & 512) == 512)
yData = (0b1111110000000000 | yData);
int zData = (readRegister(Z10_MSB) << 8) | readRegister(Z10_LSB);
if ((zData & 512) == 512)
zData = (0b1111110000000000 | zData);
Serial.print(xData);
Serial.print("x");
Serial.print(yData);
Serial.print("y");
Serial.print(zData);
Serial.print("z");
}
The outputs for 2g measurement is:
4 246 -183
5 245 -183
5 245 -182
6 245 -181
For the self test:
252 -20 -134
253 -21 -133
253 -21 -135
253 -20 -135
the values for 8 and 10 bits of data don't correspond. What am I doing wrong?
Update: I rewrote the code to get the 10 bits of data with the LSB bits fisrt as per a comment:
Code:
int xData =(readRegister (X10_LSB));
xData = xData | (readRegister (X10_MSB)<<8);
xData = xData << 6;
int yData =(readRegister (Y10_LSB));
yData = yData | (readRegister (Y10_MSB)<<8);
yData = yData << 6;
int zData = (readRegister (Z10_LSB));
zData = zData | (readRegister (Z10_MSB)<<8);
zData = zData << 6;
xData /= 64;
yData /= 64;
zData /= 64;
The results for the sensor when on a flat surface:
0 -4 71
4 -11 70
5 -13 70
2 -12 70
The results when self-test is applied:
-2 -19 123
-2 -19 122
-4 -20 122
-3 -21 122
Why would the 8 bit and 10 bit results return similar values during a self test (around 128)? Should the 10 bit value be 4X greater?