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