An example on how to read raw data with calibration

Dependencies:   mbed

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:

Files at this revision

API Documentation at this revision

Comitter:
ElectronicsSanta
Date:
Tue Jul 18 11:07:32 2017 +0000
Commit message:
first commit

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Jul 18 11:07:32 2017 +0000
@@ -0,0 +1,214 @@
+#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");
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Tue Jul 18 11:07:32 2017 +0000
@@ -0,0 +1,1 @@
+https://mbed.org/users/mbed_official/code/mbed/builds/22da6e220af6
\ No newline at end of file