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