Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of LSM9DS1_Library_cal by
LSM9DS1.cpp
00001 /****************************************************************************** 00002 SFE_LSM9DS1.cpp 00003 SFE_LSM9DS1 Library Source File 00004 Jim Lindblom @ SparkFun Electronics 00005 Original Creation Date: February 27, 2015 00006 https://github.com/sparkfun/LSM9DS1_Breakout 00007 00008 This file implements all functions of the LSM9DS1 class. Functions here range 00009 from higher level stuff, like reading/writing LSM9DS1 registers to low-level, 00010 hardware reads and writes. Both SPI and I2C handler functions can be found 00011 towards the bottom of this file. 00012 00013 Development environment specifics: 00014 IDE: Arduino 1.6 00015 Hardware Platform: Arduino Uno 00016 LSM9DS1 Breakout Version: 1.0 00017 00018 This code is beerware; if you see me (or any other SparkFun employee) at the 00019 local, and you've found our code helpful, please buy us a round! 00020 00021 Distributed as-is; no warranty is given. 00022 ******************************************************************************/ 00023 00024 #include "LSM9DS1.h" 00025 #include "LSM9DS1_Registers.h" 00026 #include "LSM9DS1_Types.h" 00027 //#include <Wire.h> // Wire library is used for I2C 00028 //#include <SPI.h> // SPI library is used for...SPI. 00029 00030 //#if defined(ARDUINO) && ARDUINO >= 100 00031 // #include "Arduino.h" 00032 //#else 00033 // #include "WProgram.h" 00034 //#endif 00035 00036 #define LSM9DS1_COMMUNICATION_TIMEOUT 1000 00037 00038 float magSensitivity[4] = {0.00014, 0.00029, 0.00043, 0.00058}; 00039 extern Serial pc; 00040 00041 LSM9DS1::LSM9DS1(PinName sda, PinName scl, uint8_t xgAddr, uint8_t mAddr) 00042 :i2c(sda, scl) 00043 { 00044 init(IMU_MODE_I2C, xgAddr, mAddr); // dont know about 0xD6 or 0x3B 00045 } 00046 /* 00047 LSM9DS1::LSM9DS1() 00048 { 00049 init(IMU_MODE_I2C, LSM9DS1_AG_ADDR(1), LSM9DS1_M_ADDR(1)); 00050 } 00051 00052 LSM9DS1::LSM9DS1(interface_mode interface, uint8_t xgAddr, uint8_t mAddr) 00053 { 00054 init(interface, xgAddr, mAddr); 00055 } 00056 */ 00057 00058 void LSM9DS1::init(interface_mode interface, uint8_t xgAddr, uint8_t mAddr) 00059 { 00060 settings.device.commInterface = interface; 00061 settings.device.agAddress = xgAddr; 00062 settings.device.mAddress = mAddr; 00063 00064 settings.gyro.enabled = true; 00065 settings.gyro.enableX = true; 00066 settings.gyro.enableY = true; 00067 settings.gyro.enableZ = true; 00068 // gyro scale can be 245, 500, or 2000 00069 settings.gyro.scale = 245; 00070 // gyro sample rate: value between 1-6 00071 // 1 = 14.9 4 = 238 00072 // 2 = 59.5 5 = 476 00073 // 3 = 119 6 = 952 00074 settings.gyro.sampleRate = 6; 00075 // gyro cutoff frequency: value between 0-3 00076 // Actual value of cutoff frequency depends 00077 // on sample rate. 00078 settings.gyro.bandwidth = 0; 00079 settings.gyro.lowPowerEnable = false; 00080 settings.gyro.HPFEnable = false; 00081 // Gyro HPF cutoff frequency: value between 0-9 00082 // Actual value depends on sample rate. Only applies 00083 // if gyroHPFEnable is true. 00084 settings.gyro.HPFCutoff = 0; 00085 settings.gyro.flipX = false; 00086 settings.gyro.flipY = false; 00087 settings.gyro.flipZ = false; 00088 settings.gyro.orientation = 0; 00089 settings.gyro.latchInterrupt = true; 00090 00091 settings.accel.enabled = true; 00092 settings.accel.enableX = true; 00093 settings.accel.enableY = true; 00094 settings.accel.enableZ = true; 00095 // accel scale can be 2, 4, 8, or 16 00096 settings.accel.scale = 2; 00097 // accel sample rate can be 1-6 00098 // 1 = 10 Hz 4 = 238 Hz 00099 // 2 = 50 Hz 5 = 476 Hz 00100 // 3 = 119 Hz 6 = 952 Hz 00101 settings.accel.sampleRate = 6; 00102 // Accel cutoff freqeuncy can be any value between -1 - 3. 00103 // -1 = bandwidth determined by sample rate 00104 // 0 = 408 Hz 2 = 105 Hz 00105 // 1 = 211 Hz 3 = 50 Hz 00106 settings.accel.bandwidth = -1; 00107 settings.accel.highResEnable = false; 00108 // accelHighResBandwidth can be any value between 0-3 00109 // LP cutoff is set to a factor of sample rate 00110 // 0 = ODR/50 2 = ODR/9 00111 // 1 = ODR/100 3 = ODR/400 00112 settings.accel.highResBandwidth = 0; 00113 00114 settings.mag.enabled = true; 00115 // mag scale can be 4, 8, 12, or 16 00116 settings.mag.scale = 4; 00117 // mag data rate can be 0-7 00118 // 0 = 0.625 Hz 4 = 10 Hz 00119 // 1 = 1.25 Hz 5 = 20 Hz 00120 // 2 = 2.5 Hz 6 = 40 Hz 00121 // 3 = 5 Hz 7 = 80 Hz 00122 settings.mag.sampleRate = 7; 00123 settings.mag.tempCompensationEnable = false; 00124 // magPerformance can be any value between 0-3 00125 // 0 = Low power mode 2 = high performance 00126 // 1 = medium performance 3 = ultra-high performance 00127 settings.mag.XYPerformance = 3; 00128 settings.mag.ZPerformance = 3; 00129 settings.mag.lowPowerEnable = false; 00130 // magOperatingMode can be 0-2 00131 // 0 = continuous conversion 00132 // 1 = single-conversion 00133 // 2 = power down 00134 settings.mag.operatingMode = 0; 00135 00136 settings.temp.enabled = true; 00137 for (int i=0; i<3; i++) { 00138 gBias[i] = 0; 00139 aBias[i] = 0; 00140 mBias[i] = 0; 00141 gBiasRaw[i] = 0; 00142 aBiasRaw[i] = 0; 00143 mBiasRaw[i] = 0; 00144 } 00145 _autoCalc = false; 00146 } 00147 00148 00149 uint16_t LSM9DS1::begin() 00150 { 00151 //! Todo: don't use _xgAddress or _mAddress, duplicating memory 00152 _xgAddress = settings.device.agAddress; 00153 _mAddress = settings.device.mAddress; 00154 00155 constrainScales(); 00156 // Once we have the scale values, we can calculate the resolution 00157 // of each sensor. That's what these functions are for. One for each sensor 00158 calcgRes(); // Calculate DPS / ADC tick, stored in gRes variable 00159 calcmRes(); // Calculate Gs / ADC tick, stored in mRes variable 00160 calcaRes(); // Calculate g / ADC tick, stored in aRes variable 00161 00162 // Now, initialize our hardware interface. 00163 if (settings.device.commInterface == IMU_MODE_I2C) // If we're using I2C 00164 initI2C(); // Initialize I2C 00165 else if (settings.device.commInterface == IMU_MODE_SPI) // else, if we're using SPI 00166 initSPI(); // Initialize SPI 00167 00168 // To verify communication, we can read from the WHO_AM_I register of 00169 // each device. Store those in a variable so we can return them. 00170 uint8_t mTest = mReadByte(WHO_AM_I_M); // Read the gyro WHO_AM_I 00171 uint8_t xgTest = xgReadByte(WHO_AM_I_XG); // Read the accel/mag WHO_AM_I 00172 pc.printf("%x, %x, %x, %x\n\r", mTest, xgTest, _xgAddress, _mAddress); 00173 uint16_t whoAmICombined = (xgTest << 8) | mTest; 00174 00175 if (whoAmICombined != ((WHO_AM_I_AG_RSP << 8) | WHO_AM_I_M_RSP)) 00176 return 0; 00177 00178 // Gyro initialization stuff: 00179 initGyro(); // This will "turn on" the gyro. Setting up interrupts, etc. 00180 00181 // Accelerometer initialization stuff: 00182 initAccel(); // "Turn on" all axes of the accel. Set up interrupts, etc. 00183 00184 // Magnetometer initialization stuff: 00185 initMag(); // "Turn on" all axes of the mag. Set up interrupts, etc. 00186 00187 // Once everything is initialized, return the WHO_AM_I registers we read: 00188 return whoAmICombined; 00189 } 00190 00191 void LSM9DS1::initGyro() 00192 { 00193 uint8_t tempRegValue = 0; 00194 00195 // CTRL_REG1_G (Default value: 0x00) 00196 // [ODR_G2][ODR_G1][ODR_G0][FS_G1][FS_G0][0][BW_G1][BW_G0] 00197 // ODR_G[2:0] - Output data rate selection 00198 // FS_G[1:0] - Gyroscope full-scale selection 00199 // BW_G[1:0] - Gyroscope bandwidth selection 00200 00201 // To disable gyro, set sample rate bits to 0. We'll only set sample 00202 // rate if the gyro is enabled. 00203 if (settings.gyro.enabled) { 00204 tempRegValue = (settings.gyro.sampleRate & 0x07) << 5; 00205 } 00206 switch (settings.gyro.scale) { 00207 case 500: 00208 tempRegValue |= (0x1 << 3); 00209 break; 00210 case 2000: 00211 tempRegValue |= (0x3 << 3); 00212 break; 00213 // Otherwise we'll set it to 245 dps (0x0 << 4) 00214 } 00215 tempRegValue |= (settings.gyro.bandwidth & 0x3); 00216 xgWriteByte(CTRL_REG1_G, tempRegValue); 00217 00218 // CTRL_REG2_G (Default value: 0x00) 00219 // [0][0][0][0][INT_SEL1][INT_SEL0][OUT_SEL1][OUT_SEL0] 00220 // INT_SEL[1:0] - INT selection configuration 00221 // OUT_SEL[1:0] - Out selection configuration 00222 xgWriteByte(CTRL_REG2_G, 0x00); 00223 00224 // CTRL_REG3_G (Default value: 0x00) 00225 // [LP_mode][HP_EN][0][0][HPCF3_G][HPCF2_G][HPCF1_G][HPCF0_G] 00226 // LP_mode - Low-power mode enable (0: disabled, 1: enabled) 00227 // HP_EN - HPF enable (0:disabled, 1: enabled) 00228 // HPCF_G[3:0] - HPF cutoff frequency 00229 tempRegValue = settings.gyro.lowPowerEnable ? (1<<7) : 0; 00230 if (settings.gyro.HPFEnable) { 00231 tempRegValue |= (1<<6) | (settings.gyro.HPFCutoff & 0x0F); 00232 } 00233 xgWriteByte(CTRL_REG3_G, tempRegValue); 00234 00235 // CTRL_REG4 (Default value: 0x38) 00236 // [0][0][Zen_G][Yen_G][Xen_G][0][LIR_XL1][4D_XL1] 00237 // Zen_G - Z-axis output enable (0:disable, 1:enable) 00238 // Yen_G - Y-axis output enable (0:disable, 1:enable) 00239 // Xen_G - X-axis output enable (0:disable, 1:enable) 00240 // LIR_XL1 - Latched interrupt (0:not latched, 1:latched) 00241 // 4D_XL1 - 4D option on interrupt (0:6D used, 1:4D used) 00242 tempRegValue = 0; 00243 if (settings.gyro.enableZ) tempRegValue |= (1<<5); 00244 if (settings.gyro.enableY) tempRegValue |= (1<<4); 00245 if (settings.gyro.enableX) tempRegValue |= (1<<3); 00246 if (settings.gyro.latchInterrupt) tempRegValue |= (1<<1); 00247 xgWriteByte(CTRL_REG4, tempRegValue); 00248 00249 // ORIENT_CFG_G (Default value: 0x00) 00250 // [0][0][SignX_G][SignY_G][SignZ_G][Orient_2][Orient_1][Orient_0] 00251 // SignX_G - Pitch axis (X) angular rate sign (0: positive, 1: negative) 00252 // Orient [2:0] - Directional user orientation selection 00253 tempRegValue = 0; 00254 if (settings.gyro.flipX) tempRegValue |= (1<<5); 00255 if (settings.gyro.flipY) tempRegValue |= (1<<4); 00256 if (settings.gyro.flipZ) tempRegValue |= (1<<3); 00257 xgWriteByte(ORIENT_CFG_G, tempRegValue); 00258 } 00259 00260 void LSM9DS1::initAccel() 00261 { 00262 uint8_t tempRegValue = 0; 00263 00264 // CTRL_REG5_XL (0x1F) (Default value: 0x38) 00265 // [DEC_1][DEC_0][Zen_XL][Yen_XL][Zen_XL][0][0][0] 00266 // DEC[0:1] - Decimation of accel data on OUT REG and FIFO. 00267 // 00: None, 01: 2 samples, 10: 4 samples 11: 8 samples 00268 // Zen_XL - Z-axis output enabled 00269 // Yen_XL - Y-axis output enabled 00270 // Xen_XL - X-axis output enabled 00271 if (settings.accel.enableZ) tempRegValue |= (1<<5); 00272 if (settings.accel.enableY) tempRegValue |= (1<<4); 00273 if (settings.accel.enableX) tempRegValue |= (1<<3); 00274 00275 xgWriteByte(CTRL_REG5_XL, tempRegValue); 00276 00277 // CTRL_REG6_XL (0x20) (Default value: 0x00) 00278 // [ODR_XL2][ODR_XL1][ODR_XL0][FS1_XL][FS0_XL][BW_SCAL_ODR][BW_XL1][BW_XL0] 00279 // ODR_XL[2:0] - Output data rate & power mode selection 00280 // FS_XL[1:0] - Full-scale selection 00281 // BW_SCAL_ODR - Bandwidth selection 00282 // BW_XL[1:0] - Anti-aliasing filter bandwidth selection 00283 tempRegValue = 0; 00284 // To disable the accel, set the sampleRate bits to 0. 00285 if (settings.accel.enabled) { 00286 tempRegValue |= (settings.accel.sampleRate & 0x07) << 5; 00287 } 00288 switch (settings.accel.scale) { 00289 case 4: 00290 tempRegValue |= (0x2 << 3); 00291 break; 00292 case 8: 00293 tempRegValue |= (0x3 << 3); 00294 break; 00295 case 16: 00296 tempRegValue |= (0x1 << 3); 00297 break; 00298 // Otherwise it'll be set to 2g (0x0 << 3) 00299 } 00300 if (settings.accel.bandwidth >= 0) { 00301 tempRegValue |= (1<<2); // Set BW_SCAL_ODR 00302 tempRegValue |= (settings.accel.bandwidth & 0x03); 00303 } 00304 xgWriteByte(CTRL_REG6_XL, tempRegValue); 00305 00306 // CTRL_REG7_XL (0x21) (Default value: 0x00) 00307 // [HR][DCF1][DCF0][0][0][FDS][0][HPIS1] 00308 // HR - High resolution mode (0: disable, 1: enable) 00309 // DCF[1:0] - Digital filter cutoff frequency 00310 // FDS - Filtered data selection 00311 // HPIS1 - HPF enabled for interrupt function 00312 tempRegValue = 0; 00313 if (settings.accel.highResEnable) { 00314 tempRegValue |= (1<<7); // Set HR bit 00315 tempRegValue |= (settings.accel.highResBandwidth & 0x3) << 5; 00316 } 00317 xgWriteByte(CTRL_REG7_XL, tempRegValue); 00318 } 00319 00320 // This is a function that uses the FIFO to accumulate sample of accelerometer and gyro data, average 00321 // them, scales them to gs and deg/s, respectively, and then passes the biases to the main sketch 00322 // for subtraction from all subsequent data. There are no gyro and accelerometer bias registers to store 00323 // the data as there are in the ADXL345, a precursor to the LSM9DS0, or the MPU-9150, so we have to 00324 // subtract the biases ourselves. This results in a more accurate measurement in general and can 00325 // remove errors due to imprecise or varying initial placement. Calibration of sensor data in this manner 00326 // is good practice. 00327 void LSM9DS1::calibrate(bool autoCalc) 00328 { 00329 uint8_t data[6] = {0, 0, 0, 0, 0, 0}; 00330 uint8_t samples = 0; 00331 int ii; 00332 int32_t aBiasRawTemp[3] = {0, 0, 0}; 00333 int32_t gBiasRawTemp[3] = {0, 0, 0}; 00334 pc.printf("\n\rPlace IMU on level surface and do not move it for gyro and accel calibration.\n\r"); 00335 wait(1); 00336 // Turn on FIFO and set threshold to 32 samples 00337 enableFIFO(true); 00338 setFIFO(FIFO_THS, 0x1F); 00339 while (samples < 0x1F) { 00340 samples = (xgReadByte(FIFO_SRC) & 0x3F); // Read number of stored samples 00341 } 00342 for(ii = 0; ii < samples ; ii++) { 00343 // Read the gyro data stored in the FIFO 00344 readGyro(); 00345 gBiasRawTemp[0] += gx; 00346 gBiasRawTemp[1] += gy; 00347 gBiasRawTemp[2] += gz; 00348 readAccel(); 00349 aBiasRawTemp[0] += ax; 00350 aBiasRawTemp[1] += ay; 00351 aBiasRawTemp[2] += az - (int16_t)(1./aRes); // Assumes sensor facing up! 00352 } 00353 for (ii = 0; ii < 3; ii++) { 00354 gBiasRaw[ii] = gBiasRawTemp[ii] / samples; 00355 gBias[ii] = calcGyro(gBiasRaw[ii]); 00356 aBiasRaw[ii] = aBiasRawTemp[ii] / samples; 00357 aBias[ii] = calcAccel(aBiasRaw[ii]); 00358 } 00359 00360 enableFIFO(false); 00361 setFIFO(FIFO_OFF, 0x00); 00362 00363 if (autoCalc) _autoCalc = true; 00364 } 00365 00366 void LSM9DS1::calibrateMag(bool loadIn) 00367 { 00368 int i, j; 00369 int16_t magMin[3] = {0, 0, 0}; 00370 int16_t magMax[3] = {0, 0, 0}; // The road warrior 00371 pc.printf("\n\n\r Rotate IMU device at least 360 in horizontal plane for magnetometer calibration\n\r"); 00372 wait(0.5); 00373 //pc.printf("enter loop\r\n"); 00374 for (i=0; i<1000; i++) { 00375 //pc.printf("%d\r\n",i); 00376 while (!magAvailable(ALL_AXIS)); 00377 //pc.printf("yes\r\n"); 00378 readMag(); 00379 int16_t magTemp[3] = {0, 0, 0}; 00380 magTemp[0] = mx; 00381 magTemp[1] = my; 00382 magTemp[2] = mz; 00383 for (j = 0; j < 3; j++) { 00384 if (magTemp[j] > magMax[j]) magMax[j] = magTemp[j]; 00385 if (magTemp[j] < magMin[j]) magMin[j] = magTemp[j]; 00386 } 00387 } 00388 pc.printf("thousand loop done\r\n"); 00389 for (j = 0; j < 3; j++) { 00390 mBiasRaw[j] = (magMax[j] + magMin[j]) / 2; 00391 mBias[j] = calcMag(mBiasRaw[j]); 00392 pc.printf("%f ",mBias[j]); 00393 if (loadIn) 00394 magOffset(j, mBiasRaw[j]); 00395 } 00396 pc.printf("\n\rMAG calibration done\n\r"); 00397 } 00398 void LSM9DS1::magOffset(uint8_t axis, int16_t offset) 00399 { 00400 if (axis > 2) 00401 return; 00402 uint8_t msb, lsb; 00403 msb = (offset & 0xFF00) >> 8; 00404 lsb = offset & 0x00FF; 00405 mWriteByte(OFFSET_X_REG_L_M + (2 * axis), lsb); 00406 mWriteByte(OFFSET_X_REG_H_M + (2 * axis), msb); 00407 } 00408 00409 void LSM9DS1::initMag() 00410 { 00411 uint8_t tempRegValue = 0; 00412 00413 // CTRL_REG1_M (Default value: 0x10) 00414 // [TEMP_COMP][OM1][OM0][DO2][DO1][DO0][0][ST] 00415 // TEMP_COMP - Temperature compensation 00416 // OM[1:0] - X & Y axes op mode selection 00417 // 00:low-power, 01:medium performance 00418 // 10: high performance, 11:ultra-high performance 00419 // DO[2:0] - Output data rate selection 00420 // ST - Self-test enable 00421 if (settings.mag.tempCompensationEnable) tempRegValue |= (1<<7); 00422 tempRegValue |= (settings.mag.XYPerformance & 0x3) << 5; 00423 tempRegValue |= (settings.mag.sampleRate & 0x7) << 2; 00424 mWriteByte(CTRL_REG1_M, tempRegValue); 00425 00426 // CTRL_REG2_M (Default value 0x00) 00427 // [0][FS1][FS0][0][REBOOT][SOFT_RST][0][0] 00428 // FS[1:0] - Full-scale configuration 00429 // REBOOT - Reboot memory content (0:normal, 1:reboot) 00430 // SOFT_RST - Reset config and user registers (0:default, 1:reset) 00431 tempRegValue = 0; 00432 switch (settings.mag.scale) { 00433 case 8: 00434 tempRegValue |= (0x1 << 5); 00435 break; 00436 case 12: 00437 tempRegValue |= (0x2 << 5); 00438 break; 00439 case 16: 00440 tempRegValue |= (0x3 << 5); 00441 break; 00442 // Otherwise we'll default to 4 gauss (00) 00443 } 00444 mWriteByte(CTRL_REG2_M, tempRegValue); // +/-4Gauss 00445 00446 // CTRL_REG3_M (Default value: 0x03) 00447 // [I2C_DISABLE][0][LP][0][0][SIM][MD1][MD0] 00448 // I2C_DISABLE - Disable I2C interace (0:enable, 1:disable) 00449 // LP - Low-power mode cofiguration (1:enable) 00450 // SIM - SPI mode selection (0:write-only, 1:read/write enable) 00451 // MD[1:0] - Operating mode 00452 // 00:continuous conversion, 01:single-conversion, 00453 // 10,11: Power-down 00454 tempRegValue = 0; 00455 if (settings.mag.lowPowerEnable) tempRegValue |= (1<<5); 00456 tempRegValue |= (settings.mag.operatingMode & 0x3); 00457 mWriteByte(CTRL_REG3_M, tempRegValue); // Continuous conversion mode 00458 00459 // CTRL_REG4_M (Default value: 0x00) 00460 // [0][0][0][0][OMZ1][OMZ0][BLE][0] 00461 // OMZ[1:0] - Z-axis operative mode selection 00462 // 00:low-power mode, 01:medium performance 00463 // 10:high performance, 10:ultra-high performance 00464 // BLE - Big/little endian data 00465 tempRegValue = 0; 00466 tempRegValue = (settings.mag.ZPerformance & 0x3) << 2; 00467 mWriteByte(CTRL_REG4_M, tempRegValue); 00468 00469 // CTRL_REG5_M (Default value: 0x00) 00470 // [0][BDU][0][0][0][0][0][0] 00471 // BDU - Block data update for magnetic data 00472 // 0:continuous, 1:not updated until MSB/LSB are read 00473 tempRegValue = 0; 00474 mWriteByte(CTRL_REG5_M, tempRegValue); 00475 } 00476 00477 uint8_t LSM9DS1::accelAvailable() 00478 { 00479 uint8_t status = xgReadByte(STATUS_REG_1); 00480 00481 return (status & (1<<0)); 00482 } 00483 00484 uint8_t LSM9DS1::gyroAvailable() 00485 { 00486 uint8_t status = xgReadByte(STATUS_REG_1); 00487 00488 return ((status & (1<<1)) >> 1); 00489 } 00490 00491 uint8_t LSM9DS1::tempAvailable() 00492 { 00493 uint8_t status = xgReadByte(STATUS_REG_1); 00494 00495 return ((status & (1<<2)) >> 2); 00496 } 00497 00498 uint8_t LSM9DS1::magAvailable(lsm9ds1_axis axis) 00499 { 00500 uint8_t status; 00501 status = mReadByte(STATUS_REG_M); 00502 00503 return ((status & (1<<axis)) >> axis); 00504 } 00505 00506 void LSM9DS1::readAccel() 00507 { 00508 uint8_t temp[6]; // We'll read six bytes from the accelerometer into temp 00509 xgReadBytes(OUT_X_L_XL, temp, 6); // Read 6 bytes, beginning at OUT_X_L_XL 00510 ax = (temp[1] << 8) | temp[0]; // Store x-axis values into ax 00511 ay = (temp[3] << 8) | temp[2]; // Store y-axis values into ay 00512 az = (temp[5] << 8) | temp[4]; // Store z-axis values into az 00513 if (_autoCalc) { 00514 ax -= aBiasRaw[X_AXIS]; 00515 ay -= aBiasRaw[Y_AXIS]; 00516 az -= aBiasRaw[Z_AXIS]; 00517 } 00518 } 00519 00520 int16_t LSM9DS1::readAccel(lsm9ds1_axis axis) 00521 { 00522 uint8_t temp[2]; 00523 int16_t value; 00524 xgReadBytes(OUT_X_L_XL + (2 * axis), temp, 2); 00525 value = (temp[1] << 8) | temp[0]; 00526 00527 if (_autoCalc) 00528 value -= aBiasRaw[axis]; 00529 00530 return value; 00531 } 00532 00533 void LSM9DS1::readMag() 00534 { 00535 uint8_t temp[6]; // We'll read six bytes from the mag into temp 00536 mReadBytes(OUT_X_L_M, temp, 6); // Read 6 bytes, beginning at OUT_X_L_M 00537 mx = (temp[1] << 8) | temp[0]; // Store x-axis values into mx 00538 my = (temp[3] << 8) | temp[2]; // Store y-axis values into my 00539 mz = (temp[5] << 8) | temp[4]; // Store z-axis values into mz 00540 mx = mx - mBiasRaw[0]; 00541 my = my - mBiasRaw[1]; 00542 mz = mz - mBiasRaw[2]; 00543 } 00544 00545 int16_t LSM9DS1::readMag(lsm9ds1_axis axis) 00546 { 00547 uint8_t temp[2]; 00548 mReadBytes(OUT_X_L_M + (2 * axis), temp, 2); 00549 return (temp[1] << 8) | temp[0]; 00550 } 00551 00552 void LSM9DS1::readTemp() 00553 { 00554 uint8_t temp[2]; // We'll read two bytes from the temperature sensor into temp 00555 xgReadBytes(OUT_TEMP_L, temp, 2); // Read 2 bytes, beginning at OUT_TEMP_L 00556 temperature = (int16_t)((temp[1] << 8) | temp[0]); 00557 } 00558 00559 void LSM9DS1::readGyro() 00560 { 00561 uint8_t temp[6]; // We'll read six bytes from the gyro into temp 00562 xgReadBytes(OUT_X_L_G, temp, 6); // Read 6 bytes, beginning at OUT_X_L_G 00563 gx = (temp[1] << 8) | temp[0]; // Store x-axis values into gx 00564 gy = (temp[3] << 8) | temp[2]; // Store y-axis values into gy 00565 gz = (temp[5] << 8) | temp[4]; // Store z-axis values into gz 00566 if (_autoCalc) { 00567 gx -= gBiasRaw[X_AXIS]; 00568 gy -= gBiasRaw[Y_AXIS]; 00569 gz -= gBiasRaw[Z_AXIS]; 00570 } 00571 } 00572 00573 int16_t LSM9DS1::readGyro(lsm9ds1_axis axis) 00574 { 00575 uint8_t temp[2]; 00576 int16_t value; 00577 00578 xgReadBytes(OUT_X_L_G + (2 * axis), temp, 2); 00579 00580 value = (temp[1] << 8) | temp[0]; 00581 00582 if (_autoCalc) 00583 value -= gBiasRaw[axis]; 00584 00585 return value; 00586 } 00587 00588 float LSM9DS1::calcGyro(int16_t gyro) 00589 { 00590 // Return the gyro raw reading times our pre-calculated DPS / (ADC tick): 00591 return gRes * gyro; 00592 } 00593 00594 float LSM9DS1::calcAccel(int16_t accel) 00595 { 00596 // Return the accel raw reading times our pre-calculated g's / (ADC tick): 00597 return aRes * accel; 00598 } 00599 00600 float LSM9DS1::calcMag(int16_t mag) 00601 { 00602 // Return the mag raw reading times our pre-calculated Gs / (ADC tick): 00603 return mRes * mag; 00604 } 00605 00606 void LSM9DS1::setGyroScale(uint16_t gScl) 00607 { 00608 // Read current value of CTRL_REG1_G: 00609 uint8_t ctrl1RegValue = xgReadByte(CTRL_REG1_G); 00610 // Mask out scale bits (3 & 4): 00611 ctrl1RegValue &= 0xE7; 00612 switch (gScl) { 00613 case 500: 00614 ctrl1RegValue |= (0x1 << 3); 00615 settings.gyro.scale = 500; 00616 break; 00617 case 2000: 00618 ctrl1RegValue |= (0x3 << 3); 00619 settings.gyro.scale = 2000; 00620 break; 00621 default: // Otherwise we'll set it to 245 dps (0x0 << 4) 00622 settings.gyro.scale = 245; 00623 break; 00624 } 00625 xgWriteByte(CTRL_REG1_G, ctrl1RegValue); 00626 00627 calcgRes(); 00628 } 00629 00630 void LSM9DS1::setAccelScale(uint8_t aScl) 00631 { 00632 // We need to preserve the other bytes in CTRL_REG6_XL. So, first read it: 00633 uint8_t tempRegValue = xgReadByte(CTRL_REG6_XL); 00634 // Mask out accel scale bits: 00635 tempRegValue &= 0xE7; 00636 00637 switch (aScl) { 00638 case 4: 00639 tempRegValue |= (0x2 << 3); 00640 settings.accel.scale = 4; 00641 break; 00642 case 8: 00643 tempRegValue |= (0x3 << 3); 00644 settings.accel.scale = 8; 00645 break; 00646 case 16: 00647 tempRegValue |= (0x1 << 3); 00648 settings.accel.scale = 16; 00649 break; 00650 default: // Otherwise it'll be set to 2g (0x0 << 3) 00651 settings.accel.scale = 2; 00652 break; 00653 } 00654 xgWriteByte(CTRL_REG6_XL, tempRegValue); 00655 00656 // Then calculate a new aRes, which relies on aScale being set correctly: 00657 calcaRes(); 00658 } 00659 00660 void LSM9DS1::setMagScale(uint8_t mScl) 00661 { 00662 // We need to preserve the other bytes in CTRL_REG6_XM. So, first read it: 00663 uint8_t temp = mReadByte(CTRL_REG2_M); 00664 // Then mask out the mag scale bits: 00665 temp &= 0xFF^(0x3 << 5); 00666 00667 switch (mScl) { 00668 case 8: 00669 temp |= (0x1 << 5); 00670 settings.mag.scale = 8; 00671 break; 00672 case 12: 00673 temp |= (0x2 << 5); 00674 settings.mag.scale = 12; 00675 break; 00676 case 16: 00677 temp |= (0x3 << 5); 00678 settings.mag.scale = 16; 00679 break; 00680 default: // Otherwise we'll default to 4 gauss (00) 00681 settings.mag.scale = 4; 00682 break; 00683 } 00684 00685 // And write the new register value back into CTRL_REG6_XM: 00686 mWriteByte(CTRL_REG2_M, temp); 00687 00688 // We've updated the sensor, but we also need to update our class variables 00689 // First update mScale: 00690 //mScale = mScl; 00691 // Then calculate a new mRes, which relies on mScale being set correctly: 00692 calcmRes(); 00693 } 00694 00695 void LSM9DS1::setGyroODR(uint8_t gRate) 00696 { 00697 // Only do this if gRate is not 0 (which would disable the gyro) 00698 if ((gRate & 0x07) != 0) { 00699 // We need to preserve the other bytes in CTRL_REG1_G. So, first read it: 00700 uint8_t temp = xgReadByte(CTRL_REG1_G); 00701 // Then mask out the gyro ODR bits: 00702 temp &= 0xFF^(0x7 << 5); 00703 temp |= (gRate & 0x07) << 5; 00704 // Update our settings struct 00705 settings.gyro.sampleRate = gRate & 0x07; 00706 // And write the new register value back into CTRL_REG1_G: 00707 xgWriteByte(CTRL_REG1_G, temp); 00708 } 00709 } 00710 00711 void LSM9DS1::setAccelODR(uint8_t aRate) 00712 { 00713 // Only do this if aRate is not 0 (which would disable the accel) 00714 if ((aRate & 0x07) != 0) { 00715 // We need to preserve the other bytes in CTRL_REG1_XM. So, first read it: 00716 uint8_t temp = xgReadByte(CTRL_REG6_XL); 00717 // Then mask out the accel ODR bits: 00718 temp &= 0x1F; 00719 // Then shift in our new ODR bits: 00720 temp |= ((aRate & 0x07) << 5); 00721 settings.accel.sampleRate = aRate & 0x07; 00722 // And write the new register value back into CTRL_REG1_XM: 00723 xgWriteByte(CTRL_REG6_XL, temp); 00724 } 00725 } 00726 00727 void LSM9DS1::setMagODR(uint8_t mRate) 00728 { 00729 // We need to preserve the other bytes in CTRL_REG5_XM. So, first read it: 00730 uint8_t temp = mReadByte(CTRL_REG1_M); 00731 // Then mask out the mag ODR bits: 00732 temp &= 0xFF^(0x7 << 2); 00733 // Then shift in our new ODR bits: 00734 temp |= ((mRate & 0x07) << 2); 00735 settings.mag.sampleRate = mRate & 0x07; 00736 // And write the new register value back into CTRL_REG5_XM: 00737 mWriteByte(CTRL_REG1_M, temp); 00738 } 00739 00740 void LSM9DS1::calcgRes() 00741 { 00742 gRes = ((float) settings.gyro.scale) / 32768.0; 00743 } 00744 00745 void LSM9DS1::calcaRes() 00746 { 00747 aRes = ((float) settings.accel.scale) / 32768.0; 00748 } 00749 00750 void LSM9DS1::calcmRes() 00751 { 00752 //mRes = ((float) settings.mag.scale) / 32768.0; 00753 switch (settings.mag.scale) { 00754 case 4: 00755 mRes = magSensitivity[0]; 00756 break; 00757 case 8: 00758 mRes = magSensitivity[1]; 00759 break; 00760 case 12: 00761 mRes = magSensitivity[2]; 00762 break; 00763 case 16: 00764 mRes = magSensitivity[3]; 00765 break; 00766 } 00767 00768 } 00769 00770 void LSM9DS1::configInt(interrupt_select interrupt, uint8_t generator, 00771 h_lactive activeLow, pp_od pushPull) 00772 { 00773 // Write to INT1_CTRL or INT2_CTRL. [interupt] should already be one of 00774 // those two values. 00775 // [generator] should be an OR'd list of values from the interrupt_generators enum 00776 xgWriteByte(interrupt, generator); 00777 00778 // Configure CTRL_REG8 00779 uint8_t temp; 00780 temp = xgReadByte(CTRL_REG8); 00781 00782 if (activeLow) temp |= (1<<5); 00783 else temp &= ~(1<<5); 00784 00785 if (pushPull) temp &= ~(1<<4); 00786 else temp |= (1<<4); 00787 00788 xgWriteByte(CTRL_REG8, temp); 00789 } 00790 00791 void LSM9DS1::configInactivity(uint8_t duration, uint8_t threshold, bool sleepOn) 00792 { 00793 uint8_t temp = 0; 00794 00795 temp = threshold & 0x7F; 00796 if (sleepOn) temp |= (1<<7); 00797 xgWriteByte(ACT_THS, temp); 00798 00799 xgWriteByte(ACT_DUR, duration); 00800 } 00801 00802 uint8_t LSM9DS1::getInactivity() 00803 { 00804 uint8_t temp = xgReadByte(STATUS_REG_0); 00805 temp &= (0x10); 00806 return temp; 00807 } 00808 00809 void LSM9DS1::configAccelInt(uint8_t generator, bool andInterrupts) 00810 { 00811 // Use variables from accel_interrupt_generator, OR'd together to create 00812 // the [generator]value. 00813 uint8_t temp = generator; 00814 if (andInterrupts) temp |= 0x80; 00815 xgWriteByte(INT_GEN_CFG_XL, temp); 00816 } 00817 00818 void LSM9DS1::configAccelThs(uint8_t threshold, lsm9ds1_axis axis, uint8_t duration, bool wait) 00819 { 00820 // Write threshold value to INT_GEN_THS_?_XL. 00821 // axis will be 0, 1, or 2 (x, y, z respectively) 00822 xgWriteByte(INT_GEN_THS_X_XL + axis, threshold); 00823 00824 // Write duration and wait to INT_GEN_DUR_XL 00825 uint8_t temp; 00826 temp = (duration & 0x7F); 00827 if (wait) temp |= 0x80; 00828 xgWriteByte(INT_GEN_DUR_XL, temp); 00829 } 00830 00831 uint8_t LSM9DS1::getAccelIntSrc() 00832 { 00833 uint8_t intSrc = xgReadByte(INT_GEN_SRC_XL); 00834 00835 // Check if the IA_XL (interrupt active) bit is set 00836 if (intSrc & (1<<6)) { 00837 return (intSrc & 0x3F); 00838 } 00839 00840 return 0; 00841 } 00842 00843 void LSM9DS1::configGyroInt(uint8_t generator, bool aoi, bool latch) 00844 { 00845 // Use variables from accel_interrupt_generator, OR'd together to create 00846 // the [generator]value. 00847 uint8_t temp = generator; 00848 if (aoi) temp |= 0x80; 00849 if (latch) temp |= 0x40; 00850 xgWriteByte(INT_GEN_CFG_G, temp); 00851 } 00852 00853 void LSM9DS1::configGyroThs(int16_t threshold, lsm9ds1_axis axis, uint8_t duration, bool wait) 00854 { 00855 uint8_t buffer[2]; 00856 buffer[0] = (threshold & 0x7F00) >> 8; 00857 buffer[1] = (threshold & 0x00FF); 00858 // Write threshold value to INT_GEN_THS_?H_G and INT_GEN_THS_?L_G. 00859 // axis will be 0, 1, or 2 (x, y, z respectively) 00860 xgWriteByte(INT_GEN_THS_XH_G + (axis * 2), buffer[0]); 00861 xgWriteByte(INT_GEN_THS_XH_G + 1 + (axis * 2), buffer[1]); 00862 00863 // Write duration and wait to INT_GEN_DUR_XL 00864 uint8_t temp; 00865 temp = (duration & 0x7F); 00866 if (wait) temp |= 0x80; 00867 xgWriteByte(INT_GEN_DUR_G, temp); 00868 } 00869 00870 uint8_t LSM9DS1::getGyroIntSrc() 00871 { 00872 uint8_t intSrc = xgReadByte(INT_GEN_SRC_G); 00873 00874 // Check if the IA_G (interrupt active) bit is set 00875 if (intSrc & (1<<6)) { 00876 return (intSrc & 0x3F); 00877 } 00878 00879 return 0; 00880 } 00881 00882 void LSM9DS1::configMagInt(uint8_t generator, h_lactive activeLow, bool latch) 00883 { 00884 // Mask out non-generator bits (0-4) 00885 uint8_t config = (generator & 0xE0); 00886 // IEA bit is 0 for active-low, 1 for active-high. 00887 if (activeLow == INT_ACTIVE_HIGH) config |= (1<<2); 00888 // IEL bit is 0 for latched, 1 for not-latched 00889 if (!latch) config |= (1<<1); 00890 // As long as we have at least 1 generator, enable the interrupt 00891 if (generator != 0) config |= (1<<0); 00892 00893 mWriteByte(INT_CFG_M, config); 00894 } 00895 00896 void LSM9DS1::configMagThs(uint16_t threshold) 00897 { 00898 // Write high eight bits of [threshold] to INT_THS_H_M 00899 mWriteByte(INT_THS_H_M, uint8_t((threshold & 0x7F00) >> 8)); 00900 // Write low eight bits of [threshold] to INT_THS_L_M 00901 mWriteByte(INT_THS_L_M, uint8_t(threshold & 0x00FF)); 00902 } 00903 00904 uint8_t LSM9DS1::getMagIntSrc() 00905 { 00906 uint8_t intSrc = mReadByte(INT_SRC_M); 00907 00908 // Check if the INT (interrupt active) bit is set 00909 if (intSrc & (1<<0)) { 00910 return (intSrc & 0xFE); 00911 } 00912 00913 return 0; 00914 } 00915 00916 void LSM9DS1::sleepGyro(bool enable) 00917 { 00918 uint8_t temp = xgReadByte(CTRL_REG9); 00919 if (enable) temp |= (1<<6); 00920 else temp &= ~(1<<6); 00921 xgWriteByte(CTRL_REG9, temp); 00922 } 00923 00924 void LSM9DS1::enableFIFO(bool enable) 00925 { 00926 uint8_t temp = xgReadByte(CTRL_REG9); 00927 if (enable) temp |= (1<<1); 00928 else temp &= ~(1<<1); 00929 xgWriteByte(CTRL_REG9, temp); 00930 } 00931 00932 void LSM9DS1::setFIFO(fifoMode_type fifoMode, uint8_t fifoThs) 00933 { 00934 // Limit threshold - 0x1F (31) is the maximum. If more than that was asked 00935 // limit it to the maximum. 00936 uint8_t threshold = fifoThs <= 0x1F ? fifoThs : 0x1F; 00937 xgWriteByte(FIFO_CTRL, ((fifoMode & 0x7) << 5) | (threshold & 0x1F)); 00938 } 00939 00940 uint8_t LSM9DS1::getFIFOSamples() 00941 { 00942 return (xgReadByte(FIFO_SRC) & 0x3F); 00943 } 00944 00945 void LSM9DS1::constrainScales() 00946 { 00947 if ((settings.gyro.scale != 245) && (settings.gyro.scale != 500) && 00948 (settings.gyro.scale != 2000)) { 00949 settings.gyro.scale = 245; 00950 } 00951 00952 if ((settings.accel.scale != 2) && (settings.accel.scale != 4) && 00953 (settings.accel.scale != 8) && (settings.accel.scale != 16)) { 00954 settings.accel.scale = 2; 00955 } 00956 00957 if ((settings.mag.scale != 4) && (settings.mag.scale != 8) && 00958 (settings.mag.scale != 12) && (settings.mag.scale != 16)) { 00959 settings.mag.scale = 4; 00960 } 00961 } 00962 00963 void LSM9DS1::xgWriteByte(uint8_t subAddress, uint8_t data) 00964 { 00965 // Whether we're using I2C or SPI, write a byte using the 00966 // gyro-specific I2C address or SPI CS pin. 00967 if (settings.device.commInterface == IMU_MODE_I2C) { 00968 pc.printf("yo"); 00969 I2CwriteByte(_xgAddress, subAddress, data); 00970 } else if (settings.device.commInterface == IMU_MODE_SPI) { 00971 SPIwriteByte(_xgAddress, subAddress, data); 00972 } 00973 } 00974 00975 void LSM9DS1::mWriteByte(uint8_t subAddress, uint8_t data) 00976 { 00977 // Whether we're using I2C or SPI, write a byte using the 00978 // accelerometer-specific I2C address or SPI CS pin. 00979 if (settings.device.commInterface == IMU_MODE_I2C) { 00980 pc.printf("mo"); 00981 return I2CwriteByte(_mAddress, subAddress, data); 00982 } else if (settings.device.commInterface == IMU_MODE_SPI) 00983 return SPIwriteByte(_mAddress, subAddress, data); 00984 } 00985 00986 uint8_t LSM9DS1::xgReadByte(uint8_t subAddress) 00987 { 00988 // Whether we're using I2C or SPI, read a byte using the 00989 // gyro-specific I2C address or SPI CS pin. 00990 if (settings.device.commInterface == IMU_MODE_I2C) 00991 return I2CreadByte(_xgAddress, subAddress); 00992 else if (settings.device.commInterface == IMU_MODE_SPI) 00993 return SPIreadByte(_xgAddress, subAddress); 00994 } 00995 00996 void LSM9DS1::xgReadBytes(uint8_t subAddress, uint8_t * dest, uint8_t count) 00997 { 00998 // Whether we're using I2C or SPI, read multiple bytes using the 00999 // gyro-specific I2C address or SPI CS pin. 01000 if (settings.device.commInterface == IMU_MODE_I2C) { 01001 I2CreadBytes(_xgAddress, subAddress, dest, count); 01002 } else if (settings.device.commInterface == IMU_MODE_SPI) { 01003 SPIreadBytes(_xgAddress, subAddress, dest, count); 01004 } 01005 } 01006 01007 uint8_t LSM9DS1::mReadByte(uint8_t subAddress) 01008 { 01009 // Whether we're using I2C or SPI, read a byte using the 01010 // accelerometer-specific I2C address or SPI CS pin. 01011 if (settings.device.commInterface == IMU_MODE_I2C) 01012 return I2CreadByte(_mAddress, subAddress); 01013 else if (settings.device.commInterface == IMU_MODE_SPI) 01014 return SPIreadByte(_mAddress, subAddress); 01015 } 01016 01017 void LSM9DS1::mReadBytes(uint8_t subAddress, uint8_t * dest, uint8_t count) 01018 { 01019 // Whether we're using I2C or SPI, read multiple bytes using the 01020 // accelerometer-specific I2C address or SPI CS pin. 01021 if (settings.device.commInterface == IMU_MODE_I2C) 01022 I2CreadBytes(_mAddress, subAddress, dest, count); 01023 else if (settings.device.commInterface == IMU_MODE_SPI) 01024 SPIreadBytes(_mAddress, subAddress, dest, count); 01025 } 01026 01027 void LSM9DS1::initSPI() 01028 { 01029 /* 01030 pinMode(_xgAddress, OUTPUT); 01031 digitalWrite(_xgAddress, HIGH); 01032 pinMode(_mAddress, OUTPUT); 01033 digitalWrite(_mAddress, HIGH); 01034 01035 SPI.begin(); 01036 // Maximum SPI frequency is 10MHz, could divide by 2 here: 01037 SPI.setClockDivider(SPI_CLOCK_DIV2); 01038 // Data is read and written MSb first. 01039 SPI.setBitOrder(MSBFIRST); 01040 // Data is captured on rising edge of clock (CPHA = 0) 01041 // Base value of the clock is HIGH (CPOL = 1) 01042 SPI.setDataMode(SPI_MODE0); 01043 */ 01044 } 01045 01046 void LSM9DS1::SPIwriteByte(uint8_t csPin, uint8_t subAddress, uint8_t data) 01047 { 01048 /* 01049 digitalWrite(csPin, LOW); // Initiate communication 01050 01051 // If write, bit 0 (MSB) should be 0 01052 // If single write, bit 1 should be 0 01053 SPI.transfer(subAddress & 0x3F); // Send Address 01054 SPI.transfer(data); // Send data 01055 01056 digitalWrite(csPin, HIGH); // Close communication 01057 */ 01058 } 01059 01060 uint8_t LSM9DS1::SPIreadByte(uint8_t csPin, uint8_t subAddress) 01061 { 01062 uint8_t temp; 01063 // Use the multiple read function to read 1 byte. 01064 // Value is returned to `temp`. 01065 SPIreadBytes(csPin, subAddress, &temp, 1); 01066 return temp; 01067 } 01068 01069 void LSM9DS1::SPIreadBytes(uint8_t csPin, uint8_t subAddress, 01070 uint8_t * dest, uint8_t count) 01071 { 01072 // To indicate a read, set bit 0 (msb) of first byte to 1 01073 uint8_t rAddress = 0x80 | (subAddress & 0x3F); 01074 // Mag SPI port is different. If we're reading multiple bytes, 01075 // set bit 1 to 1. The remaining six bytes are the address to be read 01076 if ((csPin == _mAddress) && count > 1) 01077 rAddress |= 0x40; 01078 01079 /* 01080 digitalWrite(csPin, LOW); // Initiate communication 01081 SPI.transfer(rAddress); 01082 for (int i=0; i<count; i++) 01083 { 01084 dest[i] = SPI.transfer(0x00); // Read into destination array 01085 } 01086 digitalWrite(csPin, HIGH); // Close communication 01087 */ 01088 } 01089 01090 void LSM9DS1::initI2C() 01091 { 01092 /* 01093 Wire.begin(); // Initialize I2C library 01094 */ 01095 01096 //already initialized in constructor! 01097 } 01098 01099 // Wire.h read and write protocols 01100 void LSM9DS1::I2CwriteByte(uint8_t address, uint8_t subAddress, uint8_t data) 01101 { 01102 /* 01103 Wire.beginTransmission(address); // Initialize the Tx buffer 01104 Wire.write(subAddress); // Put slave register address in Tx buffer 01105 Wire.write(data); // Put data in Tx buffer 01106 Wire.endTransmission(); // Send the Tx buffer 01107 */ 01108 char temp_data[2] = {subAddress, data}; 01109 i2c.write(address, temp_data, 2); 01110 } 01111 01112 uint8_t LSM9DS1::I2CreadByte(uint8_t address, uint8_t subAddress) 01113 { 01114 /* 01115 int timeout = LSM9DS1_COMMUNICATION_TIMEOUT; 01116 uint8_t data; // `data` will store the register data 01117 01118 Wire.beginTransmission(address); // Initialize the Tx buffer 01119 Wire.write(subAddress); // Put slave register address in Tx buffer 01120 Wire.endTransmission(true); // Send the Tx buffer, but send a restart to keep connection alive 01121 Wire.requestFrom(address, (uint8_t) 1); // Read one byte from slave register address 01122 while ((Wire.available() < 1) && (timeout-- > 0)) 01123 delay(1); 01124 01125 if (timeout <= 0) 01126 return 255; //! Bad! 255 will be misinterpreted as a good value. 01127 01128 data = Wire.read(); // Fill Rx buffer with result 01129 return data; // Return data read from slave register 01130 */ 01131 char data; 01132 char temp[2] = {subAddress}; 01133 01134 i2c.write(address, temp, 1); 01135 //i2c.write(address & 0xFE); 01136 temp[1] = 0x00; 01137 i2c.write(address, temp, 1); 01138 //i2c.write( address | 0x01); 01139 int a = i2c.read(address, &data, 1); 01140 return data; 01141 } 01142 01143 uint8_t LSM9DS1::I2CreadBytes(uint8_t address, uint8_t subAddress, uint8_t * dest, uint8_t count) 01144 { 01145 /* 01146 int timeout = LSM9DS1_COMMUNICATION_TIMEOUT; 01147 Wire.beginTransmission(address); // Initialize the Tx buffer 01148 // Next send the register to be read. OR with 0x80 to indicate multi-read. 01149 Wire.write(subAddress | 0x80); // Put slave register address in Tx buffer 01150 01151 Wire.endTransmission(true); // Send the Tx buffer, but send a restart to keep connection alive 01152 uint8_t i = 0; 01153 Wire.requestFrom(address, count); // Read bytes from slave register address 01154 while ((Wire.available() < count) && (timeout-- > 0)) 01155 delay(1); 01156 if (timeout <= 0) 01157 return -1; 01158 01159 for (int i=0; i<count;) 01160 { 01161 if (Wire.available()) 01162 { 01163 dest[i++] = Wire.read(); 01164 } 01165 } 01166 return count; 01167 */ 01168 int i; 01169 char temp_dest[count]; 01170 char temp[1] = {subAddress}; 01171 i2c.write(address, temp, 1); 01172 i2c.read(address, temp_dest, count); 01173 01174 //i2c doesn't take uint8_ts, but rather chars so do this nasty af conversion 01175 for (i=0; i < count; i++) { 01176 dest[i] = temp_dest[i]; 01177 } 01178 return count; 01179 }
Generated on Fri Jul 22 2022 16:30:56 by
1.7.2
