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 Adafruit9-DOf by
Adafruit_LSM303_U.cpp
00001 /*************************************************************************** 00002 This is a library for the LSM303 Accelerometer and magnentometer/compass 00003 00004 Designed specifically to work with the Adafruit LSM303DLHC Breakout 00005 00006 These displays use I2C to communicate, 2 pins are required to interface. 00007 00008 Adafruit invests time and resources providing this open source code, 00009 please support Adafruit andopen-source hardware by purchasing products 00010 from Adafruit! 00011 00012 Written by Kevin Townsend for Adafruit Industries. 00013 BSD license, all text above must be included in any redistribution 00014 ***************************************************************************/ 00015 00016 00017 #include "Adafruit_LSM303_U.h" 00018 #include "Serial_base.h" 00019 00020 static float _lsm303Accel_MG_LSB = 0.001F; // 1, 2, 4 or 12 mg per lsb 00021 static float _lsm303Mag_Gauss_LSB_XY = 1100.0F; // Varies with gain 00022 static float _lsm303Mag_Gauss_LSB_Z = 980.0F; // Varies with gain 00023 00024 /*************************************************************************** 00025 ACCELEROMETER 00026 ***************************************************************************/ 00027 /*************************************************************************** 00028 PRIVATE FUNCTIONS 00029 ***************************************************************************/ 00030 00031 /**************************************************************************/ 00032 /*! 00033 @brief Abstract away platform differences in Arduino wire library 00034 */ 00035 /**************************************************************************/ 00036 void Adafruit_LSM303_Accel_Unified::write8(byte address, byte reg, byte value) 00037 { 00038 byte data[2] = {reg, value}; 00039 i2c->write(address,data,2); 00040 } 00041 00042 /**************************************************************************/ 00043 /*! 00044 @brief Abstract away platform differences in Arduino wire library 00045 */ 00046 /**************************************************************************/ 00047 byte Adafruit_LSM303_Accel_Unified::read8(byte address, byte reg) 00048 { 00049 byte value; 00050 00051 i2c->writeByte(address, reg); 00052 i2c->read(address, &value, 1); 00053 00054 return value; 00055 } 00056 00057 /**************************************************************************/ 00058 /*! 00059 @brief Reads the raw data from the sensor 00060 */ 00061 /**************************************************************************/ 00062 void Adafruit_LSM303_Accel_Unified::read() 00063 { 00064 // Read the accelerometer 00065 i2c->writeByte(LSM303_ADDRESS_ACCEL, LSM303_REGISTER_ACCEL_OUT_X_L_A | 0x80); 00066 00067 byte data[6]; 00068 i2c->read(LSM303_ADDRESS_ACCEL, data, 6); 00069 00070 // Shift values to create properly formed integer (low byte first) 00071 _accelData.x = (int16_t)(data[0] | (data[1] << 8)) >> 4; 00072 _accelData.y = (int16_t)(data[2] | (data[3] << 8)) >> 4; 00073 _accelData.z = (int16_t)(data[4] | (data[5] << 8)) >> 4; 00074 } 00075 00076 /*************************************************************************** 00077 CONSTRUCTOR 00078 ***************************************************************************/ 00079 00080 /**************************************************************************/ 00081 /*! 00082 @brief Instantiates a new Adafruit_LSM303 class 00083 */ 00084 /**************************************************************************/ 00085 Adafruit_LSM303_Accel_Unified::Adafruit_LSM303_Accel_Unified(int32_t sensorID) { 00086 _sensorID = sensorID; 00087 } 00088 00089 /*************************************************************************** 00090 PUBLIC FUNCTIONS 00091 ***************************************************************************/ 00092 00093 /**************************************************************************/ 00094 /*! 00095 @brief Setups the HW 00096 */ 00097 /**************************************************************************/ 00098 bool Adafruit_LSM303_Accel_Unified::begin() 00099 { 00100 // Enable I2C 00101 // Enable the accelerometer (100Hz) 00102 write8(LSM303_ADDRESS_ACCEL, LSM303_REGISTER_ACCEL_CTRL_REG1_A, 0x57); 00103 00104 // LSM303DLHC has no WHOAMI register so read CTRL_REG1_A back to check 00105 // if we are connected or not 00106 uint8_t reg1_a = read8(LSM303_ADDRESS_ACCEL, LSM303_REGISTER_ACCEL_CTRL_REG1_A); 00107 if (reg1_a != 0x57) 00108 { 00109 return false; 00110 } 00111 00112 return true; 00113 } 00114 00115 /**************************************************************************/ 00116 /*! 00117 @brief Gets the most recent sensor event 00118 */ 00119 /**************************************************************************/ 00120 void Adafruit_LSM303_Accel_Unified::getEvent(sensors_event_t *event) { 00121 /* Clear the event */ 00122 memset(event, 0, sizeof(sensors_event_t)); 00123 00124 /* Read new data */ 00125 read(); 00126 00127 event->version = sizeof(sensors_event_t); 00128 event->sensor_id = _sensorID; 00129 event->type = SENSOR_TYPE_ACCELEROMETER; 00130 event->timestamp = millis(); 00131 event->acceleration.x = _accelData.x * _lsm303Accel_MG_LSB * SENSORS_GRAVITY_STANDARD; 00132 event->acceleration.y = _accelData.y * _lsm303Accel_MG_LSB * SENSORS_GRAVITY_STANDARD; 00133 event->acceleration.z = _accelData.z * _lsm303Accel_MG_LSB * SENSORS_GRAVITY_STANDARD; 00134 } 00135 00136 /**************************************************************************/ 00137 /*! 00138 @brief Gets the sensor_t data 00139 */ 00140 /**************************************************************************/ 00141 void Adafruit_LSM303_Accel_Unified::getSensor(sensor_t *sensor) { 00142 /* Clear the sensor_t object */ 00143 memset(sensor, 0, sizeof(sensor_t)); 00144 00145 /* Insert the sensor name in the fixed length char array */ 00146 strncpy (sensor->name, "LSM303", sizeof(sensor->name) - 1); 00147 sensor->name[sizeof(sensor->name)- 1] = 0; 00148 sensor->version = 1; 00149 sensor->sensor_id = _sensorID; 00150 sensor->type = SENSOR_TYPE_ACCELEROMETER; 00151 sensor->min_delay = 0; 00152 sensor->max_value = 0.0F; // TBD 00153 sensor->min_value = 0.0F; // TBD 00154 sensor->resolution = 0.0F; // TBD 00155 } 00156 00157 /*************************************************************************** 00158 MAGNETOMETER 00159 ***************************************************************************/ 00160 /*************************************************************************** 00161 PRIVATE FUNCTIONS 00162 ***************************************************************************/ 00163 00164 /**************************************************************************/ 00165 /*! 00166 @brief Abstract away platform differences in Arduino wire library 00167 */ 00168 /**************************************************************************/ 00169 void Adafruit_LSM303_Mag_Unified::write8(byte address, byte reg, byte value) 00170 { 00171 byte data[2] = {reg, value}; 00172 i2c->write(address,data,2); 00173 } 00174 00175 /**************************************************************************/ 00176 /*! 00177 @brief Abstract away platform differences in Arduino wire library 00178 */ 00179 /**************************************************************************/ 00180 byte Adafruit_LSM303_Mag_Unified::read8(byte address, byte reg) 00181 { 00182 byte value; 00183 i2c->writeByte(address, reg); 00184 i2c->read(address, &value, 1); 00185 00186 return value; 00187 } 00188 00189 /**************************************************************************/ 00190 /*! 00191 @brief Reads the raw data from the sensor 00192 */ 00193 /**************************************************************************/ 00194 void Adafruit_LSM303_Mag_Unified::read() 00195 { 00196 // Read the magnetometer 00197 i2c->writeByte(LSM303_ADDRESS_MAG, LSM303_REGISTER_MAG_OUT_X_H_M); 00198 00199 byte data[6]; 00200 i2c->read(LSM303_ADDRESS_MAG, data, 6); 00201 00202 00203 // Shift values to create properly formed integer (low byte first) 00204 _magData.x = (int16_t)(data[0] | ((int16_t)data[1] << 8)); 00205 _magData.y = (int16_t)(data[2] | ((int16_t)data[3] << 8)); 00206 _magData.z = (int16_t)(data[4] | ((int16_t)data[5] << 8)); 00207 00208 // ToDo: Calculate orientation 00209 _magData.orientation = 0.0; 00210 } 00211 00212 /*************************************************************************** 00213 CONSTRUCTOR 00214 ***************************************************************************/ 00215 00216 /**************************************************************************/ 00217 /*! 00218 @brief Instantiates a new Adafruit_LSM303 class 00219 */ 00220 /**************************************************************************/ 00221 Adafruit_LSM303_Mag_Unified::Adafruit_LSM303_Mag_Unified(int32_t sensorID) { 00222 _sensorID = sensorID; 00223 _autoRangeEnabled = false; 00224 } 00225 00226 /*************************************************************************** 00227 PUBLIC FUNCTIONS 00228 ***************************************************************************/ 00229 00230 /**************************************************************************/ 00231 /*! 00232 @brief Setups the HW 00233 */ 00234 /**************************************************************************/ 00235 bool Adafruit_LSM303_Mag_Unified::begin() 00236 { 00237 // Enable I2C 00238 00239 // Enable the magnetometer 00240 write8(LSM303_ADDRESS_MAG, LSM303_REGISTER_MAG_MR_REG_M, 0x00); 00241 00242 // LSM303DLHC has no WHOAMI register so read CRA_REG_M to check 00243 // the default value (0b00010000/0x10) 00244 uint8_t reg1_a = read8(LSM303_ADDRESS_MAG, LSM303_REGISTER_MAG_CRA_REG_M); 00245 if (reg1_a != 0x10) 00246 { 00247 return false; 00248 } 00249 00250 // Set the gain to a known level 00251 setMagGain(LSM303_MAGGAIN_1_3); 00252 00253 return true; 00254 } 00255 00256 /**************************************************************************/ 00257 /*! 00258 @brief Enables or disables auto-ranging 00259 */ 00260 /**************************************************************************/ 00261 void Adafruit_LSM303_Mag_Unified::enableAutoRange(bool enabled) 00262 { 00263 _autoRangeEnabled = enabled; 00264 } 00265 00266 /**************************************************************************/ 00267 /*! 00268 @brief Sets the magnetometer's gain 00269 */ 00270 /**************************************************************************/ 00271 void Adafruit_LSM303_Mag_Unified::setMagGain(lsm303MagGain gain) 00272 { 00273 write8(LSM303_ADDRESS_MAG, LSM303_REGISTER_MAG_CRB_REG_M, (byte)gain); 00274 00275 _magGain = gain; 00276 00277 switch(gain) 00278 { 00279 case LSM303_MAGGAIN_1_3: 00280 _lsm303Mag_Gauss_LSB_XY = 1100; 00281 _lsm303Mag_Gauss_LSB_Z = 980; 00282 break; 00283 case LSM303_MAGGAIN_1_9: 00284 _lsm303Mag_Gauss_LSB_XY = 855; 00285 _lsm303Mag_Gauss_LSB_Z = 760; 00286 break; 00287 case LSM303_MAGGAIN_2_5: 00288 _lsm303Mag_Gauss_LSB_XY = 670; 00289 _lsm303Mag_Gauss_LSB_Z = 600; 00290 break; 00291 case LSM303_MAGGAIN_4_0: 00292 _lsm303Mag_Gauss_LSB_XY = 450; 00293 _lsm303Mag_Gauss_LSB_Z = 400; 00294 break; 00295 case LSM303_MAGGAIN_4_7: 00296 _lsm303Mag_Gauss_LSB_XY = 400; 00297 _lsm303Mag_Gauss_LSB_Z = 355; 00298 break; 00299 case LSM303_MAGGAIN_5_6: 00300 _lsm303Mag_Gauss_LSB_XY = 330; 00301 _lsm303Mag_Gauss_LSB_Z = 295; 00302 break; 00303 case LSM303_MAGGAIN_8_1: 00304 _lsm303Mag_Gauss_LSB_XY = 230; 00305 _lsm303Mag_Gauss_LSB_Z = 205; 00306 break; 00307 } 00308 } 00309 00310 /**************************************************************************/ 00311 /*! 00312 @brief Gets the most recent sensor event 00313 */ 00314 /**************************************************************************/ 00315 void Adafruit_LSM303_Mag_Unified::getEvent(sensors_event_t *event) { 00316 bool readingValid = false; 00317 00318 /* Clear the event */ 00319 memset(event, 0, sizeof(sensors_event_t)); 00320 00321 while(!readingValid) 00322 { 00323 /* Read new data */ 00324 read(); 00325 00326 /* Make sure the sensor isn't saturating if auto-ranging is enabled */ 00327 if (!_autoRangeEnabled) 00328 { 00329 readingValid = true; 00330 } 00331 else 00332 { 00333 s_com->print(_magData.x); s_com->print(" "); 00334 s_com->print(_magData.y); s_com->print(" "); 00335 s_com->print(_magData.z); s_com->println(" "); 00336 /* Check if the sensor is saturating or not */ 00337 if ( (_magData.x >= 2040) | (_magData.x <= -2040) | 00338 (_magData.y >= 2040) | (_magData.y <= -2040) | 00339 (_magData.z >= 2040) | (_magData.z <= -2040) ) 00340 { 00341 /* Saturating .... increase the range if we can */ 00342 switch(_magGain) 00343 { 00344 case LSM303_MAGGAIN_5_6: 00345 setMagGain(LSM303_MAGGAIN_8_1); 00346 readingValid = false; 00347 s_com->println("Changing range to +/- 8.1"); 00348 break; 00349 case LSM303_MAGGAIN_4_7: 00350 setMagGain(LSM303_MAGGAIN_5_6); 00351 readingValid = false; 00352 s_com->println("Changing range to +/- 5.6"); 00353 break; 00354 case LSM303_MAGGAIN_4_0: 00355 setMagGain(LSM303_MAGGAIN_4_7); 00356 readingValid = false; 00357 s_com->println("Changing range to +/- 4.7"); 00358 break; 00359 case LSM303_MAGGAIN_2_5: 00360 setMagGain(LSM303_MAGGAIN_4_0); 00361 readingValid = false; 00362 s_com->println("Changing range to +/- 4.0"); 00363 break; 00364 case LSM303_MAGGAIN_1_9: 00365 setMagGain(LSM303_MAGGAIN_2_5); 00366 readingValid = false; 00367 s_com->println("Changing range to +/- 2.5"); 00368 break; 00369 case LSM303_MAGGAIN_1_3: 00370 setMagGain(LSM303_MAGGAIN_1_9); 00371 readingValid = false; 00372 s_com->println("Changing range to +/- 1.9"); 00373 break; 00374 default: 00375 readingValid = true; 00376 break; 00377 } 00378 } 00379 else 00380 { 00381 /* All values are withing range */ 00382 readingValid = true; 00383 } 00384 } 00385 } 00386 00387 event->version = sizeof(sensors_event_t); 00388 event->sensor_id = _sensorID; 00389 event->type = SENSOR_TYPE_MAGNETIC_FIELD; 00390 event->timestamp = millis(); 00391 event->magnetic.x = _magData.x / _lsm303Mag_Gauss_LSB_XY * SENSORS_GAUSS_TO_MICROTESLA; 00392 event->magnetic.y = _magData.y / _lsm303Mag_Gauss_LSB_XY * SENSORS_GAUSS_TO_MICROTESLA; 00393 event->magnetic.z = _magData.z / _lsm303Mag_Gauss_LSB_Z * SENSORS_GAUSS_TO_MICROTESLA; 00394 } 00395 00396 /**************************************************************************/ 00397 /*! 00398 @brief Gets the sensor_t data 00399 */ 00400 /**************************************************************************/ 00401 void Adafruit_LSM303_Mag_Unified::getSensor(sensor_t *sensor) { 00402 /* Clear the sensor_t object */ 00403 memset(sensor, 0, sizeof(sensor_t)); 00404 00405 /* Insert the sensor name in the fixed length char array */ 00406 strncpy (sensor->name, "LSM303", sizeof(sensor->name) - 1); 00407 sensor->name[sizeof(sensor->name)- 1] = 0; 00408 sensor->version = 1; 00409 sensor->sensor_id = _sensorID; 00410 sensor->type = SENSOR_TYPE_MAGNETIC_FIELD; 00411 sensor->min_delay = 0; 00412 sensor->max_value = 0.0F; // TBD 00413 sensor->min_value = 0.0F; // TBD 00414 sensor->resolution = 0.0F; // TBD 00415 }
Generated on Wed Jul 13 2022 18:41:10 by
1.7.2
