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