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 data[6] = {0, 0, 0, 0, 0, 0}; 00336 uint8_t samples = 0; 00337 int ii; 00338 int32_t aBiasRawTemp[3] = {0, 0, 0}; 00339 int32_t gBiasRawTemp[3] = {0, 0, 0}; 00340 00341 // Turn on FIFO and set threshold to 32 samples 00342 enableFIFO(true); 00343 setFIFO(FIFO_THS, 0x1F); 00344 while (samples < 0x1F) 00345 { 00346 samples = (xgReadByte(FIFO_SRC) & 0x3F); // Read number of stored samples 00347 } 00348 for(ii = 0; ii < samples ; ii++) 00349 { // Read the gyro data stored in the FIFO 00350 readGyro(); 00351 gBiasRawTemp[0] += gx; 00352 gBiasRawTemp[1] += gy; 00353 gBiasRawTemp[2] += gz; 00354 readAccel(); 00355 aBiasRawTemp[0] += ax; 00356 aBiasRawTemp[1] += ay; 00357 aBiasRawTemp[2] += az - (int16_t)(1./aRes); // Assumes sensor facing up! 00358 } 00359 for (ii = 0; ii < 3; ii++) 00360 { 00361 gBiasRaw[ii] = gBiasRawTemp[ii] / samples; 00362 gBias[ii] = calcGyro(gBiasRaw[ii]); 00363 aBiasRaw[ii] = aBiasRawTemp[ii] / samples; 00364 aBias[ii] = calcAccel(aBiasRaw[ii]); 00365 } 00366 00367 enableFIFO(false); 00368 setFIFO(FIFO_OFF, 0x00); 00369 00370 if (autoCalc) _autoCalc = true; 00371 } 00372 00373 void LSM9DS1::calibrateMag(bool loadIn) 00374 { 00375 int i, j; 00376 int16_t magMin[3] = {0, 0, 0}; 00377 int16_t magMax[3] = {0, 0, 0}; // The road warrior 00378 00379 for (i=0; i<128; i++) 00380 { 00381 while (!magAvailable()) 00382 ; 00383 readMag(); 00384 int16_t magTemp[3] = {0, 0, 0}; 00385 magTemp[0] = mx; 00386 magTemp[1] = my; 00387 magTemp[2] = mz; 00388 for (j = 0; j < 3; j++) 00389 { 00390 if (magTemp[j] > magMax[j]) magMax[j] = magTemp[j]; 00391 if (magTemp[j] < magMin[j]) magMin[j] = magTemp[j]; 00392 } 00393 } 00394 for (j = 0; j < 3; j++) 00395 { 00396 mBiasRaw[j] = (magMax[j] + magMin[j]) / 2; 00397 mBias[j] = calcMag(mBiasRaw[j]); 00398 if (loadIn) 00399 magOffset(j, mBiasRaw[j]); 00400 } 00401 00402 } 00403 void LSM9DS1::magOffset(uint8_t axis, int16_t offset) 00404 { 00405 if (axis > 2) 00406 return; 00407 uint8_t msb, lsb; 00408 msb = (offset & 0xFF00) >> 8; 00409 lsb = offset & 0x00FF; 00410 mWriteByte(OFFSET_X_REG_L_M + (2 * axis), lsb); 00411 mWriteByte(OFFSET_X_REG_H_M + (2 * axis), msb); 00412 } 00413 00414 void LSM9DS1::initMag() 00415 { 00416 uint8_t tempRegValue = 0; 00417 00418 // CTRL_REG1_M (Default value: 0x10) 00419 // [TEMP_COMP][OM1][OM0][DO2][DO1][DO0][0][ST] 00420 // TEMP_COMP - Temperature compensation 00421 // OM[1:0] - X & Y axes op mode selection 00422 // 00:low-power, 01:medium performance 00423 // 10: high performance, 11:ultra-high performance 00424 // DO[2:0] - Output data rate selection 00425 // ST - Self-test enable 00426 if (settings.mag.tempCompensationEnable) tempRegValue |= (1<<7); 00427 tempRegValue |= (settings.mag.XYPerformance & 0x3) << 5; 00428 tempRegValue |= (settings.mag.sampleRate & 0x7) << 2; 00429 mWriteByte(CTRL_REG1_M, tempRegValue); 00430 00431 // CTRL_REG2_M (Default value 0x00) 00432 // [0][FS1][FS0][0][REBOOT][SOFT_RST][0][0] 00433 // FS[1:0] - Full-scale configuration 00434 // REBOOT - Reboot memory content (0:normal, 1:reboot) 00435 // SOFT_RST - Reset config and user registers (0:default, 1:reset) 00436 tempRegValue = 0; 00437 switch (settings.mag.scale) 00438 { 00439 case 8: 00440 tempRegValue |= (0x1 << 5); 00441 break; 00442 case 12: 00443 tempRegValue |= (0x2 << 5); 00444 break; 00445 case 16: 00446 tempRegValue |= (0x3 << 5); 00447 break; 00448 // Otherwise we'll default to 4 gauss (00) 00449 } 00450 mWriteByte(CTRL_REG2_M, tempRegValue); // +/-4Gauss 00451 00452 // CTRL_REG3_M (Default value: 0x03) 00453 // [I2C_DISABLE][0][LP][0][0][SIM][MD1][MD0] 00454 // I2C_DISABLE - Disable I2C interace (0:enable, 1:disable) 00455 // LP - Low-power mode cofiguration (1:enable) 00456 // SIM - SPI mode selection (0:write-only, 1:read/write enable) 00457 // MD[1:0] - Operating mode 00458 // 00:continuous conversion, 01:single-conversion, 00459 // 10,11: Power-down 00460 tempRegValue = 0; 00461 if (settings.mag.lowPowerEnable) tempRegValue |= (1<<5); 00462 tempRegValue |= (settings.mag.operatingMode & 0x3); 00463 mWriteByte(CTRL_REG3_M, tempRegValue); // Continuous conversion mode 00464 00465 // CTRL_REG4_M (Default value: 0x00) 00466 // [0][0][0][0][OMZ1][OMZ0][BLE][0] 00467 // OMZ[1:0] - Z-axis operative mode selection 00468 // 00:low-power mode, 01:medium performance 00469 // 10:high performance, 10:ultra-high performance 00470 // BLE - Big/little endian data 00471 tempRegValue = 0; 00472 tempRegValue = (settings.mag.ZPerformance & 0x3) << 2; 00473 mWriteByte(CTRL_REG4_M, tempRegValue); 00474 00475 // CTRL_REG5_M (Default value: 0x00) 00476 // [0][BDU][0][0][0][0][0][0] 00477 // BDU - Block data update for magnetic data 00478 // 0:continuous, 1:not updated until MSB/LSB are read 00479 tempRegValue = 0; 00480 mWriteByte(CTRL_REG5_M, tempRegValue); 00481 } 00482 00483 uint8_t LSM9DS1::accelAvailable() 00484 { 00485 uint8_t status = xgReadByte(STATUS_REG_1); 00486 00487 return (status & (1<<0)); 00488 } 00489 00490 uint8_t LSM9DS1::gyroAvailable() 00491 { 00492 uint8_t status = xgReadByte(STATUS_REG_1); 00493 00494 return ((status & (1<<1)) >> 1); 00495 } 00496 00497 uint8_t LSM9DS1::tempAvailable() 00498 { 00499 uint8_t status = xgReadByte(STATUS_REG_1); 00500 00501 return ((status & (1<<2)) >> 2); 00502 } 00503 00504 uint8_t LSM9DS1::magAvailable(lsm9ds1_axis axis) 00505 { 00506 uint8_t status; 00507 status = mReadByte(STATUS_REG_M); 00508 00509 return ((status & (1<<axis)) >> axis); 00510 } 00511 00512 void LSM9DS1::readAccel() 00513 { 00514 uint8_t temp[6]; // We'll read six bytes from the accelerometer into temp 00515 xgReadBytes(OUT_X_L_XL, temp, 6); // Read 6 bytes, beginning at OUT_X_L_XL 00516 ax = (temp[1] << 8) | temp[0]; // Store x-axis values into ax 00517 ay = (temp[3] << 8) | temp[2]; // Store y-axis values into ay 00518 az = (temp[5] << 8) | temp[4]; // Store z-axis values into az 00519 if (_autoCalc) 00520 { 00521 ax -= aBiasRaw[X_AXIS]; 00522 ay -= aBiasRaw[Y_AXIS]; 00523 az -= aBiasRaw[Z_AXIS]; 00524 } 00525 } 00526 00527 int16_t LSM9DS1::readAccel(lsm9ds1_axis axis) 00528 { 00529 uint8_t temp[2]; 00530 int16_t value; 00531 xgReadBytes(OUT_X_L_XL + (2 * axis), temp, 2); 00532 value = (temp[1] << 8) | temp[0]; 00533 00534 if (_autoCalc) 00535 value -= aBiasRaw[axis]; 00536 00537 return value; 00538 } 00539 00540 void LSM9DS1::readMag() 00541 { 00542 uint8_t temp[6]; // We'll read six bytes from the mag into temp 00543 mReadBytes(OUT_X_L_M, temp, 6); // Read 6 bytes, beginning at OUT_X_L_M 00544 mx = (temp[1] << 8) | temp[0]; // Store x-axis values into mx 00545 my = (temp[3] << 8) | temp[2]; // Store y-axis values into my 00546 mz = (temp[5] << 8) | temp[4]; // Store z-axis values into mz 00547 } 00548 00549 int16_t LSM9DS1::readMag(lsm9ds1_axis axis) 00550 { 00551 uint8_t temp[2]; 00552 mReadBytes(OUT_X_L_M + (2 * axis), temp, 2); 00553 return (temp[1] << 8) | temp[0]; 00554 } 00555 00556 void LSM9DS1::readTemp() 00557 { 00558 uint8_t temp[2]; // We'll read two bytes from the temperature sensor into temp 00559 xgReadBytes(OUT_TEMP_L, temp, 2); // Read 2 bytes, beginning at OUT_TEMP_L 00560 temperature = ((int16_t)temp[1] << 8) | temp[0]; 00561 } 00562 00563 void LSM9DS1::readGyro() 00564 { 00565 uint8_t temp[6]; // We'll read six bytes from the gyro into temp 00566 xgReadBytes(OUT_X_L_G, temp, 6); // Read 6 bytes, beginning at OUT_X_L_G 00567 gx = (temp[1] << 8) | temp[0]; // Store x-axis values into gx 00568 gy = (temp[3] << 8) | temp[2]; // Store y-axis values into gy 00569 gz = (temp[5] << 8) | temp[4]; // Store z-axis values into gz 00570 if (_autoCalc) 00571 { 00572 gx -= gBiasRaw[X_AXIS]; 00573 gy -= gBiasRaw[Y_AXIS]; 00574 gz -= gBiasRaw[Z_AXIS]; 00575 } 00576 } 00577 00578 int16_t LSM9DS1::readGyro(lsm9ds1_axis axis) 00579 { 00580 uint8_t temp[2]; 00581 int16_t value; 00582 00583 xgReadBytes(OUT_X_L_G + (2 * axis), temp, 2); 00584 00585 value = (temp[1] << 8) | temp[0]; 00586 00587 if (_autoCalc) 00588 value -= gBiasRaw[axis]; 00589 00590 return value; 00591 } 00592 00593 float LSM9DS1::calcGyro(int16_t gyro) 00594 { 00595 // Return the gyro raw reading times our pre-calculated DPS / (ADC tick): 00596 return gRes * gyro; 00597 } 00598 00599 float LSM9DS1::calcAccel(int16_t accel) 00600 { 00601 // Return the accel raw reading times our pre-calculated g's / (ADC tick): 00602 return aRes * accel; 00603 } 00604 00605 float LSM9DS1::calcMag(int16_t mag) 00606 { 00607 // Return the mag raw reading times our pre-calculated Gs / (ADC tick): 00608 return mRes * mag; 00609 } 00610 00611 void LSM9DS1::setGyroScale(uint16_t gScl) 00612 { 00613 // Read current value of CTRL_REG1_G: 00614 uint8_t ctrl1RegValue = xgReadByte(CTRL_REG1_G); 00615 // Mask out scale bits (3 & 4): 00616 ctrl1RegValue &= 0xE7; 00617 switch (gScl) 00618 { 00619 case 500: 00620 ctrl1RegValue |= (0x1 << 3); 00621 settings.gyro.scale = 500; 00622 break; 00623 case 2000: 00624 ctrl1RegValue |= (0x3 << 3); 00625 settings.gyro.scale = 2000; 00626 break; 00627 default: // Otherwise we'll set it to 245 dps (0x0 << 4) 00628 settings.gyro.scale = 245; 00629 break; 00630 } 00631 xgWriteByte(CTRL_REG1_G, ctrl1RegValue); 00632 00633 calcgRes(); 00634 } 00635 00636 void LSM9DS1::setAccelScale(uint8_t aScl) 00637 { 00638 // We need to preserve the other bytes in CTRL_REG6_XL. So, first read it: 00639 uint8_t tempRegValue = xgReadByte(CTRL_REG6_XL); 00640 // Mask out accel scale bits: 00641 tempRegValue &= 0xE7; 00642 00643 switch (aScl) 00644 { 00645 case 4: 00646 tempRegValue |= (0x2 << 3); 00647 settings.accel.scale = 4; 00648 break; 00649 case 8: 00650 tempRegValue |= (0x3 << 3); 00651 settings.accel.scale = 8; 00652 break; 00653 case 16: 00654 tempRegValue |= (0x1 << 3); 00655 settings.accel.scale = 16; 00656 break; 00657 default: // Otherwise it'll be set to 2g (0x0 << 3) 00658 settings.accel.scale = 2; 00659 break; 00660 } 00661 xgWriteByte(CTRL_REG6_XL, tempRegValue); 00662 00663 // Then calculate a new aRes, which relies on aScale being set correctly: 00664 calcaRes(); 00665 } 00666 00667 void LSM9DS1::setMagScale(uint8_t mScl) 00668 { 00669 // We need to preserve the other bytes in CTRL_REG6_XM. So, first read it: 00670 uint8_t temp = mReadByte(CTRL_REG2_M); 00671 // Then mask out the mag scale bits: 00672 temp &= 0xFF^(0x3 << 5); 00673 00674 switch (mScl) 00675 { 00676 case 8: 00677 temp |= (0x1 << 5); 00678 settings.mag.scale = 8; 00679 break; 00680 case 12: 00681 temp |= (0x2 << 5); 00682 settings.mag.scale = 12; 00683 break; 00684 case 16: 00685 temp |= (0x3 << 5); 00686 settings.mag.scale = 16; 00687 break; 00688 default: // Otherwise we'll default to 4 gauss (00) 00689 settings.mag.scale = 4; 00690 break; 00691 } 00692 00693 // And write the new register value back into CTRL_REG6_XM: 00694 mWriteByte(CTRL_REG2_M, temp); 00695 00696 // We've updated the sensor, but we also need to update our class variables 00697 // First update mScale: 00698 //mScale = mScl; 00699 // Then calculate a new mRes, which relies on mScale being set correctly: 00700 calcmRes(); 00701 } 00702 00703 void LSM9DS1::setGyroODR(uint8_t gRate) 00704 { 00705 // Only do this if gRate is not 0 (which would disable the gyro) 00706 if ((gRate & 0x07) != 0) 00707 { 00708 // We need to preserve the other bytes in CTRL_REG1_G. So, first read it: 00709 uint8_t temp = xgReadByte(CTRL_REG1_G); 00710 // Then mask out the gyro ODR bits: 00711 temp &= 0xFF^(0x7 << 5); 00712 temp |= (gRate & 0x07) << 5; 00713 // Update our settings struct 00714 settings.gyro.sampleRate = gRate & 0x07; 00715 // And write the new register value back into CTRL_REG1_G: 00716 xgWriteByte(CTRL_REG1_G, temp); 00717 } 00718 } 00719 00720 void LSM9DS1::setAccelODR(uint8_t aRate) 00721 { 00722 // Only do this if aRate is not 0 (which would disable the accel) 00723 if ((aRate & 0x07) != 0) 00724 { 00725 // We need to preserve the other bytes in CTRL_REG1_XM. So, first read it: 00726 uint8_t temp = xgReadByte(CTRL_REG6_XL); 00727 // Then mask out the accel ODR bits: 00728 temp &= 0x1F; 00729 // Then shift in our new ODR bits: 00730 temp |= ((aRate & 0x07) << 5); 00731 settings.accel.sampleRate = aRate & 0x07; 00732 // And write the new register value back into CTRL_REG1_XM: 00733 xgWriteByte(CTRL_REG6_XL, temp); 00734 } 00735 } 00736 00737 void LSM9DS1::setMagODR(uint8_t mRate) 00738 { 00739 // We need to preserve the other bytes in CTRL_REG5_XM. So, first read it: 00740 uint8_t temp = mReadByte(CTRL_REG1_M); 00741 // Then mask out the mag ODR bits: 00742 temp &= 0xFF^(0x7 << 2); 00743 // Then shift in our new ODR bits: 00744 temp |= ((mRate & 0x07) << 2); 00745 settings.mag.sampleRate = mRate & 0x07; 00746 // And write the new register value back into CTRL_REG5_XM: 00747 mWriteByte(CTRL_REG1_M, temp); 00748 } 00749 00750 void LSM9DS1::calcgRes() 00751 { 00752 gRes = ((float) settings.gyro.scale) / 32768.0; 00753 } 00754 00755 void LSM9DS1::calcaRes() 00756 { 00757 aRes = ((float) settings.accel.scale) / 32768.0; 00758 } 00759 00760 void LSM9DS1::calcmRes() 00761 { 00762 //mRes = ((float) settings.mag.scale) / 32768.0; 00763 switch (settings.mag.scale) 00764 { 00765 case 4: 00766 mRes = magSensitivity[0]; 00767 break; 00768 case 8: 00769 mRes = magSensitivity[1]; 00770 break; 00771 case 12: 00772 mRes = magSensitivity[2]; 00773 break; 00774 case 16: 00775 mRes = magSensitivity[3]; 00776 break; 00777 } 00778 00779 } 00780 00781 void LSM9DS1::configInt(interrupt_select interrupt, uint8_t generator, 00782 h_lactive activeLow, pp_od pushPull) 00783 { 00784 // Write to INT1_CTRL or INT2_CTRL. [interupt] should already be one of 00785 // those two values. 00786 // [generator] should be an OR'd list of values from the interrupt_generators enum 00787 xgWriteByte(interrupt, generator); 00788 00789 // Configure CTRL_REG8 00790 uint8_t temp; 00791 temp = xgReadByte(CTRL_REG8); 00792 00793 if (activeLow) temp |= (1<<5); 00794 else temp &= ~(1<<5); 00795 00796 if (pushPull) temp &= ~(1<<4); 00797 else temp |= (1<<4); 00798 00799 xgWriteByte(CTRL_REG8, temp); 00800 } 00801 00802 void LSM9DS1::configInactivity(uint8_t duration, uint8_t threshold, bool sleepOn) 00803 { 00804 uint8_t temp = 0; 00805 00806 temp = threshold & 0x7F; 00807 if (sleepOn) temp |= (1<<7); 00808 xgWriteByte(ACT_THS, temp); 00809 00810 xgWriteByte(ACT_DUR, duration); 00811 } 00812 00813 uint8_t LSM9DS1::getInactivity() 00814 { 00815 uint8_t temp = xgReadByte(STATUS_REG_0); 00816 temp &= (0x10); 00817 return temp; 00818 } 00819 00820 void LSM9DS1::configAccelInt(uint8_t generator, bool andInterrupts) 00821 { 00822 // Use variables from accel_interrupt_generator, OR'd together to create 00823 // the [generator]value. 00824 uint8_t temp = generator; 00825 if (andInterrupts) temp |= 0x80; 00826 xgWriteByte(INT_GEN_CFG_XL, temp); 00827 } 00828 00829 void LSM9DS1::configAccelThs(uint8_t threshold, lsm9ds1_axis axis, uint8_t duration, bool wait) 00830 { 00831 // Write threshold value to INT_GEN_THS_?_XL. 00832 // axis will be 0, 1, or 2 (x, y, z respectively) 00833 xgWriteByte(INT_GEN_THS_X_XL + axis, threshold); 00834 00835 // Write duration and wait to INT_GEN_DUR_XL 00836 uint8_t temp; 00837 temp = (duration & 0x7F); 00838 if (wait) temp |= 0x80; 00839 xgWriteByte(INT_GEN_DUR_XL, temp); 00840 } 00841 00842 uint8_t LSM9DS1::getAccelIntSrc() 00843 { 00844 uint8_t intSrc = xgReadByte(INT_GEN_SRC_XL); 00845 00846 // Check if the IA_XL (interrupt active) bit is set 00847 if (intSrc & (1<<6)) 00848 { 00849 return (intSrc & 0x3F); 00850 } 00851 00852 return 0; 00853 } 00854 00855 void LSM9DS1::configGyroInt(uint8_t generator, bool aoi, bool latch) 00856 { 00857 // Use variables from accel_interrupt_generator, OR'd together to create 00858 // the [generator]value. 00859 uint8_t temp = generator; 00860 if (aoi) temp |= 0x80; 00861 if (latch) temp |= 0x40; 00862 xgWriteByte(INT_GEN_CFG_G, temp); 00863 } 00864 00865 void LSM9DS1::configGyroThs(int16_t threshold, lsm9ds1_axis axis, uint8_t duration, bool wait) 00866 { 00867 uint8_t buffer[2]; 00868 buffer[0] = (threshold & 0x7F00) >> 8; 00869 buffer[1] = (threshold & 0x00FF); 00870 // Write threshold value to INT_GEN_THS_?H_G and INT_GEN_THS_?L_G. 00871 // axis will be 0, 1, or 2 (x, y, z respectively) 00872 xgWriteByte(INT_GEN_THS_XH_G + (axis * 2), buffer[0]); 00873 xgWriteByte(INT_GEN_THS_XH_G + 1 + (axis * 2), buffer[1]); 00874 00875 // Write duration and wait to INT_GEN_DUR_XL 00876 uint8_t temp; 00877 temp = (duration & 0x7F); 00878 if (wait) temp |= 0x80; 00879 xgWriteByte(INT_GEN_DUR_G, temp); 00880 } 00881 00882 uint8_t LSM9DS1::getGyroIntSrc() 00883 { 00884 uint8_t intSrc = xgReadByte(INT_GEN_SRC_G); 00885 00886 // Check if the IA_G (interrupt active) bit is set 00887 if (intSrc & (1<<6)) 00888 { 00889 return (intSrc & 0x3F); 00890 } 00891 00892 return 0; 00893 } 00894 00895 void LSM9DS1::configMagInt(uint8_t generator, h_lactive activeLow, bool latch) 00896 { 00897 // Mask out non-generator bits (0-4) 00898 uint8_t config = (generator & 0xE0); 00899 // IEA bit is 0 for active-low, 1 for active-high. 00900 if (activeLow == INT_ACTIVE_HIGH) config |= (1<<2); 00901 // IEL bit is 0 for latched, 1 for not-latched 00902 if (!latch) config |= (1<<1); 00903 // As long as we have at least 1 generator, enable the interrupt 00904 if (generator != 0) config |= (1<<0); 00905 00906 mWriteByte(INT_CFG_M, config); 00907 } 00908 00909 void LSM9DS1::configMagThs(uint16_t threshold) 00910 { 00911 // Write high eight bits of [threshold] to INT_THS_H_M 00912 mWriteByte(INT_THS_H_M, uint8_t((threshold & 0x7F00) >> 8)); 00913 // Write low eight bits of [threshold] to INT_THS_L_M 00914 mWriteByte(INT_THS_L_M, uint8_t(threshold & 0x00FF)); 00915 } 00916 00917 uint8_t LSM9DS1::getMagIntSrc() 00918 { 00919 uint8_t intSrc = mReadByte(INT_SRC_M); 00920 00921 // Check if the INT (interrupt active) bit is set 00922 if (intSrc & (1<<0)) 00923 { 00924 return (intSrc & 0xFE); 00925 } 00926 00927 return 0; 00928 } 00929 00930 void LSM9DS1::sleepGyro(bool enable) 00931 { 00932 uint8_t temp = xgReadByte(CTRL_REG9); 00933 if (enable) temp |= (1<<6); 00934 else temp &= ~(1<<6); 00935 xgWriteByte(CTRL_REG9, temp); 00936 } 00937 00938 void LSM9DS1::enableFIFO(bool enable) 00939 { 00940 uint8_t temp = xgReadByte(CTRL_REG9); 00941 if (enable) temp |= (1<<1); 00942 else temp &= ~(1<<1); 00943 xgWriteByte(CTRL_REG9, temp); 00944 } 00945 00946 void LSM9DS1::setFIFO(fifoMode_type fifoMode, uint8_t fifoThs) 00947 { 00948 // Limit threshold - 0x1F (31) is the maximum. If more than that was asked 00949 // limit it to the maximum. 00950 uint8_t threshold = fifoThs <= 0x1F ? fifoThs : 0x1F; 00951 xgWriteByte(FIFO_CTRL, ((fifoMode & 0x7) << 5) | (threshold & 0x1F)); 00952 } 00953 00954 uint8_t LSM9DS1::getFIFOSamples() 00955 { 00956 return (xgReadByte(FIFO_SRC) & 0x3F); 00957 } 00958 00959 void LSM9DS1::constrainScales() 00960 { 00961 if ((settings.gyro.scale != 245) && (settings.gyro.scale != 500) && 00962 (settings.gyro.scale != 2000)) 00963 { 00964 settings.gyro.scale = 245; 00965 } 00966 00967 if ((settings.accel.scale != 2) && (settings.accel.scale != 4) && 00968 (settings.accel.scale != 8) && (settings.accel.scale != 16)) 00969 { 00970 settings.accel.scale = 2; 00971 } 00972 00973 if ((settings.mag.scale != 4) && (settings.mag.scale != 8) && 00974 (settings.mag.scale != 12) && (settings.mag.scale != 16)) 00975 { 00976 settings.mag.scale = 4; 00977 } 00978 } 00979 00980 void LSM9DS1::xgWriteByte(uint8_t subAddress, uint8_t data) 00981 { 00982 // Whether we're using I2C or SPI, write a byte using the 00983 // gyro-specific I2C address or SPI CS pin. 00984 if (settings.device.commInterface == IMU_MODE_I2C) { 00985 printf("yo"); 00986 I2CwriteByte(_xgAddress, subAddress, data); 00987 } else if (settings.device.commInterface == IMU_MODE_SPI) { 00988 SPIwriteByte(_xgAddress, subAddress, data); 00989 } 00990 } 00991 00992 void LSM9DS1::mWriteByte(uint8_t subAddress, uint8_t data) 00993 { 00994 // Whether we're using I2C or SPI, write a byte using the 00995 // accelerometer-specific I2C address or SPI CS pin. 00996 if (settings.device.commInterface == IMU_MODE_I2C) 00997 return I2CwriteByte(_mAddress, subAddress, data); 00998 else if (settings.device.commInterface == IMU_MODE_SPI) 00999 return SPIwriteByte(_mAddress, subAddress, data); 01000 } 01001 01002 uint8_t LSM9DS1::xgReadByte(uint8_t subAddress) 01003 { 01004 // Whether we're using I2C or SPI, read a byte using the 01005 // gyro-specific I2C address or SPI CS pin. 01006 if (settings.device.commInterface == IMU_MODE_I2C) 01007 return I2CreadByte(_xgAddress, subAddress); 01008 else if (settings.device.commInterface == IMU_MODE_SPI) 01009 return SPIreadByte(_xgAddress, subAddress); 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 } 01032 01033 void LSM9DS1::mReadBytes(uint8_t subAddress, uint8_t * dest, uint8_t count) 01034 { 01035 // Whether we're using I2C or SPI, read multiple bytes using the 01036 // accelerometer-specific I2C address or SPI CS pin. 01037 if (settings.device.commInterface == IMU_MODE_I2C) 01038 I2CreadBytes(_mAddress, subAddress, dest, count); 01039 else if (settings.device.commInterface == IMU_MODE_SPI) 01040 SPIreadBytes(_mAddress, subAddress, dest, count); 01041 } 01042 01043 void LSM9DS1::initSPI() 01044 { 01045 /* 01046 pinMode(_xgAddress, OUTPUT); 01047 digitalWrite(_xgAddress, HIGH); 01048 pinMode(_mAddress, OUTPUT); 01049 digitalWrite(_mAddress, HIGH); 01050 01051 SPI.begin(); 01052 // Maximum SPI frequency is 10MHz, could divide by 2 here: 01053 SPI.setClockDivider(SPI_CLOCK_DIV2); 01054 // Data is read and written MSb first. 01055 SPI.setBitOrder(MSBFIRST); 01056 // Data is captured on rising edge of clock (CPHA = 0) 01057 // Base value of the clock is HIGH (CPOL = 1) 01058 SPI.setDataMode(SPI_MODE0); 01059 */ 01060 } 01061 01062 void LSM9DS1::SPIwriteByte(uint8_t csPin, uint8_t subAddress, uint8_t data) 01063 { 01064 /* 01065 digitalWrite(csPin, LOW); // Initiate communication 01066 01067 // If write, bit 0 (MSB) should be 0 01068 // If single write, bit 1 should be 0 01069 SPI.transfer(subAddress & 0x3F); // Send Address 01070 SPI.transfer(data); // Send data 01071 01072 digitalWrite(csPin, HIGH); // Close communication 01073 */ 01074 } 01075 01076 uint8_t LSM9DS1::SPIreadByte(uint8_t csPin, uint8_t subAddress) 01077 { 01078 uint8_t temp; 01079 // Use the multiple read function to read 1 byte. 01080 // Value is returned to `temp`. 01081 SPIreadBytes(csPin, subAddress, &temp, 1); 01082 return temp; 01083 } 01084 01085 void LSM9DS1::SPIreadBytes(uint8_t csPin, uint8_t subAddress, 01086 uint8_t * dest, uint8_t count) 01087 { 01088 // To indicate a read, set bit 0 (msb) of first byte to 1 01089 uint8_t rAddress = 0x80 | (subAddress & 0x3F); 01090 // Mag SPI port is different. If we're reading multiple bytes, 01091 // set bit 1 to 1. The remaining six bytes are the address to be read 01092 if ((csPin == _mAddress) && count > 1) 01093 rAddress |= 0x40; 01094 01095 /* 01096 digitalWrite(csPin, LOW); // Initiate communication 01097 SPI.transfer(rAddress); 01098 for (int i=0; i<count; i++) 01099 { 01100 dest[i] = SPI.transfer(0x00); // Read into destination array 01101 } 01102 digitalWrite(csPin, HIGH); // Close communication 01103 */ 01104 } 01105 01106 void LSM9DS1::initI2C() 01107 { 01108 /* 01109 Wire.begin(); // Initialize I2C library 01110 */ 01111 01112 //already initialized in constructor! 01113 } 01114 01115 // Wire.h read and write protocols 01116 void LSM9DS1::I2CwriteByte(uint8_t address, uint8_t subAddress, uint8_t data) 01117 { 01118 /* 01119 Wire.beginTransmission(address); // Initialize the Tx buffer 01120 Wire.write(subAddress); // Put slave register address in Tx buffer 01121 Wire.write(data); // Put data in Tx buffer 01122 Wire.endTransmission(); // Send the Tx buffer 01123 */ 01124 char temp_data[2] = {subAddress, data}; 01125 i2c.write(address, temp_data, 2); 01126 } 01127 01128 uint8_t LSM9DS1::I2CreadByte(uint8_t address, uint8_t subAddress) 01129 { 01130 /* 01131 int timeout = LSM9DS1_COMMUNICATION_TIMEOUT; 01132 uint8_t data; // `data` will store the register data 01133 01134 Wire.beginTransmission(address); // Initialize the Tx buffer 01135 Wire.write(subAddress); // Put slave register address in Tx buffer 01136 Wire.endTransmission(true); // Send the Tx buffer, but send a restart to keep connection alive 01137 Wire.requestFrom(address, (uint8_t) 1); // Read one byte from slave register address 01138 while ((Wire.available() < 1) && (timeout-- > 0)) 01139 delay(1); 01140 01141 if (timeout <= 0) 01142 return 255; //! Bad! 255 will be misinterpreted as a good value. 01143 01144 data = Wire.read(); // Fill Rx buffer with result 01145 return data; // Return data read from slave register 01146 */ 01147 char data; 01148 char temp[1] = {subAddress}; 01149 01150 i2c.write(address, temp, 1); 01151 //i2c.write(address & 0xFE); 01152 temp[1] = 0x00; 01153 i2c.write(address, temp, 1); 01154 //i2c.write( address | 0x01); 01155 int a = i2c.read(address, &data, 1); 01156 return data; 01157 } 01158 01159 uint8_t LSM9DS1::I2CreadBytes(uint8_t address, uint8_t subAddress, uint8_t * dest, uint8_t count) 01160 { 01161 /* 01162 int timeout = LSM9DS1_COMMUNICATION_TIMEOUT; 01163 Wire.beginTransmission(address); // Initialize the Tx buffer 01164 // Next send the register to be read. OR with 0x80 to indicate multi-read. 01165 Wire.write(subAddress | 0x80); // Put slave register address in Tx buffer 01166 01167 Wire.endTransmission(true); // Send the Tx buffer, but send a restart to keep connection alive 01168 uint8_t i = 0; 01169 Wire.requestFrom(address, count); // Read bytes from slave register address 01170 while ((Wire.available() < count) && (timeout-- > 0)) 01171 delay(1); 01172 if (timeout <= 0) 01173 return -1; 01174 01175 for (int i=0; i<count;) 01176 { 01177 if (Wire.available()) 01178 { 01179 dest[i++] = Wire.read(); 01180 } 01181 } 01182 return count; 01183 */ 01184 int i; 01185 char temp_dest[count]; 01186 char temp[1] = {subAddress}; 01187 i2c.write(address, temp, 1); 01188 i2c.read(address, temp_dest, count); 01189 01190 //i2c doesn't take uint8_ts, but rather chars so do this nasty af conversion 01191 for (i=0; i < count; i++) { 01192 dest[i] = temp_dest[i]; 01193 } 01194 return count; 01195 }
Generated on Wed Jul 27 2022 23:23:55 by
1.7.2
