Hei,
I'm in the process of making a little workshop tool, also to learn more about interfacing with sensors. To keep the code small, I am not using an ADXL345 library. Later, the inclinometer shall display x or y (pitch or roll) angles and I intend to incorporate a zeroing-button, in case one begins on a fold that is not co-planar to the workbench or press brake's support.
I have done a 2-point calibration with the 6-point-tumble method, with a leveling block on a leveling table, and should later use the values so obtained to correct for this particular IC. The IC is not soldered to the breakout board to allow assuming it is co-planar to it or parallel to the breakout board edges.
The problem I have is that pitch works alright, but roll only provides around -43° to + 43° degrees, when the breakout board is flipped upside down. In all other cases the serial monitor displays "nan". After reading to start learning about DOF and the +90° to -90° problem, I still do not know why roll does not work the way I thought it would; obviously, I'm not understanding something here.
Any hints much appreciated!
#include <Wire.h>
#define DEVICE (0x53) // ADXL345 I2C address, fixed
byte _buff[6];
char POWER_CTL = 0x2D;
char DATA_FORMAT = 0x31;
char DATAX0 = 0x32; // x axis byte 0
char DATAX1 = 0x33; // x axis byte 1
char DATAY0 = 0x34; // y axis byte 0
char DATAY1 = 0x35; // y axis byte 1
char DATAZ0 = 0x36; // z axis byte 0
char DATAZ1 = 0x37; // z axis byte 1
float xMin = -267; // Readings from 2-point calibration with 6-point-tumble method (are particular to each IC)
float xMax = 247;
float yMin = -261;
float yMax = 252;
float zMin = -257;
float zMax = 234;
void setup()
{
Wire.begin();
Serial.begin(57600);
registerWrite(DATA_FORMAT, 0x00); // Set to 2g mode (outputs values -256 +256 per axis as per Analog Devices data-sheet)
registerWrite(POWER_CTL, 0x08); // Set to measuring mode
} // End setup
void loop()
{
readSensor(); // Read from the sensor
delay(1000); // Only for readability
} // End loop
void readSensor() {
uint8_t bytesToRead = 6;
registerRead( DATAX0, bytesToRead, _buff); // Read from the 6 registers
int x = (((int)_buff[1]) << 8) | _buff[0]; // 10 bit (2 bytes), LSB first; convert into an int (Analog Devices data-sheet)
int y = (((int)_buff[3]) << 8) | _buff[2];
int z = (((int)_buff[5]) << 8) | _buff[4];
Serial.print( x ); // Only for calibration process
Serial.print(", "); // Excel delimiter (use CoolTerm at 57600)
Serial.print( y );
Serial.print(", ");
Serial.println( z );
// See p. 9, 11 and 12 of https://www.nxp.com/files-static/sensors/doc/app_note/AN3461.pdf as to DOF and singularity problem
float xRoll = (atan2(-y, z) * 180.0) / M_PI; // Rotation around the x axis
float yPitch = (atan2( x, sqrt(y * y + z * z)) * 180.0) / M_PI; // Rotation around the y axis
Serial.print(xRoll);
Serial.print(", ");
Serial.println(yPitch);
} // End readSensor
void registerWrite(byte address, byte val) {
Wire.beginTransmission(DEVICE);
Wire.write(address);
Wire.write(val);
Wire.endTransmission();
} // End registerWrite
void registerRead(byte address, int num, byte _buff[]) { // Reads num bytes starting from address register on device in to _buff array
Wire.beginTransmission(DEVICE);
Wire.write(address);
Wire.endTransmission();
Wire.beginTransmission(DEVICE);
Wire.requestFrom(DEVICE, num);
int i = 0;
while (Wire.available())
{
_buff[i] = Wire.read(); // Read 1 byte
i++;
}
Wire.endTransmission();
} // End registerRead