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