lsm9ds1 not organized
Dependencies: mbed SDFileSystem USBDevice
main.cpp@0:70465b25c44f, 2020-01-27 (annotated)
- Committer:
- zmoutaou
- Date:
- Mon Jan 27 10:50:13 2020 +0000
- Revision:
- 0:70465b25c44f
lsm9ds1 not organized
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
zmoutaou | 0:70465b25c44f | 1 | #include "mbed.h" |
zmoutaou | 0:70465b25c44f | 2 | #include "USBSerial.h" |
zmoutaou | 0:70465b25c44f | 3 | #include "lsm9ds1.h" |
zmoutaou | 0:70465b25c44f | 4 | #include "SDFileSystem.h" |
zmoutaou | 0:70465b25c44f | 5 | |
zmoutaou | 0:70465b25c44f | 6 | |
zmoutaou | 0:70465b25c44f | 7 | |
zmoutaou | 0:70465b25c44f | 8 | |
zmoutaou | 0:70465b25c44f | 9 | USBSerial pc(0x1f00, 0x2012, 0x0001, false); |
zmoutaou | 0:70465b25c44f | 10 | Timer t; |
zmoutaou | 0:70465b25c44f | 11 | int lastPrint = 0; |
zmoutaou | 0:70465b25c44f | 12 | int printInterval = 1; |
zmoutaou | 0:70465b25c44f | 13 | |
zmoutaou | 0:70465b25c44f | 14 | |
zmoutaou | 0:70465b25c44f | 15 | |
zmoutaou | 0:70465b25c44f | 16 | void magcalLSM9DS1(float * dest1) ; |
zmoutaou | 0:70465b25c44f | 17 | void accelgyrocalLSM9DS1(float * dest1, float * dest2); |
zmoutaou | 0:70465b25c44f | 18 | void readBytes(uint8_t address, uint8_t subAddress, uint8_t count, uint8_t * dest); |
zmoutaou | 0:70465b25c44f | 19 | uint8_t readByte(uint8_t address, uint8_t subAddress); |
zmoutaou | 0:70465b25c44f | 20 | void readBytes(uint8_t address, uint8_t subAddress, uint8_t count, uint8_t * dest); |
zmoutaou | 0:70465b25c44f | 21 | void writeByte(uint8_t address, uint8_t subAddress, uint8_t data); |
zmoutaou | 0:70465b25c44f | 22 | void getAres(); |
zmoutaou | 0:70465b25c44f | 23 | void getGres(); |
zmoutaou | 0:70465b25c44f | 24 | void getMres(); |
zmoutaou | 0:70465b25c44f | 25 | void readAccelData(int16_t * destination); |
zmoutaou | 0:70465b25c44f | 26 | void readGyroData(int16_t * destination); |
zmoutaou | 0:70465b25c44f | 27 | void readMagData(int16_t * destination); |
zmoutaou | 0:70465b25c44f | 28 | void MadgwickQuaternionUpdate(float ax, float ay, float az, float gx, float gy, float gz, float mx, float my, float mz); |
zmoutaou | 0:70465b25c44f | 29 | int16_t readTempData(); |
zmoutaou | 0:70465b25c44f | 30 | void initLSM9DS1(); |
zmoutaou | 0:70465b25c44f | 31 | void selftestLSM9DS1(); |
zmoutaou | 0:70465b25c44f | 32 | void LSM9DS1_start( int &erreur ); |
zmoutaou | 0:70465b25c44f | 33 | void LSM9DS1_VARS(float &ax, float &ay, float &az, float &mx, float &my, float &mz,float &anglex,float &angley,float &anglez, float &gx, float &gy, float &gz, bool &erreur, float &yaw, float &pitch,float &roll ); |
zmoutaou | 0:70465b25c44f | 34 | |
zmoutaou | 0:70465b25c44f | 35 | I2C i2c_m(PB_9, PB_8); |
zmoutaou | 0:70465b25c44f | 36 | unsigned char nCRC; // calculated check sum to ensure PROM integrity |
zmoutaou | 0:70465b25c44f | 37 | double dT, OFFSET, SENS, T2, OFFSET2, SENS2; // First order and second order corrections for raw S5637 temperature and pressure data |
zmoutaou | 0:70465b25c44f | 38 | int16_t accelCount[3], gyroCount[3], magCount[3]; // Stores the 16-bit signed accelerometer, gyro, and mag sensor output |
zmoutaou | 0:70465b25c44f | 39 | float gyroBias1[3] = {0, 0, 0}, accelBias[3] = {0, 0, 0}, magBias[3] = {0, 0, 0}; // Bias corrections for gyro, accelerometer, and magnetometer |
zmoutaou | 0:70465b25c44f | 40 | int16_t tempCount; // temperature raw count output |
zmoutaou | 0:70465b25c44f | 41 | float temperature; // Stores the LSM9DS1gyro internal chip temperature in degrees Celsius |
zmoutaou | 0:70465b25c44f | 42 | double Temperature, Pressure; // stores MS5611 pressures sensor pressure and temperature |
zmoutaou | 0:70465b25c44f | 43 | // global constants for 9 DoF fusion and AHRS (Attitude and Heading Reference System) |
zmoutaou | 0:70465b25c44f | 44 | float GyroMeasError = PI * (40.0f / 180.0f); // gyroscope measurement error in rads/s (start at 40 deg/s) |
zmoutaou | 0:70465b25c44f | 45 | float GyroMeasDrift = PI * (0.0f / 180.0f); // gyroscope measurement drift in rad/s/s (start at 0.0 deg/s/s) |
zmoutaou | 0:70465b25c44f | 46 | // There is a tradeoff in the beta parameter between accuracy and response speed. |
zmoutaou | 0:70465b25c44f | 47 | // In the original Madgwick study, beta of 0.041 (corresponding to GyroMeasError of 2.7 degrees/s) was found to give optimal accuracy. |
zmoutaou | 0:70465b25c44f | 48 | // However, with this value, the LSM9SD0 response time is about 10 seconds to a stable initial quaternion. |
zmoutaou | 0:70465b25c44f | 49 | // Subsequent changes also require a longish lag time to a stable output, not fast enough for a quadcopter or robot car! |
zmoutaou | 0:70465b25c44f | 50 | // By increasing beta (GyroMeasError) by about a factor of fifteen, the response time constant is reduced to ~2 sec |
zmoutaou | 0:70465b25c44f | 51 | // I haven't noticed any reduction in solution accuracy. This is essentially the I coefficient in a PID control sense; |
zmoutaou | 0:70465b25c44f | 52 | // the bigger the feedback coefficient, the faster the solution converges, usually at the expense of accuracy. |
zmoutaou | 0:70465b25c44f | 53 | // In any case, this is the free parameter in the Madgwick filtering and fusion scheme. |
zmoutaou | 0:70465b25c44f | 54 | float beta = sqrt(3.0f / 4.0f) * GyroMeasError; // compute beta |
zmoutaou | 0:70465b25c44f | 55 | float zeta = sqrt(3.0f / 4.0f) * GyroMeasDrift; // compute zeta, the other free parameter in the Madgwick scheme usually set to a small or zero value |
zmoutaou | 0:70465b25c44f | 56 | |
zmoutaou | 0:70465b25c44f | 57 | |
zmoutaou | 0:70465b25c44f | 58 | uint32_t delt_t = 0, count = 0, sumCount = 0; // used to control display output rate |
zmoutaou | 0:70465b25c44f | 59 | float pitch, yaw, roll; |
zmoutaou | 0:70465b25c44f | 60 | float deltat = 0.0f, sum = 0.0f; // integration interval for both filter schemes |
zmoutaou | 0:70465b25c44f | 61 | uint32_t lastUpdate = 0, firstUpdate = 0; // used to calculate integration interval |
zmoutaou | 0:70465b25c44f | 62 | uint32_t Now = 0; // used to calculate integration interval |
zmoutaou | 0:70465b25c44f | 63 | |
zmoutaou | 0:70465b25c44f | 64 | float ax, ay, az, gx, gy, gz, mx, my, mz; // variables to hold latest sensor data values |
zmoutaou | 0:70465b25c44f | 65 | float q[4] = {1.0f, 0.0f, 0.0f, 0.0f}; // vector to hold quaternion |
zmoutaou | 0:70465b25c44f | 66 | float eInt[3] = {0.0f, 0.0f, 0.0f}; // vector to hold integral error for Mahony meth |
zmoutaou | 0:70465b25c44f | 67 | |
zmoutaou | 0:70465b25c44f | 68 | // Specify sensor full scale |
zmoutaou | 0:70465b25c44f | 69 | uint8_t OSR = ADC_4096; // set pressure amd temperature oversample rate |
zmoutaou | 0:70465b25c44f | 70 | uint8_t Gscale = GFS_245DPS; // gyro full scale |
zmoutaou | 0:70465b25c44f | 71 | uint8_t Godr = GODR_238Hz; // gyro data sample rate |
zmoutaou | 0:70465b25c44f | 72 | uint8_t Gbw = GBW_med; // gyro data bandwidth |
zmoutaou | 0:70465b25c44f | 73 | uint8_t Ascale = AFS_2G; // accel full scale |
zmoutaou | 0:70465b25c44f | 74 | uint8_t Aodr = AODR_238Hz; // accel data sample rate |
zmoutaou | 0:70465b25c44f | 75 | uint8_t Abw = ABW_50Hz; // accel data bandwidth |
zmoutaou | 0:70465b25c44f | 76 | uint8_t Mscale = MFS_4G; // mag full scale |
zmoutaou | 0:70465b25c44f | 77 | uint8_t Modr = MODR_10Hz; // mag data sample rate |
zmoutaou | 0:70465b25c44f | 78 | uint8_t Mmode = MMode_HighPerformance; // magnetometer operation mode |
zmoutaou | 0:70465b25c44f | 79 | float aRes, gRes, mRes; // scale resolutions per LSB for the sensors |
zmoutaou | 0:70465b25c44f | 80 | |
zmoutaou | 0:70465b25c44f | 81 | void getMres() |
zmoutaou | 0:70465b25c44f | 82 | { |
zmoutaou | 0:70465b25c44f | 83 | switch (Mscale) { |
zmoutaou | 0:70465b25c44f | 84 | // Possible magnetometer scales (and their register bit settings) are: |
zmoutaou | 0:70465b25c44f | 85 | // 4 Gauss (00), 8 Gauss (01), 12 Gauss (10) and 16 Gauss (11) |
zmoutaou | 0:70465b25c44f | 86 | case MFS_4G: |
zmoutaou | 0:70465b25c44f | 87 | mRes = 4.0/32768.0; |
zmoutaou | 0:70465b25c44f | 88 | break; |
zmoutaou | 0:70465b25c44f | 89 | case MFS_8G: |
zmoutaou | 0:70465b25c44f | 90 | mRes = 8.0/32768.0; |
zmoutaou | 0:70465b25c44f | 91 | break; |
zmoutaou | 0:70465b25c44f | 92 | case MFS_12G: |
zmoutaou | 0:70465b25c44f | 93 | mRes = 12.0/32768.0; |
zmoutaou | 0:70465b25c44f | 94 | break; |
zmoutaou | 0:70465b25c44f | 95 | case MFS_16G: |
zmoutaou | 0:70465b25c44f | 96 | mRes = 16.0/32768.0; |
zmoutaou | 0:70465b25c44f | 97 | break; |
zmoutaou | 0:70465b25c44f | 98 | } |
zmoutaou | 0:70465b25c44f | 99 | } |
zmoutaou | 0:70465b25c44f | 100 | |
zmoutaou | 0:70465b25c44f | 101 | |
zmoutaou | 0:70465b25c44f | 102 | |
zmoutaou | 0:70465b25c44f | 103 | void getGres() |
zmoutaou | 0:70465b25c44f | 104 | { |
zmoutaou | 0:70465b25c44f | 105 | switch (Gscale) { |
zmoutaou | 0:70465b25c44f | 106 | // Possible gyro scales (and their register bit settings) are: |
zmoutaou | 0:70465b25c44f | 107 | // 245 DPS (00), 500 DPS (01), and 2000 DPS (11). |
zmoutaou | 0:70465b25c44f | 108 | case GFS_245DPS: |
zmoutaou | 0:70465b25c44f | 109 | gRes = 245.0/32768.0;//2^15 |
zmoutaou | 0:70465b25c44f | 110 | break; |
zmoutaou | 0:70465b25c44f | 111 | case GFS_500DPS: |
zmoutaou | 0:70465b25c44f | 112 | gRes = 500.0/32768.0; |
zmoutaou | 0:70465b25c44f | 113 | break; |
zmoutaou | 0:70465b25c44f | 114 | case GFS_2000DPS: |
zmoutaou | 0:70465b25c44f | 115 | gRes = 2000.0/32768.0; |
zmoutaou | 0:70465b25c44f | 116 | break; |
zmoutaou | 0:70465b25c44f | 117 | } |
zmoutaou | 0:70465b25c44f | 118 | } |
zmoutaou | 0:70465b25c44f | 119 | |
zmoutaou | 0:70465b25c44f | 120 | |
zmoutaou | 0:70465b25c44f | 121 | |
zmoutaou | 0:70465b25c44f | 122 | void getAres() |
zmoutaou | 0:70465b25c44f | 123 | { |
zmoutaou | 0:70465b25c44f | 124 | switch (Ascale) { |
zmoutaou | 0:70465b25c44f | 125 | // Possible accelerometer scales (and their register bit settings) are: |
zmoutaou | 0:70465b25c44f | 126 | // 2 Gs (00), 16 Gs (01), 4 Gs (10), and 8 Gs (11). |
zmoutaou | 0:70465b25c44f | 127 | case AFS_2G: |
zmoutaou | 0:70465b25c44f | 128 | aRes = 2.0/32768.0; |
zmoutaou | 0:70465b25c44f | 129 | break; |
zmoutaou | 0:70465b25c44f | 130 | case AFS_16G: |
zmoutaou | 0:70465b25c44f | 131 | aRes = 16.0/32768.0; |
zmoutaou | 0:70465b25c44f | 132 | break; |
zmoutaou | 0:70465b25c44f | 133 | case AFS_4G: |
zmoutaou | 0:70465b25c44f | 134 | aRes = 4.0/32768.0; |
zmoutaou | 0:70465b25c44f | 135 | break; |
zmoutaou | 0:70465b25c44f | 136 | case AFS_8G: |
zmoutaou | 0:70465b25c44f | 137 | aRes = 8.0/32768.0; |
zmoutaou | 0:70465b25c44f | 138 | break; |
zmoutaou | 0:70465b25c44f | 139 | } |
zmoutaou | 0:70465b25c44f | 140 | } |
zmoutaou | 0:70465b25c44f | 141 | |
zmoutaou | 0:70465b25c44f | 142 | |
zmoutaou | 0:70465b25c44f | 143 | void writeByte(uint8_t address, uint8_t subAddress, uint8_t data) |
zmoutaou | 0:70465b25c44f | 144 | { |
zmoutaou | 0:70465b25c44f | 145 | char temp_data[2] = {subAddress, data}; |
zmoutaou | 0:70465b25c44f | 146 | i2c_m.write(address, temp_data, 2); |
zmoutaou | 0:70465b25c44f | 147 | } |
zmoutaou | 0:70465b25c44f | 148 | |
zmoutaou | 0:70465b25c44f | 149 | uint8_t readByte(uint8_t address, uint8_t subAddress) |
zmoutaou | 0:70465b25c44f | 150 | { |
zmoutaou | 0:70465b25c44f | 151 | char data; |
zmoutaou | 0:70465b25c44f | 152 | char temp[1] = {subAddress}; |
zmoutaou | 0:70465b25c44f | 153 | i2c_m.write(address, temp, 1); |
zmoutaou | 0:70465b25c44f | 154 | temp[1] = 0x00; |
zmoutaou | 0:70465b25c44f | 155 | i2c_m.write(address, temp, 1); |
zmoutaou | 0:70465b25c44f | 156 | int a = i2c_m.read(address, &data, 1); |
zmoutaou | 0:70465b25c44f | 157 | return data; |
zmoutaou | 0:70465b25c44f | 158 | |
zmoutaou | 0:70465b25c44f | 159 | } |
zmoutaou | 0:70465b25c44f | 160 | |
zmoutaou | 0:70465b25c44f | 161 | void readBytes(uint8_t address, uint8_t subAddress, uint8_t count, uint8_t * dest) |
zmoutaou | 0:70465b25c44f | 162 | { |
zmoutaou | 0:70465b25c44f | 163 | |
zmoutaou | 0:70465b25c44f | 164 | int i; |
zmoutaou | 0:70465b25c44f | 165 | char temp_dest[count]; |
zmoutaou | 0:70465b25c44f | 166 | char temp[1] = {subAddress}; |
zmoutaou | 0:70465b25c44f | 167 | i2c_m.write(address, temp, 1); |
zmoutaou | 0:70465b25c44f | 168 | i2c_m.read(address, temp_dest, count); |
zmoutaou | 0:70465b25c44f | 169 | for (i=0; i < count; i++) { |
zmoutaou | 0:70465b25c44f | 170 | dest[i] = temp_dest[i]; |
zmoutaou | 0:70465b25c44f | 171 | } |
zmoutaou | 0:70465b25c44f | 172 | } |
zmoutaou | 0:70465b25c44f | 173 | |
zmoutaou | 0:70465b25c44f | 174 | |
zmoutaou | 0:70465b25c44f | 175 | void accelgyrocalLSM9DS1(float * dest1, float * dest2) |
zmoutaou | 0:70465b25c44f | 176 | { |
zmoutaou | 0:70465b25c44f | 177 | uint8_t data[6] = {0}; |
zmoutaou | 0:70465b25c44f | 178 | int32_t gyro_bias[3] = {0, 0, 0}, accel_bias[3] = {0, 0, 0}; |
zmoutaou | 0:70465b25c44f | 179 | uint16_t samples, ii; |
zmoutaou | 0:70465b25c44f | 180 | writeByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_CTRL_REG4, 0x38); // enable the 3-axes of the gyroscope |
zmoutaou | 0:70465b25c44f | 181 | writeByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_CTRL_REG1_G, Godr << 5 | Gscale << 3 | Gbw); // configure the gyroscope |
zmoutaou | 0:70465b25c44f | 182 | wait(0.2); |
zmoutaou | 0:70465b25c44f | 183 | writeByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_CTRL_REG5_XL, 0x38); // enable the three axes of the accelerometer |
zmoutaou | 0:70465b25c44f | 184 | writeByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_CTRL_REG6_XL, Aodr << 5 | Ascale << 3 | 0x04 |Abw); // configure the accelerometer-specify bandwidth selection with Abw |
zmoutaou | 0:70465b25c44f | 185 | wait(0.2); |
zmoutaou | 0:70465b25c44f | 186 | writeByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_CTRL_REG8, 0x44);// enable block data update, allow auto-increment during multiple byte read |
zmoutaou | 0:70465b25c44f | 187 | uint8_t c = readByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_CTRL_REG9);// First get gyro bias |
zmoutaou | 0:70465b25c44f | 188 | writeByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_CTRL_REG9, (c & 0xFD)| 0x02); // Enable gyro FIFO |
zmoutaou | 0:70465b25c44f | 189 | wait(0.050); // Wait for change to take effect |
zmoutaou | 0:70465b25c44f | 190 | writeByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_FIFO_CTRL, 0x20 | 0x1F); // Enable gyro FIFO stream mode and set watermark at 32 samples |
zmoutaou | 0:70465b25c44f | 191 | wait(1); // delay 1000 milliseconds to collect FIFO samples |
zmoutaou | 0:70465b25c44f | 192 | samples = (readByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_FIFO_SRC) & 0x2F); // Read number of stored samples |
zmoutaou | 0:70465b25c44f | 193 | for(ii = 0; ii < samples ; ii++) { |
zmoutaou | 0:70465b25c44f | 194 | // Read the gyro data stored in the FIFO |
zmoutaou | 0:70465b25c44f | 195 | int16_t gyro_temp[3] = {0, 0, 0}; |
zmoutaou | 0:70465b25c44f | 196 | readBytes(LSM9DS1XG_ADDRESS, LSM9DS1XG_OUT_X_L_G, 6, &data[0]); |
zmoutaou | 0:70465b25c44f | 197 | gyro_temp[0] = (int16_t) (((int16_t)data[1] << 8) | data[0]); // Form signed 16-bit integer for each sample in FIFO |
zmoutaou | 0:70465b25c44f | 198 | gyro_temp[1] = (int16_t) (((int16_t)data[3] << 8) | data[2]); |
zmoutaou | 0:70465b25c44f | 199 | gyro_temp[2] = (int16_t) (((int16_t)data[5] << 8) | data[4]); |
zmoutaou | 0:70465b25c44f | 200 | |
zmoutaou | 0:70465b25c44f | 201 | gyro_bias[0] += (int32_t) gyro_temp[0]; // Sum individual signed 16-bit biases to get accumulated signed 32-bit biases |
zmoutaou | 0:70465b25c44f | 202 | gyro_bias[1] += (int32_t) gyro_temp[1]; |
zmoutaou | 0:70465b25c44f | 203 | gyro_bias[2] += (int32_t) gyro_temp[2]; |
zmoutaou | 0:70465b25c44f | 204 | } |
zmoutaou | 0:70465b25c44f | 205 | |
zmoutaou | 0:70465b25c44f | 206 | gyro_bias[0] /= samples; // average the data |
zmoutaou | 0:70465b25c44f | 207 | gyro_bias[1] /= samples; |
zmoutaou | 0:70465b25c44f | 208 | gyro_bias[2] /= samples; |
zmoutaou | 0:70465b25c44f | 209 | |
zmoutaou | 0:70465b25c44f | 210 | dest1[0] = (float)gyro_bias[0]*gRes; // Properly scale the data to get deg/s |
zmoutaou | 0:70465b25c44f | 211 | dest1[1] = (float)gyro_bias[1]*gRes; |
zmoutaou | 0:70465b25c44f | 212 | dest1[2] = (float)gyro_bias[2]*gRes; |
zmoutaou | 0:70465b25c44f | 213 | |
zmoutaou | 0:70465b25c44f | 214 | c = readByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_CTRL_REG9); |
zmoutaou | 0:70465b25c44f | 215 | writeByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_CTRL_REG9, c & ~0x02); //Disable gyro FIFO |
zmoutaou | 0:70465b25c44f | 216 | wait(0.050); |
zmoutaou | 0:70465b25c44f | 217 | writeByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_FIFO_CTRL, 0x00); // Enable gyro bypass mode |
zmoutaou | 0:70465b25c44f | 218 | |
zmoutaou | 0:70465b25c44f | 219 | // now get the accelerometer bias |
zmoutaou | 0:70465b25c44f | 220 | c = readByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_CTRL_REG9); |
zmoutaou | 0:70465b25c44f | 221 | writeByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_CTRL_REG9, (c & 0xFD)| 0x02); // Enable accel FIFO |
zmoutaou | 0:70465b25c44f | 222 | wait(0.050); // Wait for change to take effect |
zmoutaou | 0:70465b25c44f | 223 | writeByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_FIFO_CTRL, 0x20 | 0x1F); // Enable accel FIFO stream mode and set watermark at 32 samples |
zmoutaou | 0:70465b25c44f | 224 | wait(1); // delay 1000 milliseconds to collect FIFO samples |
zmoutaou | 0:70465b25c44f | 225 | |
zmoutaou | 0:70465b25c44f | 226 | samples = (readByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_FIFO_SRC) & 0x2F); // Read number of stored samples |
zmoutaou | 0:70465b25c44f | 227 | |
zmoutaou | 0:70465b25c44f | 228 | for(ii = 0; ii < samples ; ii++) { // Read the accel data stored in the FIFO |
zmoutaou | 0:70465b25c44f | 229 | int16_t accel_temp[3] = {0, 0, 0}; |
zmoutaou | 0:70465b25c44f | 230 | readBytes(LSM9DS1XG_ADDRESS, LSM9DS1XG_OUT_X_L_XL, 6, &data[0]); |
zmoutaou | 0:70465b25c44f | 231 | accel_temp[0] = (int16_t) (((int16_t)data[1] << 8) | data[0]); // Form signed 16-bit integer for each sample in FIFO |
zmoutaou | 0:70465b25c44f | 232 | accel_temp[1] = (int16_t) (((int16_t)data[3] << 8) | data[2]); |
zmoutaou | 0:70465b25c44f | 233 | accel_temp[2] = (int16_t) (((int16_t)data[5] << 8) | data[4]); |
zmoutaou | 0:70465b25c44f | 234 | |
zmoutaou | 0:70465b25c44f | 235 | accel_bias[0] += (int32_t) accel_temp[0]; // Sum individual signed 16-bit biases to get accumulated signed 32-bit biases |
zmoutaou | 0:70465b25c44f | 236 | accel_bias[1] += (int32_t) accel_temp[1]; |
zmoutaou | 0:70465b25c44f | 237 | accel_bias[2] += (int32_t) accel_temp[2]; |
zmoutaou | 0:70465b25c44f | 238 | } |
zmoutaou | 0:70465b25c44f | 239 | |
zmoutaou | 0:70465b25c44f | 240 | accel_bias[0] /= samples; // average the data |
zmoutaou | 0:70465b25c44f | 241 | accel_bias[1] /= samples; |
zmoutaou | 0:70465b25c44f | 242 | accel_bias[2] /= samples; |
zmoutaou | 0:70465b25c44f | 243 | |
zmoutaou | 0:70465b25c44f | 244 | if(accel_bias[2] > 0L) { |
zmoutaou | 0:70465b25c44f | 245 | accel_bias[2] -= (int32_t) (1.0/aRes); // Remove gravity from the z-axis accelerometer bias calculation |
zmoutaou | 0:70465b25c44f | 246 | } else { |
zmoutaou | 0:70465b25c44f | 247 | accel_bias[2] += (int32_t) (1.0/aRes); |
zmoutaou | 0:70465b25c44f | 248 | } |
zmoutaou | 0:70465b25c44f | 249 | |
zmoutaou | 0:70465b25c44f | 250 | dest2[0] = (float)accel_bias[0]*aRes; // Properly scale the data to get g |
zmoutaou | 0:70465b25c44f | 251 | dest2[1] = (float)accel_bias[1]*aRes; |
zmoutaou | 0:70465b25c44f | 252 | dest2[2] = (float)accel_bias[2]*aRes; |
zmoutaou | 0:70465b25c44f | 253 | |
zmoutaou | 0:70465b25c44f | 254 | c = readByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_CTRL_REG9); |
zmoutaou | 0:70465b25c44f | 255 | writeByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_CTRL_REG9, c & ~0x02); //Disable accel FIFO |
zmoutaou | 0:70465b25c44f | 256 | wait(0.050); |
zmoutaou | 0:70465b25c44f | 257 | writeByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_FIFO_CTRL, 0x00); // Enable accel bypass mode*/ |
zmoutaou | 0:70465b25c44f | 258 | } |
zmoutaou | 0:70465b25c44f | 259 | |
zmoutaou | 0:70465b25c44f | 260 | void magcalLSM9DS1(float * dest1) |
zmoutaou | 0:70465b25c44f | 261 | { |
zmoutaou | 0:70465b25c44f | 262 | uint8_t data[6]; // data array to hold mag x, y, z, data |
zmoutaou | 0:70465b25c44f | 263 | uint16_t ii = 0, sample_count = 0; |
zmoutaou | 0:70465b25c44f | 264 | int32_t mag_bias[3] = {0, 0, 0}; |
zmoutaou | 0:70465b25c44f | 265 | int16_t mag_max[3] = {0, 0, 0}, mag_min[3] = {0, 0, 0}; |
zmoutaou | 0:70465b25c44f | 266 | |
zmoutaou | 0:70465b25c44f | 267 | // configure the magnetometer-enable temperature compensation of mag data |
zmoutaou | 0:70465b25c44f | 268 | writeByte(LSM9DS1M_ADDRESS, LSM9DS1M_CTRL_REG1_M, 0x80 | Mmode << 5 | Modr << 2); // select x,y-axis mode |
zmoutaou | 0:70465b25c44f | 269 | writeByte(LSM9DS1M_ADDRESS, LSM9DS1M_CTRL_REG2_M, Mscale << 5 ); // select mag full scale |
zmoutaou | 0:70465b25c44f | 270 | writeByte(LSM9DS1M_ADDRESS, LSM9DS1M_CTRL_REG3_M, 0x00 ); // continuous conversion mode |
zmoutaou | 0:70465b25c44f | 271 | writeByte(LSM9DS1M_ADDRESS, LSM9DS1M_CTRL_REG4_M, Mmode << 2 ); // select z-axis mode |
zmoutaou | 0:70465b25c44f | 272 | writeByte(LSM9DS1M_ADDRESS, LSM9DS1M_CTRL_REG5_M, 0x40 ); // select block update mode |
zmoutaou | 0:70465b25c44f | 273 | ////pc.printf("Mag Calibration: Wave device in a figure eight until done!\n"); |
zmoutaou | 0:70465b25c44f | 274 | wait(0.004); |
zmoutaou | 0:70465b25c44f | 275 | |
zmoutaou | 0:70465b25c44f | 276 | sample_count = 128; |
zmoutaou | 0:70465b25c44f | 277 | for(ii = 0; ii < sample_count; ii++) { |
zmoutaou | 0:70465b25c44f | 278 | int16_t mag_temp[3] = {0, 0, 0}; |
zmoutaou | 0:70465b25c44f | 279 | readBytes(LSM9DS1M_ADDRESS, LSM9DS1M_OUT_X_L_M, 6, &data[0]); // Read the six raw data registers into data array |
zmoutaou | 0:70465b25c44f | 280 | mag_temp[0] = (int16_t) (((int16_t)data[1] << 8) | data[0]) ; // Form signed 16-bit integer for each sample in FIFO |
zmoutaou | 0:70465b25c44f | 281 | mag_temp[1] = (int16_t) (((int16_t)data[3] << 8) | data[2]) ; |
zmoutaou | 0:70465b25c44f | 282 | mag_temp[2] = (int16_t) (((int16_t)data[5] << 8) | data[4]) ; |
zmoutaou | 0:70465b25c44f | 283 | for (int jj = 0; jj < 3; jj++) { |
zmoutaou | 0:70465b25c44f | 284 | if(mag_temp[jj] > mag_max[jj]) mag_max[jj] = mag_temp[jj]; |
zmoutaou | 0:70465b25c44f | 285 | if(mag_temp[jj] < mag_min[jj]) mag_min[jj] = mag_temp[jj]; |
zmoutaou | 0:70465b25c44f | 286 | } |
zmoutaou | 0:70465b25c44f | 287 | wait(0.105); // at 10 Hz ODR, new mag data is available every 100 ms |
zmoutaou | 0:70465b25c44f | 288 | } |
zmoutaou | 0:70465b25c44f | 289 | |
zmoutaou | 0:70465b25c44f | 290 | // ////pc.printf("mag x min/max:"); //pc.printfmag_max[0]); //pc.printfmag_min[0]); |
zmoutaou | 0:70465b25c44f | 291 | // ////pc.printf("mag y min/max:"); //pc.printfmag_max[1]); //pc.printfmag_min[1]); |
zmoutaou | 0:70465b25c44f | 292 | // ////pc.printf("mag z min/max:"); //pc.printfmag_max[2]); //pc.printfmag_min[2]); |
zmoutaou | 0:70465b25c44f | 293 | |
zmoutaou | 0:70465b25c44f | 294 | mag_bias[0] = (mag_max[0] + mag_min[0])/2; // get average x mag bias in counts |
zmoutaou | 0:70465b25c44f | 295 | mag_bias[1] = (mag_max[1] + mag_min[1])/2; // get average y mag bias in counts |
zmoutaou | 0:70465b25c44f | 296 | mag_bias[2] = (mag_max[2] + mag_min[2])/2; // get average z mag bias in counts |
zmoutaou | 0:70465b25c44f | 297 | |
zmoutaou | 0:70465b25c44f | 298 | dest1[0] = (float) mag_bias[0]*mRes; // save mag biases in G for main program |
zmoutaou | 0:70465b25c44f | 299 | dest1[1] = (float) mag_bias[1]*mRes; |
zmoutaou | 0:70465b25c44f | 300 | dest1[2] = (float) mag_bias[2]*mRes; |
zmoutaou | 0:70465b25c44f | 301 | |
zmoutaou | 0:70465b25c44f | 302 | //write biases to accelerometermagnetometer offset registers as counts); |
zmoutaou | 0:70465b25c44f | 303 | writeByte(LSM9DS1M_ADDRESS, LSM9DS1M_OFFSET_X_REG_L_M, (int16_t) mag_bias[0] & 0xFF); |
zmoutaou | 0:70465b25c44f | 304 | writeByte(LSM9DS1M_ADDRESS, LSM9DS1M_OFFSET_X_REG_H_M, ((int16_t)mag_bias[0] >> 8) & 0xFF); |
zmoutaou | 0:70465b25c44f | 305 | writeByte(LSM9DS1M_ADDRESS, LSM9DS1M_OFFSET_Y_REG_L_M, (int16_t) mag_bias[1] & 0xFF); |
zmoutaou | 0:70465b25c44f | 306 | writeByte(LSM9DS1M_ADDRESS, LSM9DS1M_OFFSET_Y_REG_H_M, ((int16_t)mag_bias[1] >> 8) & 0xFF); |
zmoutaou | 0:70465b25c44f | 307 | writeByte(LSM9DS1M_ADDRESS, LSM9DS1M_OFFSET_Z_REG_L_M, (int16_t) mag_bias[2] & 0xFF); |
zmoutaou | 0:70465b25c44f | 308 | writeByte(LSM9DS1M_ADDRESS, LSM9DS1M_OFFSET_Z_REG_H_M, ((int16_t)mag_bias[2] >> 8) & 0xFF); |
zmoutaou | 0:70465b25c44f | 309 | |
zmoutaou | 0:70465b25c44f | 310 | ////pc.printf("Mag Calibration done!\n"); |
zmoutaou | 0:70465b25c44f | 311 | } |
zmoutaou | 0:70465b25c44f | 312 | |
zmoutaou | 0:70465b25c44f | 313 | |
zmoutaou | 0:70465b25c44f | 314 | void readAccelData(int16_t * destination) |
zmoutaou | 0:70465b25c44f | 315 | { |
zmoutaou | 0:70465b25c44f | 316 | uint8_t rawData[6]; // x/y/z accel register data stored here |
zmoutaou | 0:70465b25c44f | 317 | readBytes(LSM9DS1XG_ADDRESS, LSM9DS1XG_OUT_X_L_XL, 6, &rawData[0]); // Read the six raw data registers into data array |
zmoutaou | 0:70465b25c44f | 318 | destination[0] = ((int16_t)rawData[1] << 8) | rawData[0] ; // Turn the MSB and LSB into a signed 16-bit value |
zmoutaou | 0:70465b25c44f | 319 | destination[1] = ((int16_t)rawData[3] << 8) | rawData[2] ; |
zmoutaou | 0:70465b25c44f | 320 | destination[2] = ((int16_t)rawData[5] << 8) | rawData[4] ; |
zmoutaou | 0:70465b25c44f | 321 | } |
zmoutaou | 0:70465b25c44f | 322 | |
zmoutaou | 0:70465b25c44f | 323 | |
zmoutaou | 0:70465b25c44f | 324 | void readGyroData(int16_t * destination) |
zmoutaou | 0:70465b25c44f | 325 | { |
zmoutaou | 0:70465b25c44f | 326 | uint8_t rawData[6]; // x/y/z gyro register data stored here |
zmoutaou | 0:70465b25c44f | 327 | readBytes(LSM9DS1XG_ADDRESS, LSM9DS1XG_OUT_X_L_G, 6, &rawData[0]); // Read the six raw data registers sequentially into data array |
zmoutaou | 0:70465b25c44f | 328 | destination[0] = ((int16_t)rawData[1] << 8) | rawData[0] ; // Turn the MSB and LSB into a signed 16-bit value |
zmoutaou | 0:70465b25c44f | 329 | destination[1] = ((int16_t)rawData[3] << 8) | rawData[2] ; |
zmoutaou | 0:70465b25c44f | 330 | destination[2] = ((int16_t)rawData[5] << 8) | rawData[4] ; |
zmoutaou | 0:70465b25c44f | 331 | } |
zmoutaou | 0:70465b25c44f | 332 | |
zmoutaou | 0:70465b25c44f | 333 | void readMagData(int16_t * destination) |
zmoutaou | 0:70465b25c44f | 334 | { |
zmoutaou | 0:70465b25c44f | 335 | uint8_t rawData[6]; // x/y/z gyro register data stored here |
zmoutaou | 0:70465b25c44f | 336 | readBytes(LSM9DS1M_ADDRESS, LSM9DS1M_OUT_X_L_M, 6, &rawData[0]); // Read the six raw data registers sequentially into data array |
zmoutaou | 0:70465b25c44f | 337 | destination[0] = ((int16_t)rawData[1] << 8) | rawData[0] ; // Turn the MSB and LSB into a signed 16-bit value |
zmoutaou | 0:70465b25c44f | 338 | destination[1] = ((int16_t)rawData[3] << 8) | rawData[2] ; // Data stored as little Endian |
zmoutaou | 0:70465b25c44f | 339 | destination[2] = ((int16_t)rawData[5] << 8) | rawData[4] ; |
zmoutaou | 0:70465b25c44f | 340 | } |
zmoutaou | 0:70465b25c44f | 341 | void MadgwickQuaternionUpdate(float ax, float ay, float az, float gx, float gy, float gz, float mx, float my, float mz) |
zmoutaou | 0:70465b25c44f | 342 | { |
zmoutaou | 0:70465b25c44f | 343 | float q1 = q[0], q2 = q[1], q3 = q[2], q4 = q[3]; // short name local variable for readability |
zmoutaou | 0:70465b25c44f | 344 | float norm; |
zmoutaou | 0:70465b25c44f | 345 | float hx, hy, bx, bz; |
zmoutaou | 0:70465b25c44f | 346 | float vx, vy, vz, wx, wy, wz; |
zmoutaou | 0:70465b25c44f | 347 | float ex, ey, ez; |
zmoutaou | 0:70465b25c44f | 348 | float pa, pb, pc; |
zmoutaou | 0:70465b25c44f | 349 | |
zmoutaou | 0:70465b25c44f | 350 | // Auxiliary variables to avoid repeated arithmetic |
zmoutaou | 0:70465b25c44f | 351 | float q1q1 = q1 * q1; |
zmoutaou | 0:70465b25c44f | 352 | float q1q2 = q1 * q2; |
zmoutaou | 0:70465b25c44f | 353 | float q1q3 = q1 * q3; |
zmoutaou | 0:70465b25c44f | 354 | float q1q4 = q1 * q4; |
zmoutaou | 0:70465b25c44f | 355 | float q2q2 = q2 * q2; |
zmoutaou | 0:70465b25c44f | 356 | float q2q3 = q2 * q3; |
zmoutaou | 0:70465b25c44f | 357 | float q2q4 = q2 * q4; |
zmoutaou | 0:70465b25c44f | 358 | float q3q3 = q3 * q3; |
zmoutaou | 0:70465b25c44f | 359 | float q3q4 = q3 * q4; |
zmoutaou | 0:70465b25c44f | 360 | float q4q4 = q4 * q4; |
zmoutaou | 0:70465b25c44f | 361 | |
zmoutaou | 0:70465b25c44f | 362 | // Normalise accelerometer measurement |
zmoutaou | 0:70465b25c44f | 363 | norm = sqrtf(ax * ax + ay * ay + az * az); |
zmoutaou | 0:70465b25c44f | 364 | if (norm == 0.0f) return; // handle NaN |
zmoutaou | 0:70465b25c44f | 365 | norm = 1.0f / norm; // use reciprocal for division |
zmoutaou | 0:70465b25c44f | 366 | ax *= norm; |
zmoutaou | 0:70465b25c44f | 367 | ay *= norm; |
zmoutaou | 0:70465b25c44f | 368 | az *= norm; |
zmoutaou | 0:70465b25c44f | 369 | |
zmoutaou | 0:70465b25c44f | 370 | // Normalise magnetometer measurement |
zmoutaou | 0:70465b25c44f | 371 | norm = sqrtf(mx * mx + my * my + mz * mz); |
zmoutaou | 0:70465b25c44f | 372 | if (norm == 0.0f) return; // handle NaN |
zmoutaou | 0:70465b25c44f | 373 | norm = 1.0f / norm; // use reciprocal for division |
zmoutaou | 0:70465b25c44f | 374 | mx *= norm; |
zmoutaou | 0:70465b25c44f | 375 | my *= norm; |
zmoutaou | 0:70465b25c44f | 376 | mz *= norm; |
zmoutaou | 0:70465b25c44f | 377 | |
zmoutaou | 0:70465b25c44f | 378 | // Reference direction of Earth's magnetic field |
zmoutaou | 0:70465b25c44f | 379 | hx = 2.0f * mx * (0.5f - q3q3 - q4q4) + 2.0f * my * (q2q3 - q1q4) + 2.0f * mz * (q2q4 + q1q3); |
zmoutaou | 0:70465b25c44f | 380 | hy = 2.0f * mx * (q2q3 + q1q4) + 2.0f * my * (0.5f - q2q2 - q4q4) + 2.0f * mz * (q3q4 - q1q2); |
zmoutaou | 0:70465b25c44f | 381 | bx = sqrtf((hx * hx) + (hy * hy)); |
zmoutaou | 0:70465b25c44f | 382 | bz = 2.0f * mx * (q2q4 - q1q3) + 2.0f * my * (q3q4 + q1q2) + 2.0f * mz * (0.5f - q2q2 - q3q3); |
zmoutaou | 0:70465b25c44f | 383 | |
zmoutaou | 0:70465b25c44f | 384 | // Estimated direction of gravity and magnetic field |
zmoutaou | 0:70465b25c44f | 385 | vx = 2.0f * (q2q4 - q1q3); |
zmoutaou | 0:70465b25c44f | 386 | vy = 2.0f * (q1q2 + q3q4); |
zmoutaou | 0:70465b25c44f | 387 | vz = q1q1 - q2q2 - q3q3 + q4q4; |
zmoutaou | 0:70465b25c44f | 388 | wx = 2.0f * bx * (0.5f - q3q3 - q4q4) + 2.0f * bz * (q2q4 - q1q3); |
zmoutaou | 0:70465b25c44f | 389 | wy = 2.0f * bx * (q2q3 - q1q4) + 2.0f * bz * (q1q2 + q3q4); |
zmoutaou | 0:70465b25c44f | 390 | wz = 2.0f * bx * (q1q3 + q2q4) + 2.0f * bz * (0.5f - q2q2 - q3q3); |
zmoutaou | 0:70465b25c44f | 391 | |
zmoutaou | 0:70465b25c44f | 392 | // Error is cross product between estimated direction and measured direction of gravity |
zmoutaou | 0:70465b25c44f | 393 | ex = (ay * vz - az * vy) + (my * wz - mz * wy); |
zmoutaou | 0:70465b25c44f | 394 | ey = (az * vx - ax * vz) + (mz * wx - mx * wz); |
zmoutaou | 0:70465b25c44f | 395 | ez = (ax * vy - ay * vx) + (mx * wy - my * wx); |
zmoutaou | 0:70465b25c44f | 396 | if (Ki > 0.0f) { |
zmoutaou | 0:70465b25c44f | 397 | eInt[0] += ex; // accumulate integral error |
zmoutaou | 0:70465b25c44f | 398 | eInt[1] += ey; |
zmoutaou | 0:70465b25c44f | 399 | eInt[2] += ez; |
zmoutaou | 0:70465b25c44f | 400 | } else { |
zmoutaou | 0:70465b25c44f | 401 | eInt[0] = 0.0f; // prevent integral wind up |
zmoutaou | 0:70465b25c44f | 402 | eInt[1] = 0.0f; |
zmoutaou | 0:70465b25c44f | 403 | eInt[2] = 0.0f; |
zmoutaou | 0:70465b25c44f | 404 | } |
zmoutaou | 0:70465b25c44f | 405 | |
zmoutaou | 0:70465b25c44f | 406 | // Apply feedback terms |
zmoutaou | 0:70465b25c44f | 407 | gx = gx + Kp * ex + Ki * eInt[0]; |
zmoutaou | 0:70465b25c44f | 408 | gy = gy + Kp * ey + Ki * eInt[1]; |
zmoutaou | 0:70465b25c44f | 409 | gz = gz + Kp * ez + Ki * eInt[2]; |
zmoutaou | 0:70465b25c44f | 410 | |
zmoutaou | 0:70465b25c44f | 411 | // Integrate rate of change of quaternion |
zmoutaou | 0:70465b25c44f | 412 | pa = q2; |
zmoutaou | 0:70465b25c44f | 413 | pb = q3; |
zmoutaou | 0:70465b25c44f | 414 | pc = q4; |
zmoutaou | 0:70465b25c44f | 415 | q1 = q1 + (-q2 * gx - q3 * gy - q4 * gz) * (0.5f * deltat); |
zmoutaou | 0:70465b25c44f | 416 | q2 = pa + (q1 * gx + pb * gz - pc * gy) * (0.5f * deltat); |
zmoutaou | 0:70465b25c44f | 417 | q3 = pb + (q1 * gy - pa * gz + pc * gx) * (0.5f * deltat); |
zmoutaou | 0:70465b25c44f | 418 | q4 = pc + (q1 * gz + pa * gy - pb * gx) * (0.5f * deltat); |
zmoutaou | 0:70465b25c44f | 419 | |
zmoutaou | 0:70465b25c44f | 420 | // Normalise quaternion |
zmoutaou | 0:70465b25c44f | 421 | norm = sqrtf(q1 * q1 + q2 * q2 + q3 * q3 + q4 * q4); |
zmoutaou | 0:70465b25c44f | 422 | norm = 1.0f / norm; |
zmoutaou | 0:70465b25c44f | 423 | q[0] = q1 * norm; |
zmoutaou | 0:70465b25c44f | 424 | q[1] = q2 * norm; |
zmoutaou | 0:70465b25c44f | 425 | q[2] = q3 * norm; |
zmoutaou | 0:70465b25c44f | 426 | q[3] = q4 * norm; |
zmoutaou | 0:70465b25c44f | 427 | } |
zmoutaou | 0:70465b25c44f | 428 | |
zmoutaou | 0:70465b25c44f | 429 | |
zmoutaou | 0:70465b25c44f | 430 | int16_t readTempData() |
zmoutaou | 0:70465b25c44f | 431 | { |
zmoutaou | 0:70465b25c44f | 432 | uint8_t rawData[2]; // x/y/z gyro register data stored here |
zmoutaou | 0:70465b25c44f | 433 | readBytes(LSM9DS1XG_ADDRESS, LSM9DS1XG_OUT_TEMP_L, 2, &rawData[0]); // Read the two raw data registers sequentially into data array |
zmoutaou | 0:70465b25c44f | 434 | return (((int16_t)rawData[1] << 8) | rawData[0]); // Turn the MSB and LSB into a 16-bit signed value |
zmoutaou | 0:70465b25c44f | 435 | } |
zmoutaou | 0:70465b25c44f | 436 | void initLSM9DS1() |
zmoutaou | 0:70465b25c44f | 437 | { |
zmoutaou | 0:70465b25c44f | 438 | // enable the 3-axes of the gyroscope |
zmoutaou | 0:70465b25c44f | 439 | writeByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_CTRL_REG4, 0x38); |
zmoutaou | 0:70465b25c44f | 440 | ////pc.printf( "enable the 3-axes of the gyroscope\n"); |
zmoutaou | 0:70465b25c44f | 441 | // configure the gyroscope |
zmoutaou | 0:70465b25c44f | 442 | writeByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_CTRL_REG1_G, Godr << 5 | Gscale << 3 | Gbw); |
zmoutaou | 0:70465b25c44f | 443 | ////pc.printf("// configure the gyroscope\n"); |
zmoutaou | 0:70465b25c44f | 444 | wait(0.2); |
zmoutaou | 0:70465b25c44f | 445 | // enable the three axes of the accelerometer |
zmoutaou | 0:70465b25c44f | 446 | writeByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_CTRL_REG5_XL, 0x38); |
zmoutaou | 0:70465b25c44f | 447 | ////pc.printf("// enable the three axes of the accelerometer\n ") ; |
zmoutaou | 0:70465b25c44f | 448 | // configure the accelerometer-specify bandwidth selection with Abw |
zmoutaou | 0:70465b25c44f | 449 | writeByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_CTRL_REG6_XL, Aodr << 5 | Ascale << 3 | 0x04 |Abw); |
zmoutaou | 0:70465b25c44f | 450 | ////pc.printf("configure the accelerometer-specify bandwidth selection with Abw\n"); |
zmoutaou | 0:70465b25c44f | 451 | wait(0.2); |
zmoutaou | 0:70465b25c44f | 452 | // enable block data update, allow auto-increment during multiple byte read |
zmoutaou | 0:70465b25c44f | 453 | writeByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_CTRL_REG8, 0x44); |
zmoutaou | 0:70465b25c44f | 454 | ////pc.printf("enable block data update, allow auto-increment during multiple byte read\n"); |
zmoutaou | 0:70465b25c44f | 455 | // configure the magnetometer-enable temperature compensation of mag data |
zmoutaou | 0:70465b25c44f | 456 | writeByte(LSM9DS1M_ADDRESS, LSM9DS1M_CTRL_REG1_M, 0x80 | Mmode << 5 | Modr << 2); // select x,y-axis mode |
zmoutaou | 0:70465b25c44f | 457 | ////pc.printf("configure the magnetometer-enable temperature compensation of mag data\n"); |
zmoutaou | 0:70465b25c44f | 458 | writeByte(LSM9DS1M_ADDRESS, LSM9DS1M_CTRL_REG2_M, Mscale << 5 ); // select mag full scale |
zmoutaou | 0:70465b25c44f | 459 | writeByte(LSM9DS1M_ADDRESS, LSM9DS1M_CTRL_REG3_M, 0x00 ); // continuous conversion mode |
zmoutaou | 0:70465b25c44f | 460 | writeByte(LSM9DS1M_ADDRESS, LSM9DS1M_CTRL_REG4_M, Mmode << 2 ); // select z-axis mode |
zmoutaou | 0:70465b25c44f | 461 | writeByte(LSM9DS1M_ADDRESS, LSM9DS1M_CTRL_REG5_M, 0x40 ); // select block update mode |
zmoutaou | 0:70465b25c44f | 462 | } |
zmoutaou | 0:70465b25c44f | 463 | |
zmoutaou | 0:70465b25c44f | 464 | void selftestLSM9DS1() |
zmoutaou | 0:70465b25c44f | 465 | { |
zmoutaou | 0:70465b25c44f | 466 | float accel_noST[3] = {0., 0., 0.}, accel_ST[3] = {0., 0., 0.}; |
zmoutaou | 0:70465b25c44f | 467 | float gyro_noST[3] = {0., 0., 0.}, gyro_ST[3] = {0., 0., 0.}; |
zmoutaou | 0:70465b25c44f | 468 | writeByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_CTRL_REG10, 0x00); // disable self test |
zmoutaou | 0:70465b25c44f | 469 | accelgyrocalLSM9DS1(gyro_noST, accel_noST); |
zmoutaou | 0:70465b25c44f | 470 | ////pc.printf("disable self test "); |
zmoutaou | 0:70465b25c44f | 471 | writeByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_CTRL_REG10, 0x05); // enable gyro/accel self test |
zmoutaou | 0:70465b25c44f | 472 | accelgyrocalLSM9DS1(gyro_ST, accel_ST); |
zmoutaou | 0:70465b25c44f | 473 | ////pc.printf("enable gyro/accel self test"); |
zmoutaou | 0:70465b25c44f | 474 | |
zmoutaou | 0:70465b25c44f | 475 | float gyrodx = (gyro_ST[0] - gyro_noST[0]); |
zmoutaou | 0:70465b25c44f | 476 | float gyrody = (gyro_ST[1] - gyro_noST[1]); |
zmoutaou | 0:70465b25c44f | 477 | float gyrodz = (gyro_ST[2] - gyro_noST[2]); |
zmoutaou | 0:70465b25c44f | 478 | |
zmoutaou | 0:70465b25c44f | 479 | ////pc.printf("Gyro self-test results: "); |
zmoutaou | 0:70465b25c44f | 480 | ////pc.printf("x-axis = %f , dps" ,gyrodx); //////////pc.printf(" should be between 20 and 250 dps \n"); |
zmoutaou | 0:70465b25c44f | 481 | ////pc.printf("y-axis = %f ",gyrody); //////////pc.printf(" dps"); //////pc.printf(" should be between 20 and 250 dps \n"); |
zmoutaou | 0:70465b25c44f | 482 | ////pc.printf("z-axis = %f ",gyrodz); //////////pc.printf(" dps"); //////pc.printf(" should be between 20 and 250 dps \n"); |
zmoutaou | 0:70465b25c44f | 483 | |
zmoutaou | 0:70465b25c44f | 484 | float accdx = 1000.*(accel_ST[0] - accel_noST[0]); |
zmoutaou | 0:70465b25c44f | 485 | float accdy = 1000.*(accel_ST[1] - accel_noST[1]); |
zmoutaou | 0:70465b25c44f | 486 | float accdz = 1000.*(accel_ST[2] - accel_noST[2]); |
zmoutaou | 0:70465b25c44f | 487 | //pc.printf( "%f,%f,%f,%f,%f,%f\n", gyrodx,gyrody,gyrodz,accdx,accdy,accdz); |
zmoutaou | 0:70465b25c44f | 488 | ////pc.printf("Accelerometer self-test results: "); |
zmoutaou | 0:70465b25c44f | 489 | ////pc.printf("x-axis = %f" , accdx); //////////pc.printf(" mg"); //////pc.printf(" should be between 60 and 1700 mg \n"); |
zmoutaou | 0:70465b25c44f | 490 | ////pc.printf("y-axis = %f" , accdy); //////////pc.printf(" mg"); //////pc.printf(" should be between 60 and 1700 mg \n"); |
zmoutaou | 0:70465b25c44f | 491 | ////pc.printf("z-axis = %f", accdz); ////////pc.printf(" mg"); //////pc.printf(" should be between 60 and 1700 mg \n"); |
zmoutaou | 0:70465b25c44f | 492 | |
zmoutaou | 0:70465b25c44f | 493 | writeByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_CTRL_REG10, 0x00); // disable self test |
zmoutaou | 0:70465b25c44f | 494 | |
zmoutaou | 0:70465b25c44f | 495 | wait(0.2); |
zmoutaou | 0:70465b25c44f | 496 | |
zmoutaou | 0:70465b25c44f | 497 | } |
zmoutaou | 0:70465b25c44f | 498 | |
zmoutaou | 0:70465b25c44f | 499 | SDFileSystem sd(PA_7, PA_6, PA_5, PB_6, "sd"); |
zmoutaou | 0:70465b25c44f | 500 | int main () |
zmoutaou | 0:70465b25c44f | 501 | { |
zmoutaou | 0:70465b25c44f | 502 | FILE *fp= fopen("/sd/valeur_ble.txt", "a"); |
zmoutaou | 0:70465b25c44f | 503 | wait(1); |
zmoutaou | 0:70465b25c44f | 504 | bool erreur; //pc.printf("LSM9DS1 9-axis motion sensor...\n"); |
zmoutaou | 0:70465b25c44f | 505 | uint8_t c = readByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_WHO_AM_I); // Read WHO_AM_I register for LSM9DS1 accel/gyro//pc.printf("LSM9DS1 accel/gyro % c ", c); ////////pc.printf("I AM %x",c ); ////////pc.printf(" I should be 0x68 \n"); |
zmoutaou | 0:70465b25c44f | 506 | uint8_t d = readByte(LSM9DS1M_ADDRESS, LSM9DS1M_WHO_AM_I); // Read WHO_AM_I register for LSM9DS1 magnetometer//pc.printf("LSM9DS1 magnetometer % d"); ////////pc.printf("I AM %x",d); ////////pc.printf(" I should be 0x3D\n"); |
zmoutaou | 0:70465b25c44f | 507 | if (c == 0x68 && d == 0x3D) { // WHO_AM_I should always be 0x0E for the accel/gyro and 0x3C for the mag |
zmoutaou | 0:70465b25c44f | 508 | ////pc.printf("LSM9DS1 is online...\n"); // get sensor resolutions, only need to do this once |
zmoutaou | 0:70465b25c44f | 509 | getAres();////////pc.printf("accel sensitivity is %f .",1./(1000.*aRes)); //////////////pc.printf(" LSB/mg"); |
zmoutaou | 0:70465b25c44f | 510 | getGres();////////pc.printf("gyro sensitivity is %f ." ,1./(1000.*gRes)); //////////////pc.printf(" LSB/mdps"); |
zmoutaou | 0:70465b25c44f | 511 | getMres();////////pc.printf("mag sensitivity is %f .", 1./(1000.*mRes)); //////////////pc.printf(" LSB/mGauss"); |
zmoutaou | 0:70465b25c44f | 512 | selftestLSM9DS1(); ////////pc.printf("Perform gyro and accel self test"); // check function of gyro and accelerometer via self test |
zmoutaou | 0:70465b25c44f | 513 | accelgyrocalLSM9DS1( gyroBias1, accelBias); // Calibrate gyro and accelerometers, load biases in bias registers////////pc.printf("accel biases (mg) %f %f %f \n",1000.*accelBias[0],1000.*accelBias[1],1000.*accelBias[2]);////////pc.printf("gyro biases (dps) %f %f %f \n",gyroBias[0],gyroBias[1],gyroBias[2]); |
zmoutaou | 0:70465b25c44f | 514 | magcalLSM9DS1(magBias);////////pc.printf("mag biases (mG) %f %f %f \n",1000.*magBias[0],1000.*magBias[1],1000.*magBias[2]); |
zmoutaou | 0:70465b25c44f | 515 | wait(2); // add delay to see results before serial spew of data |
zmoutaou | 0:70465b25c44f | 516 | initLSM9DS1(); ////////pc.printf("LSM9DS1 initialized for active data mode...."); // Initialize device for active mode read of acclerometer, gyroscope, and temperature |
zmoutaou | 0:70465b25c44f | 517 | erreur = false ; |
zmoutaou | 0:70465b25c44f | 518 | } else { |
zmoutaou | 0:70465b25c44f | 519 | erreur = true ; |
zmoutaou | 0:70465b25c44f | 520 | } |
zmoutaou | 0:70465b25c44f | 521 | t.start(); |
zmoutaou | 0:70465b25c44f | 522 | while (erreur == false ) { |
zmoutaou | 0:70465b25c44f | 523 | |
zmoutaou | 0:70465b25c44f | 524 | firstUpdate = t.read_ms(); |
zmoutaou | 0:70465b25c44f | 525 | lastUpdate = firstUpdate; |
zmoutaou | 0:70465b25c44f | 526 | Now = t.read_ms(); |
zmoutaou | 0:70465b25c44f | 527 | lastUpdate = Now; |
zmoutaou | 0:70465b25c44f | 528 | |
zmoutaou | 0:70465b25c44f | 529 | if (readByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_STATUS_REG) & 0x01) { //Accelerometer new data available. // check if new accel data is ready |
zmoutaou | 0:70465b25c44f | 530 | readAccelData(accelCount); // Read the x/y/z adc values // Now we'll calculate the accleration value into actual g's |
zmoutaou | 0:70465b25c44f | 531 | ax = (float)accelCount[0]*aRes - accelBias[0]; // get actual g value, this depends on scale being set |
zmoutaou | 0:70465b25c44f | 532 | ay = (float)accelCount[1]*aRes - accelBias[1]; |
zmoutaou | 0:70465b25c44f | 533 | az = (float)accelCount[2]*aRes - accelBias[2]; |
zmoutaou | 0:70465b25c44f | 534 | } |
zmoutaou | 0:70465b25c44f | 535 | if (readByte(LSM9DS1XG_ADDRESS, LSM9DS1XG_STATUS_REG) & 0x02) { // check if new gyro data is ready |
zmoutaou | 0:70465b25c44f | 536 | readGyroData(gyroCount); // Read the x/y/z adc values // Calculate the gyro value into actual degrees per second |
zmoutaou | 0:70465b25c44f | 537 | gx = (float)gyroCount[0]*gRes - gyroBias1[0]; // get actual gyro value, this depends on scale being set |
zmoutaou | 0:70465b25c44f | 538 | gy = (float)gyroCount[1]*gRes - gyroBias1[1]; |
zmoutaou | 0:70465b25c44f | 539 | gz = (float)gyroCount[2]*gRes - gyroBias1[2]; |
zmoutaou | 0:70465b25c44f | 540 | } |
zmoutaou | 0:70465b25c44f | 541 | if (readByte(LSM9DS1M_ADDRESS, LSM9DS1M_STATUS_REG_M) & 0x08) { // check if new mag data is ready |
zmoutaou | 0:70465b25c44f | 542 | readMagData(magCount); // Read the x/y/z adc values |
zmoutaou | 0:70465b25c44f | 543 | mx = (float)magCount[0]*mRes; // - magBias[0]; // get actual magnetometer value, this depends on scale being set |
zmoutaou | 0:70465b25c44f | 544 | my = (float)magCount[1]*mRes; // - magBias[1]; |
zmoutaou | 0:70465b25c44f | 545 | mz = (float)magCount[2]*mRes; // - magBias[2];} |
zmoutaou | 0:70465b25c44f | 546 | } |
zmoutaou | 0:70465b25c44f | 547 | //MadgwickQuaternionUpdate( ay, ax, az, gy*PI/180.0f, gx*PI/180.0f, gz*PI/180.0f ); |
zmoutaou | 0:70465b25c44f | 548 | int nowMs = t.read_ms(); |
zmoutaou | 0:70465b25c44f | 549 | if( nowMs - lastPrint > printInterval ) { |
zmoutaou | 0:70465b25c44f | 550 | int nowMs = t.read_ms(); |
zmoutaou | 0:70465b25c44f | 551 | if( nowMs - lastPrint > printInterval ) { |
zmoutaou | 0:70465b25c44f | 552 | lastPrint = nowMs; |
zmoutaou | 0:70465b25c44f | 553 | pc.printf("%d %f,%f,%f,%f,%f,%f\n",nowMs,ax,ay,az,gx,gy,gz); |
zmoutaou | 0:70465b25c44f | 554 | //pc.printf("gyro: %f %f %f\n\r", gx, gy, gz); |
zmoutaou | 0:70465b25c44f | 555 | //pc.printf("accel: %f %f %f\n\r", ax, ay, az); |
zmoutaou | 0:70465b25c44f | 556 | //pc.printf("quat q0 qx qy qz: %f %f %f %f\n\r", q[0], q[1], q[2], q[3]); |
zmoutaou | 0:70465b25c44f | 557 | //yaw = atan2(2.0f * (q[1] * q[2] + q[0] * q[3]), q[0] * q[0] + q[1] * q[1] - q[2] * q[2] - q[3] * q[3]); |
zmoutaou | 0:70465b25c44f | 558 | //pitch = -asin(2.0f * (q[1] * q[3] - q[0] * q[2])); |
zmoutaou | 0:70465b25c44f | 559 | //roll = atan2(2.0f * (q[0] * q[1] + q[2] * q[3]), q[0] * q[0] - q[1] * q[1] - q[2] * q[2] + q[3] * q[3]); |
zmoutaou | 0:70465b25c44f | 560 | //pitch *= 180.0f / PI; |
zmoutaou | 0:70465b25c44f | 561 | //yaw *= 180.0f / PI; |
zmoutaou | 0:70465b25c44f | 562 | //yaw -= 13.8f; // Declination at Danville, California is 13 degrees 48 minutes and 47 seconds on 2014-04-04 ?????????????????????????????????????? |
zmoutaou | 0:70465b25c44f | 563 | //roll *= 180.0f / PI; |
zmoutaou | 0:70465b25c44f | 564 | } |
zmoutaou | 0:70465b25c44f | 565 | } |
zmoutaou | 0:70465b25c44f | 566 | } |
zmoutaou | 0:70465b25c44f | 567 | |
zmoutaou | 0:70465b25c44f | 568 | } |