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