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