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:

Committer:
ElectronicsSanta
Date:
Tue Jul 18 11:07:32 2017 +0000
Revision:
0:9d83f04e179c
first commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ElectronicsSanta 0:9d83f04e179c 1 #include "mbed.h"
ElectronicsSanta 0:9d83f04e179c 2 #include <algorithm> // for min, max functions
ElectronicsSanta 0:9d83f04e179c 3
ElectronicsSanta 0:9d83f04e179c 4 #define ACCEL_I2C_ADDRESS (0x19 << 1)
ElectronicsSanta 0:9d83f04e179c 5 #define ACCEL_CALIBRATE_TIME 5 // seconds
ElectronicsSanta 0:9d83f04e179c 6
ElectronicsSanta 0:9d83f04e179c 7 // LPen Zen Yen Xen
ElectronicsSanta 0:9d83f04e179c 8 #define LSM303_REGISTER_ACCEL_CTRL_REG1_A_EN 0x07 // 0 1 1 1
ElectronicsSanta 0:9d83f04e179c 9
ElectronicsSanta 0:9d83f04e179c 10 // ODR3 ODR2 ODR1 ODR0 LPen Zen Yen Xen
ElectronicsSanta 0:9d83f04e179c 11 #define LSM303_REGISTER_ACCEL_CTRL_REG1_A_PDWN (0 << 4) // 0 0 0 0 x x x x
ElectronicsSanta 0:9d83f04e179c 12 #define LSM303_REGISTER_ACCEL_CTRL_REG1_A_1_HZ (1 << 4) // 0 0 0 1 x x x x
ElectronicsSanta 0:9d83f04e179c 13 #define LSM303_REGISTER_ACCEL_CTRL_REG1_A_10_HZ (2 << 4) // 0 0 1 0 x x x x
ElectronicsSanta 0:9d83f04e179c 14 #define LSM303_REGISTER_ACCEL_CTRL_REG1_A_25_HZ (3 << 4) // 0 0 1 1 x x x x
ElectronicsSanta 0:9d83f04e179c 15 #define LSM303_REGISTER_ACCEL_CTRL_REG1_A_50_HZ (4 << 4) // 0 1 0 0 x x x x
ElectronicsSanta 0:9d83f04e179c 16 #define LSM303_REGISTER_ACCEL_CTRL_REG1_A_100_HZ (5 << 4) // 0 1 0 1 x x x x
ElectronicsSanta 0:9d83f04e179c 17 #define LSM303_REGISTER_ACCEL_CTRL_REG1_A_200_HZ (6 << 4) // 0 1 1 0 x x x x
ElectronicsSanta 0:9d83f04e179c 18 #define LSM303_REGISTER_ACCEL_CTRL_REG1_A_400_HZ (7 << 4) // 0 1 1 1 x x x x
ElectronicsSanta 0:9d83f04e179c 19
ElectronicsSanta 0:9d83f04e179c 20 #define LSM303_ACCEL_REFRESH_RATE (LSM303_REGISTER_ACCEL_CTRL_REG1_A_EN | LSM303_REGISTER_ACCEL_CTRL_REG1_A_100_HZ)
ElectronicsSanta 0:9d83f04e179c 21
ElectronicsSanta 0:9d83f04e179c 22 #define LSM303_REGISTER_ACCEL_DEFAULT_CTRL_REG1_A 0x07 // default value
ElectronicsSanta 0:9d83f04e179c 23
ElectronicsSanta 0:9d83f04e179c 24 #define LSM303_REGISTER_ACCEL_CTRL_REG1_A 0x20
ElectronicsSanta 0:9d83f04e179c 25 #define LSM303_REGISTER_ACCEL_CTRL_REG4_A 0x23
ElectronicsSanta 0:9d83f04e179c 26
ElectronicsSanta 0:9d83f04e179c 27 // BDU BLE FS1 FS0 HR 0 0 SIM
ElectronicsSanta 0:9d83f04e179c 28 #define LSM303_ACCEL_FS_BIT_00 (0) | (1 << 3) // 0 0 0 0 1 0 0 0
ElectronicsSanta 0:9d83f04e179c 29
ElectronicsSanta 0:9d83f04e179c 30 #define LSM303_REGISTER_ACCEL_OUT_X_L_A 0x28
ElectronicsSanta 0:9d83f04e179c 31 #define LSM303_REGISTER_ACCEL_OUT_X_H_A 0x29
ElectronicsSanta 0:9d83f04e179c 32 #define LSM303_REGISTER_ACCEL_OUT_Y_L_A 0x2A
ElectronicsSanta 0:9d83f04e179c 33 #define LSM303_REGISTER_ACCEL_OUT_Y_H_A 0x2B
ElectronicsSanta 0:9d83f04e179c 34 #define LSM303_REGISTER_ACCEL_OUT_Z_L_A 0x2C
ElectronicsSanta 0:9d83f04e179c 35 #define LSM303_REGISTER_ACCEL_OUT_Z_H_A 0x2D
ElectronicsSanta 0:9d83f04e179c 36
ElectronicsSanta 0:9d83f04e179c 37 Serial serial(SERIAL_TX, SERIAL_RX);
ElectronicsSanta 0:9d83f04e179c 38 I2C i2c(I2C_SDA, I2C_SCL); // PB_9, PB_8
ElectronicsSanta 0:9d83f04e179c 39 Timer calibrate_t;
ElectronicsSanta 0:9d83f04e179c 40
ElectronicsSanta 0:9d83f04e179c 41 int16_t running_min_x = 32767;
ElectronicsSanta 0:9d83f04e179c 42 int16_t running_min_y = 32767;
ElectronicsSanta 0:9d83f04e179c 43 int16_t running_min_z = 32767;
ElectronicsSanta 0:9d83f04e179c 44 int16_t running_max_x = -32768;
ElectronicsSanta 0:9d83f04e179c 45 int16_t running_max_y = -32768;
ElectronicsSanta 0:9d83f04e179c 46 int16_t running_max_z = -32768;
ElectronicsSanta 0:9d83f04e179c 47 int16_t running_avg_x = 0;
ElectronicsSanta 0:9d83f04e179c 48 int16_t running_avg_y = 0;
ElectronicsSanta 0:9d83f04e179c 49 int16_t running_avg_z = 0;
ElectronicsSanta 0:9d83f04e179c 50 int16_t raw_x;
ElectronicsSanta 0:9d83f04e179c 51 int16_t raw_y;
ElectronicsSanta 0:9d83f04e179c 52 int16_t raw_z;
ElectronicsSanta 0:9d83f04e179c 53 int16_t x;
ElectronicsSanta 0:9d83f04e179c 54 int16_t y;
ElectronicsSanta 0:9d83f04e179c 55 int16_t z;
ElectronicsSanta 0:9d83f04e179c 56 bool calibration_done = false;
ElectronicsSanta 0:9d83f04e179c 57 bool acc_found = false;
ElectronicsSanta 0:9d83f04e179c 58
ElectronicsSanta 0:9d83f04e179c 59 uint8_t i2c_read8_reg(uint8_t address, int8_t reg) {
ElectronicsSanta 0:9d83f04e179c 60 char i2cBuffer[1];
ElectronicsSanta 0:9d83f04e179c 61 i2cBuffer[0] = reg;
ElectronicsSanta 0:9d83f04e179c 62 i2c.write(address, i2cBuffer, 1);
ElectronicsSanta 0:9d83f04e179c 63
ElectronicsSanta 0:9d83f04e179c 64 i2c.read(address, i2cBuffer, 1);
ElectronicsSanta 0:9d83f04e179c 65
ElectronicsSanta 0:9d83f04e179c 66 return (uint8_t)i2cBuffer[0];
ElectronicsSanta 0:9d83f04e179c 67 }
ElectronicsSanta 0:9d83f04e179c 68
ElectronicsSanta 0:9d83f04e179c 69 void i2c_write8_reg(uint8_t address, int8_t reg, int8_t value) {
ElectronicsSanta 0:9d83f04e179c 70 char i2cBuffer[2];
ElectronicsSanta 0:9d83f04e179c 71 i2cBuffer[0] = reg;
ElectronicsSanta 0:9d83f04e179c 72 i2cBuffer[1] = value;
ElectronicsSanta 0:9d83f04e179c 73 i2c.write(address, i2cBuffer, 2);
ElectronicsSanta 0:9d83f04e179c 74 }
ElectronicsSanta 0:9d83f04e179c 75
ElectronicsSanta 0:9d83f04e179c 76 void read_accel() {
ElectronicsSanta 0:9d83f04e179c 77 char i2cBuffer[1];
ElectronicsSanta 0:9d83f04e179c 78
ElectronicsSanta 0:9d83f04e179c 79 raw_x = 0;
ElectronicsSanta 0:9d83f04e179c 80 raw_y = 0;
ElectronicsSanta 0:9d83f04e179c 81 raw_z = 0;
ElectronicsSanta 0:9d83f04e179c 82 x = 0;
ElectronicsSanta 0:9d83f04e179c 83 y = 0;
ElectronicsSanta 0:9d83f04e179c 84 z = 0;
ElectronicsSanta 0:9d83f04e179c 85
ElectronicsSanta 0:9d83f04e179c 86 i2cBuffer[0] = LSM303_REGISTER_ACCEL_OUT_X_H_A;
ElectronicsSanta 0:9d83f04e179c 87 i2c.write(ACCEL_I2C_ADDRESS, i2cBuffer, 1);
ElectronicsSanta 0:9d83f04e179c 88 i2c.read(ACCEL_I2C_ADDRESS, i2cBuffer, 1);
ElectronicsSanta 0:9d83f04e179c 89 x = (i2cBuffer[0] << 8);
ElectronicsSanta 0:9d83f04e179c 90
ElectronicsSanta 0:9d83f04e179c 91 i2cBuffer[0] = LSM303_REGISTER_ACCEL_OUT_X_L_A;
ElectronicsSanta 0:9d83f04e179c 92 i2c.write(ACCEL_I2C_ADDRESS, i2cBuffer, 1);
ElectronicsSanta 0:9d83f04e179c 93 i2c.read(ACCEL_I2C_ADDRESS, i2cBuffer, 1);
ElectronicsSanta 0:9d83f04e179c 94 x |= i2cBuffer[0];
ElectronicsSanta 0:9d83f04e179c 95
ElectronicsSanta 0:9d83f04e179c 96 x >>= 4;
ElectronicsSanta 0:9d83f04e179c 97
ElectronicsSanta 0:9d83f04e179c 98 i2cBuffer[0] = LSM303_REGISTER_ACCEL_OUT_Y_H_A;
ElectronicsSanta 0:9d83f04e179c 99 i2c.write(ACCEL_I2C_ADDRESS, i2cBuffer, 1);
ElectronicsSanta 0:9d83f04e179c 100 i2c.read(ACCEL_I2C_ADDRESS, i2cBuffer, 1);
ElectronicsSanta 0:9d83f04e179c 101 y = (i2cBuffer[0] << 8);
ElectronicsSanta 0:9d83f04e179c 102
ElectronicsSanta 0:9d83f04e179c 103 i2cBuffer[0] = LSM303_REGISTER_ACCEL_OUT_Y_L_A;
ElectronicsSanta 0:9d83f04e179c 104 i2c.write(ACCEL_I2C_ADDRESS, i2cBuffer, 1);
ElectronicsSanta 0:9d83f04e179c 105 i2c.read(ACCEL_I2C_ADDRESS, i2cBuffer, 1);
ElectronicsSanta 0:9d83f04e179c 106 y |= i2cBuffer[0];
ElectronicsSanta 0:9d83f04e179c 107
ElectronicsSanta 0:9d83f04e179c 108 y >>= 4;
ElectronicsSanta 0:9d83f04e179c 109
ElectronicsSanta 0:9d83f04e179c 110 i2cBuffer[0] = LSM303_REGISTER_ACCEL_OUT_Z_H_A;
ElectronicsSanta 0:9d83f04e179c 111 i2c.write(ACCEL_I2C_ADDRESS, i2cBuffer, 1);
ElectronicsSanta 0:9d83f04e179c 112 i2c.read(ACCEL_I2C_ADDRESS, i2cBuffer, 1);
ElectronicsSanta 0:9d83f04e179c 113 z = (i2cBuffer[0] << 8);
ElectronicsSanta 0:9d83f04e179c 114
ElectronicsSanta 0:9d83f04e179c 115 i2cBuffer[0] = LSM303_REGISTER_ACCEL_OUT_Z_L_A;
ElectronicsSanta 0:9d83f04e179c 116 i2c.write(ACCEL_I2C_ADDRESS, i2cBuffer, 1);
ElectronicsSanta 0:9d83f04e179c 117 i2c.read(ACCEL_I2C_ADDRESS, i2cBuffer, 1);
ElectronicsSanta 0:9d83f04e179c 118 z |= i2cBuffer[0];
ElectronicsSanta 0:9d83f04e179c 119
ElectronicsSanta 0:9d83f04e179c 120 z >>= 4;
ElectronicsSanta 0:9d83f04e179c 121
ElectronicsSanta 0:9d83f04e179c 122 raw_x = x;
ElectronicsSanta 0:9d83f04e179c 123 raw_y = y;
ElectronicsSanta 0:9d83f04e179c 124 raw_z = z;
ElectronicsSanta 0:9d83f04e179c 125
ElectronicsSanta 0:9d83f04e179c 126 if (calibration_done) {
ElectronicsSanta 0:9d83f04e179c 127 x -= running_avg_x;
ElectronicsSanta 0:9d83f04e179c 128 y -= running_avg_y;
ElectronicsSanta 0:9d83f04e179c 129 z -= running_avg_z;
ElectronicsSanta 0:9d83f04e179c 130 }
ElectronicsSanta 0:9d83f04e179c 131 }
ElectronicsSanta 0:9d83f04e179c 132
ElectronicsSanta 0:9d83f04e179c 133 void calibrate() {
ElectronicsSanta 0:9d83f04e179c 134 read_accel();
ElectronicsSanta 0:9d83f04e179c 135
ElectronicsSanta 0:9d83f04e179c 136 running_min_x = min(running_min_x, x);
ElectronicsSanta 0:9d83f04e179c 137 running_min_y = min(running_min_y, y);
ElectronicsSanta 0:9d83f04e179c 138 running_min_z = min(running_min_z, z);
ElectronicsSanta 0:9d83f04e179c 139
ElectronicsSanta 0:9d83f04e179c 140 running_max_x = max(running_max_x, x);
ElectronicsSanta 0:9d83f04e179c 141 running_max_y = max(running_max_y, y);
ElectronicsSanta 0:9d83f04e179c 142 running_max_z = max(running_max_z, z);
ElectronicsSanta 0:9d83f04e179c 143 }
ElectronicsSanta 0:9d83f04e179c 144
ElectronicsSanta 0:9d83f04e179c 145 int16_t avg(int16_t a, int16_t b) {
ElectronicsSanta 0:9d83f04e179c 146 return (int16_t)((a + b) / 2);
ElectronicsSanta 0:9d83f04e179c 147 }
ElectronicsSanta 0:9d83f04e179c 148
ElectronicsSanta 0:9d83f04e179c 149 int main() {
ElectronicsSanta 0:9d83f04e179c 150 serial.baud(115200);
ElectronicsSanta 0:9d83f04e179c 151 i2c.frequency((uint32_t)100e3);
ElectronicsSanta 0:9d83f04e179c 152
ElectronicsSanta 0:9d83f04e179c 153 serial.printf("LSM303DLHC example with calibration...\n");
ElectronicsSanta 0:9d83f04e179c 154
ElectronicsSanta 0:9d83f04e179c 155 // who am i
ElectronicsSanta 0:9d83f04e179c 156 uint8_t default_val = i2c_read8_reg(ACCEL_I2C_ADDRESS, LSM303_REGISTER_ACCEL_CTRL_REG1_A);
ElectronicsSanta 0:9d83f04e179c 157 serial.printf("who am i: %d, 0x%X\n", default_val, default_val);
ElectronicsSanta 0:9d83f04e179c 158
ElectronicsSanta 0:9d83f04e179c 159 if ((default_val & 0xF) == LSM303_REGISTER_ACCEL_DEFAULT_CTRL_REG1_A) { // least significant nibble is the default one
ElectronicsSanta 0:9d83f04e179c 160 acc_found = true;
ElectronicsSanta 0:9d83f04e179c 161 serial.printf("accel found\n");
ElectronicsSanta 0:9d83f04e179c 162 } else {
ElectronicsSanta 0:9d83f04e179c 163 serial.printf("accel NOT found\n");
ElectronicsSanta 0:9d83f04e179c 164 }
ElectronicsSanta 0:9d83f04e179c 165
ElectronicsSanta 0:9d83f04e179c 166 if (acc_found) {
ElectronicsSanta 0:9d83f04e179c 167 // enable the accelerometer
ElectronicsSanta 0:9d83f04e179c 168 i2c_write8_reg(ACCEL_I2C_ADDRESS, LSM303_REGISTER_ACCEL_CTRL_REG1_A, LSM303_ACCEL_REFRESH_RATE);
ElectronicsSanta 0:9d83f04e179c 169
ElectronicsSanta 0:9d83f04e179c 170 // set accelerometer full-scale bits
ElectronicsSanta 0:9d83f04e179c 171 i2c_write8_reg(ACCEL_I2C_ADDRESS, LSM303_REGISTER_ACCEL_CTRL_REG4_A, LSM303_ACCEL_FS_BIT_00);
ElectronicsSanta 0:9d83f04e179c 172
ElectronicsSanta 0:9d83f04e179c 173 calibrate_t.start();
ElectronicsSanta 0:9d83f04e179c 174
ElectronicsSanta 0:9d83f04e179c 175 serial.printf("calibrating accel...");
ElectronicsSanta 0:9d83f04e179c 176
ElectronicsSanta 0:9d83f04e179c 177 while (true) {
ElectronicsSanta 0:9d83f04e179c 178 if (!calibration_done) {
ElectronicsSanta 0:9d83f04e179c 179 if (calibrate_t.read() < ACCEL_CALIBRATE_TIME) { // x sec calibration
ElectronicsSanta 0:9d83f04e179c 180 calibrate();
ElectronicsSanta 0:9d83f04e179c 181 } else {
ElectronicsSanta 0:9d83f04e179c 182 calibration_done = true;
ElectronicsSanta 0:9d83f04e179c 183
ElectronicsSanta 0:9d83f04e179c 184 serial.printf("done\n");
ElectronicsSanta 0:9d83f04e179c 185
ElectronicsSanta 0:9d83f04e179c 186 running_avg_x = avg(running_min_x, running_max_x);
ElectronicsSanta 0:9d83f04e179c 187 running_avg_y = avg(running_min_y, running_max_y);
ElectronicsSanta 0:9d83f04e179c 188 running_avg_z = avg(running_min_z, running_max_z);
ElectronicsSanta 0:9d83f04e179c 189
ElectronicsSanta 0:9d83f04e179c 190 serial.printf("calibration results: ");
ElectronicsSanta 0:9d83f04e179c 191 serial.printf("min_x %d, ", running_min_x);
ElectronicsSanta 0:9d83f04e179c 192 serial.printf("min_y %d, ", running_min_y);
ElectronicsSanta 0:9d83f04e179c 193 serial.printf("min_z %d, ", running_min_z);
ElectronicsSanta 0:9d83f04e179c 194 serial.printf("max_x %d, ", running_max_x);
ElectronicsSanta 0:9d83f04e179c 195 serial.printf("max_y %d, ", running_max_y);
ElectronicsSanta 0:9d83f04e179c 196 serial.printf("max_z %d", running_max_z);
ElectronicsSanta 0:9d83f04e179c 197 serial.printf("avg_x %d, ", running_avg_x);
ElectronicsSanta 0:9d83f04e179c 198 serial.printf("avg_y %d, ", running_avg_y);
ElectronicsSanta 0:9d83f04e179c 199 serial.printf("avg_z %d\n", running_avg_z);
ElectronicsSanta 0:9d83f04e179c 200
ElectronicsSanta 0:9d83f04e179c 201 calibrate_t.reset();
ElectronicsSanta 0:9d83f04e179c 202 }
ElectronicsSanta 0:9d83f04e179c 203 } else {
ElectronicsSanta 0:9d83f04e179c 204 if (calibrate_t.read_ms() > 200) { // print x ms
ElectronicsSanta 0:9d83f04e179c 205 read_accel();
ElectronicsSanta 0:9d83f04e179c 206 calibrate_t.reset();
ElectronicsSanta 0:9d83f04e179c 207 serial.printf("raw x: %d; raw y: %d; raw z: %d\n", raw_x, raw_y, raw_z);
ElectronicsSanta 0:9d83f04e179c 208 serial.printf("x: %d; y: %d; z: %d\n", x, y, z);
ElectronicsSanta 0:9d83f04e179c 209 serial.printf("**************************\n");
ElectronicsSanta 0:9d83f04e179c 210 }
ElectronicsSanta 0:9d83f04e179c 211 }
ElectronicsSanta 0:9d83f04e179c 212 }
ElectronicsSanta 0:9d83f04e179c 213 }
ElectronicsSanta 0:9d83f04e179c 214 }