An example on how to read raw data with calibration
In order to have a valid reading with calibration, i had to read multiple sources on how to drive this IC. The following sources have helped me:
- https://stackoverflow.com/a/19164062
- http://forum.arduino.cc/index.php?topic=216145.0
- https://www.pololu.com/product/2124
- https://forum.arduino.cc/index.php?topic=265541.0
- https://github.com/elechouse/LSM303/blob/master/LSM303/LSM303.cpp
- https://github.com/praneshkmr/node-lsm303/wiki/Understanding-the-calibration-of-the-LSM303-magnetometer-%28compass%29
main.cpp
- Committer:
- ElectronicsSanta
- Date:
- 2017-07-18
- Revision:
- 0:9d83f04e179c
File content as of revision 0:9d83f04e179c:
#include "mbed.h" #include <algorithm> // for min, max functions #define ACCEL_I2C_ADDRESS (0x19 << 1) #define ACCEL_CALIBRATE_TIME 5 // seconds // LPen Zen Yen Xen #define LSM303_REGISTER_ACCEL_CTRL_REG1_A_EN 0x07 // 0 1 1 1 // ODR3 ODR2 ODR1 ODR0 LPen Zen Yen Xen #define LSM303_REGISTER_ACCEL_CTRL_REG1_A_PDWN (0 << 4) // 0 0 0 0 x x x x #define LSM303_REGISTER_ACCEL_CTRL_REG1_A_1_HZ (1 << 4) // 0 0 0 1 x x x x #define LSM303_REGISTER_ACCEL_CTRL_REG1_A_10_HZ (2 << 4) // 0 0 1 0 x x x x #define LSM303_REGISTER_ACCEL_CTRL_REG1_A_25_HZ (3 << 4) // 0 0 1 1 x x x x #define LSM303_REGISTER_ACCEL_CTRL_REG1_A_50_HZ (4 << 4) // 0 1 0 0 x x x x #define LSM303_REGISTER_ACCEL_CTRL_REG1_A_100_HZ (5 << 4) // 0 1 0 1 x x x x #define LSM303_REGISTER_ACCEL_CTRL_REG1_A_200_HZ (6 << 4) // 0 1 1 0 x x x x #define LSM303_REGISTER_ACCEL_CTRL_REG1_A_400_HZ (7 << 4) // 0 1 1 1 x x x x #define LSM303_ACCEL_REFRESH_RATE (LSM303_REGISTER_ACCEL_CTRL_REG1_A_EN | LSM303_REGISTER_ACCEL_CTRL_REG1_A_100_HZ) #define LSM303_REGISTER_ACCEL_DEFAULT_CTRL_REG1_A 0x07 // default value #define LSM303_REGISTER_ACCEL_CTRL_REG1_A 0x20 #define LSM303_REGISTER_ACCEL_CTRL_REG4_A 0x23 // BDU BLE FS1 FS0 HR 0 0 SIM #define LSM303_ACCEL_FS_BIT_00 (0) | (1 << 3) // 0 0 0 0 1 0 0 0 #define LSM303_REGISTER_ACCEL_OUT_X_L_A 0x28 #define LSM303_REGISTER_ACCEL_OUT_X_H_A 0x29 #define LSM303_REGISTER_ACCEL_OUT_Y_L_A 0x2A #define LSM303_REGISTER_ACCEL_OUT_Y_H_A 0x2B #define LSM303_REGISTER_ACCEL_OUT_Z_L_A 0x2C #define LSM303_REGISTER_ACCEL_OUT_Z_H_A 0x2D Serial serial(SERIAL_TX, SERIAL_RX); I2C i2c(I2C_SDA, I2C_SCL); // PB_9, PB_8 Timer calibrate_t; int16_t running_min_x = 32767; int16_t running_min_y = 32767; int16_t running_min_z = 32767; int16_t running_max_x = -32768; int16_t running_max_y = -32768; int16_t running_max_z = -32768; int16_t running_avg_x = 0; int16_t running_avg_y = 0; int16_t running_avg_z = 0; int16_t raw_x; int16_t raw_y; int16_t raw_z; int16_t x; int16_t y; int16_t z; bool calibration_done = false; bool acc_found = false; uint8_t i2c_read8_reg(uint8_t address, int8_t reg) { char i2cBuffer[1]; i2cBuffer[0] = reg; i2c.write(address, i2cBuffer, 1); i2c.read(address, i2cBuffer, 1); return (uint8_t)i2cBuffer[0]; } void i2c_write8_reg(uint8_t address, int8_t reg, int8_t value) { char i2cBuffer[2]; i2cBuffer[0] = reg; i2cBuffer[1] = value; i2c.write(address, i2cBuffer, 2); } void read_accel() { char i2cBuffer[1]; raw_x = 0; raw_y = 0; raw_z = 0; x = 0; y = 0; z = 0; i2cBuffer[0] = LSM303_REGISTER_ACCEL_OUT_X_H_A; i2c.write(ACCEL_I2C_ADDRESS, i2cBuffer, 1); i2c.read(ACCEL_I2C_ADDRESS, i2cBuffer, 1); x = (i2cBuffer[0] << 8); i2cBuffer[0] = LSM303_REGISTER_ACCEL_OUT_X_L_A; i2c.write(ACCEL_I2C_ADDRESS, i2cBuffer, 1); i2c.read(ACCEL_I2C_ADDRESS, i2cBuffer, 1); x |= i2cBuffer[0]; x >>= 4; i2cBuffer[0] = LSM303_REGISTER_ACCEL_OUT_Y_H_A; i2c.write(ACCEL_I2C_ADDRESS, i2cBuffer, 1); i2c.read(ACCEL_I2C_ADDRESS, i2cBuffer, 1); y = (i2cBuffer[0] << 8); i2cBuffer[0] = LSM303_REGISTER_ACCEL_OUT_Y_L_A; i2c.write(ACCEL_I2C_ADDRESS, i2cBuffer, 1); i2c.read(ACCEL_I2C_ADDRESS, i2cBuffer, 1); y |= i2cBuffer[0]; y >>= 4; i2cBuffer[0] = LSM303_REGISTER_ACCEL_OUT_Z_H_A; i2c.write(ACCEL_I2C_ADDRESS, i2cBuffer, 1); i2c.read(ACCEL_I2C_ADDRESS, i2cBuffer, 1); z = (i2cBuffer[0] << 8); i2cBuffer[0] = LSM303_REGISTER_ACCEL_OUT_Z_L_A; i2c.write(ACCEL_I2C_ADDRESS, i2cBuffer, 1); i2c.read(ACCEL_I2C_ADDRESS, i2cBuffer, 1); z |= i2cBuffer[0]; z >>= 4; raw_x = x; raw_y = y; raw_z = z; if (calibration_done) { x -= running_avg_x; y -= running_avg_y; z -= running_avg_z; } } void calibrate() { read_accel(); running_min_x = min(running_min_x, x); running_min_y = min(running_min_y, y); running_min_z = min(running_min_z, z); running_max_x = max(running_max_x, x); running_max_y = max(running_max_y, y); running_max_z = max(running_max_z, z); } int16_t avg(int16_t a, int16_t b) { return (int16_t)((a + b) / 2); } int main() { serial.baud(115200); i2c.frequency((uint32_t)100e3); serial.printf("LSM303DLHC example with calibration...\n"); // who am i uint8_t default_val = i2c_read8_reg(ACCEL_I2C_ADDRESS, LSM303_REGISTER_ACCEL_CTRL_REG1_A); serial.printf("who am i: %d, 0x%X\n", default_val, default_val); if ((default_val & 0xF) == LSM303_REGISTER_ACCEL_DEFAULT_CTRL_REG1_A) { // least significant nibble is the default one acc_found = true; serial.printf("accel found\n"); } else { serial.printf("accel NOT found\n"); } if (acc_found) { // enable the accelerometer i2c_write8_reg(ACCEL_I2C_ADDRESS, LSM303_REGISTER_ACCEL_CTRL_REG1_A, LSM303_ACCEL_REFRESH_RATE); // set accelerometer full-scale bits i2c_write8_reg(ACCEL_I2C_ADDRESS, LSM303_REGISTER_ACCEL_CTRL_REG4_A, LSM303_ACCEL_FS_BIT_00); calibrate_t.start(); serial.printf("calibrating accel..."); while (true) { if (!calibration_done) { if (calibrate_t.read() < ACCEL_CALIBRATE_TIME) { // x sec calibration calibrate(); } else { calibration_done = true; serial.printf("done\n"); running_avg_x = avg(running_min_x, running_max_x); running_avg_y = avg(running_min_y, running_max_y); running_avg_z = avg(running_min_z, running_max_z); serial.printf("calibration results: "); serial.printf("min_x %d, ", running_min_x); serial.printf("min_y %d, ", running_min_y); serial.printf("min_z %d, ", running_min_z); serial.printf("max_x %d, ", running_max_x); serial.printf("max_y %d, ", running_max_y); serial.printf("max_z %d", running_max_z); serial.printf("avg_x %d, ", running_avg_x); serial.printf("avg_y %d, ", running_avg_y); serial.printf("avg_z %d\n", running_avg_z); calibrate_t.reset(); } } else { if (calibrate_t.read_ms() > 200) { // print x ms read_accel(); calibrate_t.reset(); serial.printf("raw x: %d; raw y: %d; raw z: %d\n", raw_x, raw_y, raw_z); serial.printf("x: %d; y: %d; z: %d\n", x, y, z); serial.printf("**************************\n"); } } } } }