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