├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .travis.yml ├── Adafruit_LSM303.h ├── Adafruit_LSM303_U.cpp ├── Adafruit_LSM303_U.h ├── README.md ├── examples ├── accelsensor │ └── accelsensor.ino └── magsensor │ └── magsensor.ino └── library.properties /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thank you for opening an issue on an Adafruit Arduino library repository. To 2 | improve the speed of resolution please review the following guidelines and 3 | common troubleshooting steps below before creating the issue: 4 | 5 | - **Do not use GitHub issues for troubleshooting projects and issues.** Instead use 6 | the forums at http://forums.adafruit.com to ask questions and troubleshoot why 7 | something isn't working as expected. In many cases the problem is a common issue 8 | that you will more quickly receive help from the forum community. GitHub issues 9 | are meant for known defects in the code. If you don't know if there is a defect 10 | in the code then start with troubleshooting on the forum first. 11 | 12 | - **If following a tutorial or guide be sure you didn't miss a step.** Carefully 13 | check all of the steps and commands to run have been followed. Consult the 14 | forum if you're unsure or have questions about steps in a guide/tutorial. 15 | 16 | - **For Arduino projects check these very common issues to ensure they don't apply**: 17 | 18 | - For uploading sketches or communicating with the board make sure you're using 19 | a **USB data cable** and **not** a **USB charge-only cable**. It is sometimes 20 | very hard to tell the difference between a data and charge cable! Try using the 21 | cable with other devices or swapping to another cable to confirm it is not 22 | the problem. 23 | 24 | - **Be sure you are supplying adequate power to the board.** Check the specs of 25 | your board and plug in an external power supply. In many cases just 26 | plugging a board into your computer is not enough to power it and other 27 | peripherals. 28 | 29 | - **Double check all soldering joints and connections.** Flakey connections 30 | cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints. 31 | 32 | - **Ensure you are using an official Arduino or Adafruit board.** We can't 33 | guarantee a clone board will have the same functionality and work as expected 34 | with this code and don't support them. 35 | 36 | If you're sure this issue is a defect in the code and checked the steps above 37 | please fill in the following fields to provide enough troubleshooting information. 38 | You may delete the guideline and text above to just leave the following details: 39 | 40 | - Arduino board: **INSERT ARDUINO BOARD NAME/TYPE HERE** 41 | 42 | - Arduino IDE version (found in Arduino -> About Arduino menu): **INSERT ARDUINO 43 | VERSION HERE** 44 | 45 | - List the steps to reproduce the problem below (if possible attach a sketch or 46 | copy the sketch code in too): **LIST REPRO STEPS BELOW** 47 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thank you for creating a pull request to contribute to Adafruit's GitHub code! 2 | Before you open the request please review the following guidelines and tips to 3 | help it be more easily integrated: 4 | 5 | - **Describe the scope of your change--i.e. what the change does and what parts 6 | of the code were modified.** This will help us understand any risks of integrating 7 | the code. 8 | 9 | - **Describe any known limitations with your change.** For example if the change 10 | doesn't apply to a supported platform of the library please mention it. 11 | 12 | - **Please run any tests or examples that can exercise your modified code.** We 13 | strive to not break users of the code and running tests/examples helps with this 14 | process. 15 | 16 | Thank you again for contributing! We will try to test and integrate the change 17 | as soon as we can, but be aware we have many GitHub repositories to manage and 18 | can't immediately respond to every request. There is no need to bump or check in 19 | on a pull request (it will clutter the discussion of the request). 20 | 21 | Also don't be worried if the request is closed or not integrated--sometimes the 22 | priorities of Adafruit's GitHub code (education, ease of use) might not match the 23 | priorities of the pull request. Don't fret, the open source community thrives on 24 | forks and GitHub makes it easy to keep your changes in a forked repo. 25 | 26 | After reviewing the guidelines above you can delete this text from the pull request. 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.swo 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | sudo: false 3 | 4 | cache: 5 | directories: 6 | - ~/arduino_ide 7 | - ~/.arduino15/packages/ 8 | 9 | git: 10 | depth: false 11 | quiet: true 12 | 13 | env: 14 | global: 15 | - PRETTYNAME="Adafruit LSM303DLHC" 16 | 17 | before_install: 18 | - source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/install.sh) 19 | 20 | install: 21 | - arduino --install-library "Adafruit Unified Sensor" 22 | 23 | script: 24 | - build_main_platforms 25 | 26 | after_success: 27 | - source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/library_check.sh) 28 | -------------------------------------------------------------------------------- /Adafruit_LSM303.h: -------------------------------------------------------------------------------- 1 | // This file is provided for compatibility reasons with the deprecated 2 | // (non-Unified) Adafruit_LSM303 library. Any new development should use 3 | // the Adafruit_LSM303_U.h header, this file is provided to try to minimize 4 | // issues with projects that depend on the older driver. 5 | 6 | #ifndef __ADAFRUIT_LSM303_H__ 7 | #define __ADAFRUIT_LSM303_H__ 8 | 9 | #include "Adafruit_LSM303_U.h" 10 | 11 | #endif // __ADAFRUIT_LSM303_H__ 12 | -------------------------------------------------------------------------------- /Adafruit_LSM303_U.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | This is a library for the LSM303 Accelerometer and magnentometer/compass 3 | 4 | Designed specifically to work with the Adafruit LSM303DLHC Breakout 5 | 6 | These displays use I2C to communicate, 2 pins are required to interface. 7 | 8 | Adafruit invests time and resources providing this open source code, 9 | please support Adafruit andopen-source hardware by purchasing products 10 | from Adafruit! 11 | 12 | Written by Kevin Townsend for Adafruit Industries. 13 | BSD license, all text above must be included in any redistribution 14 | ***************************************************************************/ 15 | #if ARDUINO >= 100 16 | #include "Arduino.h" 17 | #else 18 | #include "WProgram.h" 19 | #endif 20 | 21 | #include 22 | 23 | #include 24 | 25 | #include "Adafruit_LSM303_U.h" 26 | 27 | /* enabling this #define will enable the debug print blocks 28 | #define LSM303_DEBUG 29 | */ 30 | 31 | static float _lsm303Accel_MG_LSB = 0.001F; // 1, 2, 4 or 12 mg per lsb 32 | static float _lsm303Mag_Gauss_LSB_XY = 1100.0F; // Varies with gain 33 | static float _lsm303Mag_Gauss_LSB_Z = 980.0F; // Varies with gain 34 | 35 | /*************************************************************************** 36 | ACCELEROMETER 37 | ***************************************************************************/ 38 | /*************************************************************************** 39 | PRIVATE FUNCTIONS 40 | ***************************************************************************/ 41 | 42 | /**************************************************************************/ 43 | /*! 44 | @brief Abstract away platform differences in Arduino wire library 45 | */ 46 | /**************************************************************************/ 47 | void Adafruit_LSM303_Accel_Unified::write8(byte address, byte reg, byte value) 48 | { 49 | Wire.beginTransmission(address); 50 | #if ARDUINO >= 100 51 | Wire.write((uint8_t)reg); 52 | Wire.write((uint8_t)value); 53 | #else 54 | Wire.send(reg); 55 | Wire.send(value); 56 | #endif 57 | Wire.endTransmission(); 58 | } 59 | 60 | /**************************************************************************/ 61 | /*! 62 | @brief Abstract away platform differences in Arduino wire library 63 | */ 64 | /**************************************************************************/ 65 | byte Adafruit_LSM303_Accel_Unified::read8(byte address, byte reg) 66 | { 67 | byte value; 68 | 69 | Wire.beginTransmission(address); 70 | #if ARDUINO >= 100 71 | Wire.write((uint8_t)reg); 72 | #else 73 | Wire.send(reg); 74 | #endif 75 | Wire.endTransmission(); 76 | Wire.requestFrom(address, (byte)1); 77 | #if ARDUINO >= 100 78 | value = Wire.read(); 79 | #else 80 | value = Wire.receive(); 81 | #endif 82 | Wire.endTransmission(); 83 | 84 | return value; 85 | } 86 | 87 | /**************************************************************************/ 88 | /*! 89 | @brief Reads the raw data from the sensor 90 | */ 91 | /**************************************************************************/ 92 | void Adafruit_LSM303_Accel_Unified::read() 93 | { 94 | // Read the accelerometer 95 | Wire.beginTransmission((byte)LSM303_ADDRESS_ACCEL); 96 | #if ARDUINO >= 100 97 | Wire.write(LSM303_REGISTER_ACCEL_OUT_X_L_A | 0x80); 98 | #else 99 | Wire.send(LSM303_REGISTER_ACCEL_OUT_X_L_A | 0x80); 100 | #endif 101 | Wire.endTransmission(); 102 | Wire.requestFrom((byte)LSM303_ADDRESS_ACCEL, (byte)6); 103 | 104 | // Wait around until enough data is available 105 | while (Wire.available() < 6); 106 | 107 | #if ARDUINO >= 100 108 | uint8_t xlo = Wire.read(); 109 | uint8_t xhi = Wire.read(); 110 | uint8_t ylo = Wire.read(); 111 | uint8_t yhi = Wire.read(); 112 | uint8_t zlo = Wire.read(); 113 | uint8_t zhi = Wire.read(); 114 | #else 115 | uint8_t xlo = Wire.receive(); 116 | uint8_t xhi = Wire.receive(); 117 | uint8_t ylo = Wire.receive(); 118 | uint8_t yhi = Wire.receive(); 119 | uint8_t zlo = Wire.receive(); 120 | uint8_t zhi = Wire.receive(); 121 | #endif 122 | 123 | // Shift values to create properly formed integer (low byte first) 124 | raw.x = (int16_t)(xlo | (xhi << 8)) >> 4; 125 | raw.y = (int16_t)(ylo | (yhi << 8)) >> 4; 126 | raw.z = (int16_t)(zlo | (zhi << 8)) >> 4; 127 | } 128 | 129 | /*************************************************************************** 130 | CONSTRUCTOR 131 | ***************************************************************************/ 132 | 133 | /**************************************************************************/ 134 | /*! 135 | @brief Instantiates a new Adafruit_LSM303 class 136 | */ 137 | /**************************************************************************/ 138 | Adafruit_LSM303_Accel_Unified::Adafruit_LSM303_Accel_Unified(int32_t sensorID) { 139 | _sensorID = sensorID; 140 | 141 | // Clear the raw accel data 142 | raw.x = 0; 143 | raw.y = 0; 144 | raw.z = 0; 145 | } 146 | 147 | /*************************************************************************** 148 | PUBLIC FUNCTIONS 149 | ***************************************************************************/ 150 | 151 | /**************************************************************************/ 152 | /*! 153 | @brief Setups the HW 154 | */ 155 | /**************************************************************************/ 156 | bool Adafruit_LSM303_Accel_Unified::begin() 157 | { 158 | // Enable I2C 159 | Wire.begin(); 160 | 161 | // Enable the accelerometer (100Hz) 162 | write8(LSM303_ADDRESS_ACCEL, LSM303_REGISTER_ACCEL_CTRL_REG1_A, 0x57); 163 | 164 | // LSM303DLHC has no WHOAMI register so read CTRL_REG1_A back to check 165 | // if we are connected or not 166 | uint8_t reg1_a = read8(LSM303_ADDRESS_ACCEL, LSM303_REGISTER_ACCEL_CTRL_REG1_A); 167 | if (reg1_a != 0x57) 168 | { 169 | return false; 170 | } 171 | 172 | return true; 173 | } 174 | 175 | /**************************************************************************/ 176 | /*! 177 | @brief Gets the most recent sensor event 178 | */ 179 | /**************************************************************************/ 180 | bool Adafruit_LSM303_Accel_Unified::getEvent(sensors_event_t *event) { 181 | /* Clear the event */ 182 | memset(event, 0, sizeof(sensors_event_t)); 183 | 184 | /* Read new data */ 185 | read(); 186 | 187 | event->version = sizeof(sensors_event_t); 188 | event->sensor_id = _sensorID; 189 | event->type = SENSOR_TYPE_ACCELEROMETER; 190 | event->timestamp = millis(); 191 | event->acceleration.x = (float)raw.x * _lsm303Accel_MG_LSB * SENSORS_GRAVITY_STANDARD; 192 | event->acceleration.y = (float)raw.y * _lsm303Accel_MG_LSB * SENSORS_GRAVITY_STANDARD; 193 | event->acceleration.z = (float)raw.z * _lsm303Accel_MG_LSB * SENSORS_GRAVITY_STANDARD; 194 | 195 | return true; 196 | } 197 | 198 | /**************************************************************************/ 199 | /*! 200 | @brief Gets the sensor_t data 201 | */ 202 | /**************************************************************************/ 203 | void Adafruit_LSM303_Accel_Unified::getSensor(sensor_t *sensor) { 204 | /* Clear the sensor_t object */ 205 | memset(sensor, 0, sizeof(sensor_t)); 206 | 207 | /* Insert the sensor name in the fixed length char array */ 208 | strncpy (sensor->name, "LSM303", sizeof(sensor->name) - 1); 209 | sensor->name[sizeof(sensor->name)- 1] = 0; 210 | sensor->version = 1; 211 | sensor->sensor_id = _sensorID; 212 | sensor->type = SENSOR_TYPE_ACCELEROMETER; 213 | sensor->min_delay = 0; 214 | sensor->max_value = 0.0F; // TBD 215 | sensor->min_value = 0.0F; // TBD 216 | sensor->resolution = 0.0F; // TBD 217 | } 218 | 219 | /*************************************************************************** 220 | MAGNETOMETER 221 | ***************************************************************************/ 222 | /*************************************************************************** 223 | PRIVATE FUNCTIONS 224 | ***************************************************************************/ 225 | 226 | /**************************************************************************/ 227 | /*! 228 | @brief Abstract away platform differences in Arduino wire library 229 | */ 230 | /**************************************************************************/ 231 | void Adafruit_LSM303_Mag_Unified::write8(byte address, byte reg, byte value) 232 | { 233 | Wire.beginTransmission(address); 234 | #if ARDUINO >= 100 235 | Wire.write((uint8_t)reg); 236 | Wire.write((uint8_t)value); 237 | #else 238 | Wire.send(reg); 239 | Wire.send(value); 240 | #endif 241 | Wire.endTransmission(); 242 | } 243 | 244 | /**************************************************************************/ 245 | /*! 246 | @brief Abstract away platform differences in Arduino wire library 247 | */ 248 | /**************************************************************************/ 249 | byte Adafruit_LSM303_Mag_Unified::read8(byte address, byte reg) 250 | { 251 | byte value; 252 | 253 | Wire.beginTransmission(address); 254 | #if ARDUINO >= 100 255 | Wire.write((uint8_t)reg); 256 | #else 257 | Wire.send(reg); 258 | #endif 259 | Wire.endTransmission(); 260 | Wire.requestFrom(address, (byte)1); 261 | #if ARDUINO >= 100 262 | value = Wire.read(); 263 | #else 264 | value = Wire.receive(); 265 | #endif 266 | Wire.endTransmission(); 267 | 268 | return value; 269 | } 270 | 271 | /**************************************************************************/ 272 | /*! 273 | @brief Reads the raw data from the sensor 274 | */ 275 | /**************************************************************************/ 276 | void Adafruit_LSM303_Mag_Unified::read() 277 | { 278 | // Read the magnetometer 279 | Wire.beginTransmission((byte)LSM303_ADDRESS_MAG); 280 | #if ARDUINO >= 100 281 | Wire.write(LSM303_REGISTER_MAG_OUT_X_H_M); 282 | #else 283 | Wire.send(LSM303_REGISTER_MAG_OUT_X_H_M); 284 | #endif 285 | Wire.endTransmission(); 286 | Wire.requestFrom((byte)LSM303_ADDRESS_MAG, (byte)6); 287 | 288 | // Wait around until enough data is available 289 | while (Wire.available() < 6); 290 | 291 | // Note high before low (different than accel) 292 | #if ARDUINO >= 100 293 | uint8_t xhi = Wire.read(); 294 | uint8_t xlo = Wire.read(); 295 | uint8_t zhi = Wire.read(); 296 | uint8_t zlo = Wire.read(); 297 | uint8_t yhi = Wire.read(); 298 | uint8_t ylo = Wire.read(); 299 | #else 300 | uint8_t xhi = Wire.receive(); 301 | uint8_t xlo = Wire.receive(); 302 | uint8_t zhi = Wire.receive(); 303 | uint8_t zlo = Wire.receive(); 304 | uint8_t yhi = Wire.receive(); 305 | uint8_t ylo = Wire.receive(); 306 | #endif 307 | 308 | // Shift values to create properly formed integer (low byte first) 309 | raw.x = (int16_t)(xlo | ((int16_t)xhi << 8)); 310 | raw.y = (int16_t)(ylo | ((int16_t)yhi << 8)); 311 | raw.z = (int16_t)(zlo | ((int16_t)zhi << 8)); 312 | } 313 | 314 | /*************************************************************************** 315 | CONSTRUCTOR 316 | ***************************************************************************/ 317 | 318 | /**************************************************************************/ 319 | /*! 320 | @brief Instantiates a new Adafruit_LSM303 class 321 | */ 322 | /**************************************************************************/ 323 | Adafruit_LSM303_Mag_Unified::Adafruit_LSM303_Mag_Unified(int32_t sensorID) { 324 | _sensorID = sensorID; 325 | autoRangeEnabled = false; 326 | 327 | // Clear the raw mag data 328 | raw.x = 0; 329 | raw.y = 0; 330 | raw.z = 0; 331 | } 332 | 333 | /*************************************************************************** 334 | PUBLIC FUNCTIONS 335 | ***************************************************************************/ 336 | 337 | /**************************************************************************/ 338 | /*! 339 | @brief Setups the HW 340 | */ 341 | /**************************************************************************/ 342 | bool Adafruit_LSM303_Mag_Unified::begin() 343 | { 344 | // Enable I2C 345 | Wire.begin(); 346 | 347 | // Enable the magnetometer 348 | write8(LSM303_ADDRESS_MAG, LSM303_REGISTER_MAG_MR_REG_M, 0x00); 349 | 350 | // LSM303DLHC has no WHOAMI register so read CRA_REG_M to check 351 | // the default value (0b00010000/0x10) 352 | uint8_t reg1_a = read8(LSM303_ADDRESS_MAG, LSM303_REGISTER_MAG_CRA_REG_M); 353 | if (reg1_a != 0x10) 354 | { 355 | return false; 356 | } 357 | 358 | // Set the gain to a known level 359 | setMagGain(LSM303_MAGGAIN_1_3); 360 | 361 | return true; 362 | } 363 | 364 | /**************************************************************************/ 365 | /*! 366 | @brief Enables or disables auto-ranging 367 | */ 368 | /**************************************************************************/ 369 | void Adafruit_LSM303_Mag_Unified::enableAutoRange(bool enabled) 370 | { 371 | autoRangeEnabled = enabled; 372 | } 373 | 374 | /**************************************************************************/ 375 | /*! 376 | @brief Sets the magnetometer's gain 377 | */ 378 | /**************************************************************************/ 379 | void Adafruit_LSM303_Mag_Unified::setMagGain(lsm303MagGain gain) 380 | { 381 | write8(LSM303_ADDRESS_MAG, LSM303_REGISTER_MAG_CRB_REG_M, (byte)gain); 382 | 383 | magGain = gain; 384 | 385 | switch(gain) 386 | { 387 | case LSM303_MAGGAIN_1_3: 388 | _lsm303Mag_Gauss_LSB_XY = 1100; 389 | _lsm303Mag_Gauss_LSB_Z = 980; 390 | break; 391 | case LSM303_MAGGAIN_1_9: 392 | _lsm303Mag_Gauss_LSB_XY = 855; 393 | _lsm303Mag_Gauss_LSB_Z = 760; 394 | break; 395 | case LSM303_MAGGAIN_2_5: 396 | _lsm303Mag_Gauss_LSB_XY = 670; 397 | _lsm303Mag_Gauss_LSB_Z = 600; 398 | break; 399 | case LSM303_MAGGAIN_4_0: 400 | _lsm303Mag_Gauss_LSB_XY = 450; 401 | _lsm303Mag_Gauss_LSB_Z = 400; 402 | break; 403 | case LSM303_MAGGAIN_4_7: 404 | _lsm303Mag_Gauss_LSB_XY = 400; 405 | _lsm303Mag_Gauss_LSB_Z = 355; 406 | break; 407 | case LSM303_MAGGAIN_5_6: 408 | _lsm303Mag_Gauss_LSB_XY = 330; 409 | _lsm303Mag_Gauss_LSB_Z = 295; 410 | break; 411 | case LSM303_MAGGAIN_8_1: 412 | _lsm303Mag_Gauss_LSB_XY = 230; 413 | _lsm303Mag_Gauss_LSB_Z = 205; 414 | break; 415 | } 416 | } 417 | 418 | /**************************************************************************/ 419 | /*! 420 | @brief Sets the magnetometer's update rate 421 | */ 422 | /**************************************************************************/ 423 | void Adafruit_LSM303_Mag_Unified::setMagRate(lsm303MagRate rate) 424 | { 425 | byte reg_m = ((byte)rate & 0x07) << 2; 426 | write8(LSM303_ADDRESS_MAG, LSM303_REGISTER_MAG_CRA_REG_M, reg_m); 427 | } 428 | 429 | 430 | /**************************************************************************/ 431 | /*! 432 | @brief Gets the most recent sensor event 433 | */ 434 | /**************************************************************************/ 435 | bool Adafruit_LSM303_Mag_Unified::getEvent(sensors_event_t *event) { 436 | bool readingValid = false; 437 | 438 | /* Clear the event */ 439 | memset(event, 0, sizeof(sensors_event_t)); 440 | 441 | while(!readingValid) 442 | { 443 | 444 | uint8_t reg_mg = read8(LSM303_ADDRESS_MAG, LSM303_REGISTER_MAG_SR_REG_Mg); 445 | if (!(reg_mg & 0x1)) { 446 | return false; 447 | } 448 | 449 | /* Read new data */ 450 | read(); 451 | 452 | /* Make sure the sensor isn't saturating if auto-ranging is enabled */ 453 | if (!autoRangeEnabled) 454 | { 455 | readingValid = true; 456 | } 457 | else 458 | { 459 | #ifdef LSM303_DEBUG 460 | Serial.print(raw.x); Serial.print(" "); 461 | Serial.print(raw.y); Serial.print(" "); 462 | Serial.print(raw.z); Serial.println(" "); 463 | #endif 464 | /* Check if the sensor is saturating or not */ 465 | if ( (raw.x >= 2040) | (raw.x <= -2040) | 466 | (raw.y >= 2040) | (raw.y <= -2040) | 467 | (raw.z >= 2040) | (raw.z <= -2040) ) 468 | { 469 | /* Saturating .... increase the range if we can */ 470 | switch(magGain) 471 | { 472 | case LSM303_MAGGAIN_5_6: 473 | setMagGain(LSM303_MAGGAIN_8_1); 474 | readingValid = false; 475 | #ifdef LSM303_DEBUG 476 | Serial.println("Changing range to +/- 8.1"); 477 | #endif 478 | break; 479 | case LSM303_MAGGAIN_4_7: 480 | setMagGain(LSM303_MAGGAIN_5_6); 481 | readingValid = false; 482 | #ifdef LSM303_DEBUG 483 | Serial.println("Changing range to +/- 5.6"); 484 | #endif 485 | break; 486 | case LSM303_MAGGAIN_4_0: 487 | setMagGain(LSM303_MAGGAIN_4_7); 488 | readingValid = false; 489 | #ifdef LSM303_DEBUG 490 | Serial.println("Changing range to +/- 4.7"); 491 | #endif 492 | break; 493 | case LSM303_MAGGAIN_2_5: 494 | setMagGain(LSM303_MAGGAIN_4_0); 495 | readingValid = false; 496 | #ifdef LSM303_DEBUG 497 | Serial.println("Changing range to +/- 4.0"); 498 | #endif 499 | break; 500 | case LSM303_MAGGAIN_1_9: 501 | setMagGain(LSM303_MAGGAIN_2_5); 502 | readingValid = false; 503 | #ifdef LSM303_DEBUG 504 | Serial.println("Changing range to +/- 2.5"); 505 | #endif 506 | break; 507 | case LSM303_MAGGAIN_1_3: 508 | setMagGain(LSM303_MAGGAIN_1_9); 509 | readingValid = false; 510 | #ifdef LSM303_DEBUG 511 | Serial.println("Changing range to +/- 1.9"); 512 | #endif 513 | break; 514 | default: 515 | readingValid = true; 516 | break; 517 | } 518 | } 519 | else 520 | { 521 | /* All values are withing range */ 522 | readingValid = true; 523 | } 524 | } 525 | } 526 | 527 | event->version = sizeof(sensors_event_t); 528 | event->sensor_id = _sensorID; 529 | event->type = SENSOR_TYPE_MAGNETIC_FIELD; 530 | event->timestamp = millis(); 531 | event->magnetic.x = (float)raw.x / _lsm303Mag_Gauss_LSB_XY * SENSORS_GAUSS_TO_MICROTESLA; 532 | event->magnetic.y = (float)raw.y / _lsm303Mag_Gauss_LSB_XY * SENSORS_GAUSS_TO_MICROTESLA; 533 | event->magnetic.z = (float)raw.z / _lsm303Mag_Gauss_LSB_Z * SENSORS_GAUSS_TO_MICROTESLA; 534 | 535 | return true; 536 | } 537 | 538 | /**************************************************************************/ 539 | /*! 540 | @brief Gets the sensor_t data 541 | */ 542 | /**************************************************************************/ 543 | void Adafruit_LSM303_Mag_Unified::getSensor(sensor_t *sensor) { 544 | /* Clear the sensor_t object */ 545 | memset(sensor, 0, sizeof(sensor_t)); 546 | 547 | /* Insert the sensor name in the fixed length char array */ 548 | strncpy (sensor->name, "LSM303", sizeof(sensor->name) - 1); 549 | sensor->name[sizeof(sensor->name)- 1] = 0; 550 | sensor->version = 1; 551 | sensor->sensor_id = _sensorID; 552 | sensor->type = SENSOR_TYPE_MAGNETIC_FIELD; 553 | sensor->min_delay = 0; 554 | sensor->max_value = 0.0F; // TBD 555 | sensor->min_value = 0.0F; // TBD 556 | sensor->resolution = 0.0F; // TBD 557 | } 558 | 559 | /* --- The code below is no longer maintained and provided solely for */ 560 | /* --- compatibility reasons! */ 561 | 562 | /*************************************************************************** 563 | DEPRECATED (NON UNIFIED) DRIVER (Adafruit_LSM303.c/h) 564 | ***************************************************************************/ 565 | 566 | /*************************************************************************** 567 | CONSTRUCTOR 568 | ***************************************************************************/ 569 | bool Adafruit_LSM303::begin() 570 | { 571 | Wire.begin(); 572 | 573 | // Enable the accelerometer 574 | write8(LSM303_ADDRESS_ACCEL, LSM303_REGISTER_ACCEL_CTRL_REG1_A, 0x27); 575 | 576 | // Enable the magnetometer 577 | write8(LSM303_ADDRESS_MAG, LSM303_REGISTER_MAG_MR_REG_M, 0x00); 578 | 579 | return true; 580 | } 581 | 582 | /*************************************************************************** 583 | PUBLIC FUNCTIONS 584 | ***************************************************************************/ 585 | void Adafruit_LSM303::read() 586 | { 587 | // Read the accelerometer 588 | Wire.beginTransmission((byte)LSM303_ADDRESS_ACCEL); 589 | Wire.write(LSM303_REGISTER_ACCEL_OUT_X_L_A | 0x80); 590 | Wire.endTransmission(); 591 | Wire.requestFrom((byte)LSM303_ADDRESS_ACCEL, (byte)6); 592 | 593 | // Wait around until enough data is available 594 | while (Wire.available() < 6); 595 | 596 | uint8_t xlo = Wire.read(); 597 | uint8_t xhi = Wire.read(); 598 | uint8_t ylo = Wire.read(); 599 | uint8_t yhi = Wire.read(); 600 | uint8_t zlo = Wire.read(); 601 | uint8_t zhi = Wire.read(); 602 | 603 | // Shift values to create properly formed integer (low byte first) 604 | accelData.x = (int16_t)((uint16_t)xlo | ((uint16_t)xhi << 8)) >> 4; 605 | accelData.y = (int16_t)((uint16_t)ylo | ((uint16_t)yhi << 8)) >> 4; 606 | accelData.z = (int16_t)((uint16_t)zlo | ((uint16_t)zhi << 8)) >> 4; 607 | 608 | // Read the magnetometer 609 | Wire.beginTransmission((byte)LSM303_ADDRESS_MAG); 610 | Wire.write(LSM303_REGISTER_MAG_OUT_X_H_M); 611 | Wire.endTransmission(); 612 | Wire.requestFrom((byte)LSM303_ADDRESS_MAG, (byte)6); 613 | 614 | // Wait around until enough data is available 615 | while (Wire.available() < 6); 616 | 617 | // Note high before low (different than accel) 618 | xhi = Wire.read(); 619 | xlo = Wire.read(); 620 | zhi = Wire.read(); 621 | zlo = Wire.read(); 622 | yhi = Wire.read(); 623 | ylo = Wire.read(); 624 | 625 | // Shift values to create properly formed integer (low byte first) 626 | magData.x = (int16_t)((uint16_t)xlo | ((uint16_t)xhi << 8)); 627 | magData.y = (int16_t)((uint16_t)ylo | ((uint16_t)yhi << 8)); 628 | magData.z = (int16_t)((uint16_t)zlo | ((uint16_t)zhi << 8)); 629 | } 630 | 631 | void Adafruit_LSM303::setMagGain(lsm303MagGain gain) 632 | { 633 | write8(LSM303_ADDRESS_MAG, LSM303_REGISTER_MAG_CRB_REG_M, (byte)gain); 634 | } 635 | 636 | /*************************************************************************** 637 | PRIVATE FUNCTIONS 638 | ***************************************************************************/ 639 | void Adafruit_LSM303::write8(byte address, byte reg, byte value) 640 | { 641 | Wire.beginTransmission(address); 642 | Wire.write(reg); 643 | Wire.write(value); 644 | Wire.endTransmission(); 645 | } 646 | 647 | byte Adafruit_LSM303::read8(byte address, byte reg) 648 | { 649 | byte value; 650 | 651 | Wire.beginTransmission(address); 652 | Wire.write(reg); 653 | Wire.endTransmission(); 654 | Wire.requestFrom(address, (byte)1); 655 | value = Wire.read(); 656 | Wire.endTransmission(); 657 | 658 | return value; 659 | } 660 | -------------------------------------------------------------------------------- /Adafruit_LSM303_U.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | This is a library for the LSM303 Accelerometer and magnentometer/compass 3 | 4 | Designed specifically to work with the Adafruit LSM303DLHC Breakout 5 | 6 | These displays use I2C to communicate, 2 pins are required to interface. 7 | 8 | Adafruit invests time and resources providing this open source code, 9 | please support Adafruit andopen-source hardware by purchasing products 10 | from Adafruit! 11 | 12 | Written by Kevin Townsend for Adafruit Industries. 13 | BSD license, all text above must be included in any redistribution 14 | ***************************************************************************/ 15 | #ifndef __LSM303_H__ 16 | #define __LSM303_H__ 17 | 18 | #if (ARDUINO >= 100) 19 | #include "Arduino.h" 20 | #else 21 | #include "WProgram.h" 22 | #endif 23 | 24 | #include 25 | #include 26 | 27 | 28 | /*========================================================================= 29 | I2C ADDRESS/BITS 30 | -----------------------------------------------------------------------*/ 31 | #define LSM303_ADDRESS_ACCEL (0x32 >> 1) // 0011001x 32 | #define LSM303_ADDRESS_MAG (0x3C >> 1) // 0011110x 33 | /*=========================================================================*/ 34 | 35 | /*========================================================================= 36 | REGISTERS 37 | -----------------------------------------------------------------------*/ 38 | typedef enum 39 | { // DEFAULT TYPE 40 | LSM303_REGISTER_ACCEL_CTRL_REG1_A = 0x20, // 00000111 rw 41 | LSM303_REGISTER_ACCEL_CTRL_REG2_A = 0x21, // 00000000 rw 42 | LSM303_REGISTER_ACCEL_CTRL_REG3_A = 0x22, // 00000000 rw 43 | LSM303_REGISTER_ACCEL_CTRL_REG4_A = 0x23, // 00000000 rw 44 | LSM303_REGISTER_ACCEL_CTRL_REG5_A = 0x24, // 00000000 rw 45 | LSM303_REGISTER_ACCEL_CTRL_REG6_A = 0x25, // 00000000 rw 46 | LSM303_REGISTER_ACCEL_REFERENCE_A = 0x26, // 00000000 r 47 | LSM303_REGISTER_ACCEL_STATUS_REG_A = 0x27, // 00000000 r 48 | LSM303_REGISTER_ACCEL_OUT_X_L_A = 0x28, 49 | LSM303_REGISTER_ACCEL_OUT_X_H_A = 0x29, 50 | LSM303_REGISTER_ACCEL_OUT_Y_L_A = 0x2A, 51 | LSM303_REGISTER_ACCEL_OUT_Y_H_A = 0x2B, 52 | LSM303_REGISTER_ACCEL_OUT_Z_L_A = 0x2C, 53 | LSM303_REGISTER_ACCEL_OUT_Z_H_A = 0x2D, 54 | LSM303_REGISTER_ACCEL_FIFO_CTRL_REG_A = 0x2E, 55 | LSM303_REGISTER_ACCEL_FIFO_SRC_REG_A = 0x2F, 56 | LSM303_REGISTER_ACCEL_INT1_CFG_A = 0x30, 57 | LSM303_REGISTER_ACCEL_INT1_SOURCE_A = 0x31, 58 | LSM303_REGISTER_ACCEL_INT1_THS_A = 0x32, 59 | LSM303_REGISTER_ACCEL_INT1_DURATION_A = 0x33, 60 | LSM303_REGISTER_ACCEL_INT2_CFG_A = 0x34, 61 | LSM303_REGISTER_ACCEL_INT2_SOURCE_A = 0x35, 62 | LSM303_REGISTER_ACCEL_INT2_THS_A = 0x36, 63 | LSM303_REGISTER_ACCEL_INT2_DURATION_A = 0x37, 64 | LSM303_REGISTER_ACCEL_CLICK_CFG_A = 0x38, 65 | LSM303_REGISTER_ACCEL_CLICK_SRC_A = 0x39, 66 | LSM303_REGISTER_ACCEL_CLICK_THS_A = 0x3A, 67 | LSM303_REGISTER_ACCEL_TIME_LIMIT_A = 0x3B, 68 | LSM303_REGISTER_ACCEL_TIME_LATENCY_A = 0x3C, 69 | LSM303_REGISTER_ACCEL_TIME_WINDOW_A = 0x3D 70 | } lsm303AccelRegisters_t; 71 | 72 | typedef enum 73 | { 74 | LSM303_REGISTER_MAG_CRA_REG_M = 0x00, 75 | LSM303_REGISTER_MAG_CRB_REG_M = 0x01, 76 | LSM303_REGISTER_MAG_MR_REG_M = 0x02, 77 | LSM303_REGISTER_MAG_OUT_X_H_M = 0x03, 78 | LSM303_REGISTER_MAG_OUT_X_L_M = 0x04, 79 | LSM303_REGISTER_MAG_OUT_Z_H_M = 0x05, 80 | LSM303_REGISTER_MAG_OUT_Z_L_M = 0x06, 81 | LSM303_REGISTER_MAG_OUT_Y_H_M = 0x07, 82 | LSM303_REGISTER_MAG_OUT_Y_L_M = 0x08, 83 | LSM303_REGISTER_MAG_SR_REG_Mg = 0x09, 84 | LSM303_REGISTER_MAG_IRA_REG_M = 0x0A, 85 | LSM303_REGISTER_MAG_IRB_REG_M = 0x0B, 86 | LSM303_REGISTER_MAG_IRC_REG_M = 0x0C, 87 | LSM303_REGISTER_MAG_TEMP_OUT_H_M = 0x31, 88 | LSM303_REGISTER_MAG_TEMP_OUT_L_M = 0x32 89 | } lsm303MagRegisters_t; 90 | /*=========================================================================*/ 91 | 92 | /*========================================================================= 93 | MAGNETOMETER GAIN SETTINGS 94 | -----------------------------------------------------------------------*/ 95 | typedef enum 96 | { 97 | LSM303_MAGGAIN_1_3 = 0x20, // +/- 1.3 98 | LSM303_MAGGAIN_1_9 = 0x40, // +/- 1.9 99 | LSM303_MAGGAIN_2_5 = 0x60, // +/- 2.5 100 | LSM303_MAGGAIN_4_0 = 0x80, // +/- 4.0 101 | LSM303_MAGGAIN_4_7 = 0xA0, // +/- 4.7 102 | LSM303_MAGGAIN_5_6 = 0xC0, // +/- 5.6 103 | LSM303_MAGGAIN_8_1 = 0xE0 // +/- 8.1 104 | } lsm303MagGain; 105 | /*=========================================================================*/ 106 | 107 | /*========================================================================= 108 | MAGNETOMETER UPDATE RATE SETTINGS 109 | -----------------------------------------------------------------------*/ 110 | typedef enum 111 | { 112 | LSM303_MAGRATE_0_7 = 0x00, // 0.75 Hz 113 | LSM303_MAGRATE_1_5 = 0x01, // 1.5 Hz 114 | LSM303_MAGRATE_3_0 = 0x62, // 3.0 Hz 115 | LSM303_MAGRATE_7_5 = 0x03, // 7.5 Hz 116 | LSM303_MAGRATE_15 = 0x04, // 15 Hz 117 | LSM303_MAGRATE_30 = 0x05, // 30 Hz 118 | LSM303_MAGRATE_75 = 0x06, // 75 Hz 119 | LSM303_MAGRATE_220 = 0x07 // 200 Hz 120 | } lsm303MagRate; 121 | /*=========================================================================*/ 122 | 123 | /*========================================================================= 124 | INTERNAL MAGNETOMETER DATA TYPE 125 | -----------------------------------------------------------------------*/ 126 | typedef struct lsm303MagData_s 127 | { 128 | int16_t x; 129 | int16_t y; 130 | int16_t z; 131 | } lsm303MagData; 132 | /*=========================================================================*/ 133 | 134 | /*========================================================================= 135 | INTERNAL ACCELERATION DATA TYPE 136 | -----------------------------------------------------------------------*/ 137 | typedef struct lsm303AccelData_s 138 | { 139 | int16_t x; 140 | int16_t y; 141 | int16_t z; 142 | } lsm303AccelData; 143 | /*=========================================================================*/ 144 | 145 | /*========================================================================= 146 | CHIP ID 147 | -----------------------------------------------------------------------*/ 148 | #define LSM303_ID (0b11010100) 149 | /*=========================================================================*/ 150 | 151 | /* Unified sensor driver for the accelerometer */ 152 | class Adafruit_LSM303_Accel_Unified : public Adafruit_Sensor 153 | { 154 | public: 155 | Adafruit_LSM303_Accel_Unified(int32_t sensorID = -1); 156 | 157 | bool begin(void); 158 | bool getEvent(sensors_event_t*); 159 | void getSensor(sensor_t*); 160 | 161 | lsm303AccelData raw; // Last read accelerometer data will be available here 162 | 163 | private: 164 | int32_t _sensorID; 165 | 166 | void write8(byte address, byte reg, byte value); 167 | byte read8(byte address, byte reg); 168 | void read(void); 169 | }; 170 | 171 | /* Unified sensor driver for the magnetometer */ 172 | class Adafruit_LSM303_Mag_Unified : public Adafruit_Sensor 173 | { 174 | public: 175 | Adafruit_LSM303_Mag_Unified(int32_t sensorID = -1); 176 | 177 | bool begin(void); 178 | void enableAutoRange(bool enable); 179 | void setMagGain(lsm303MagGain gain); 180 | void setMagRate(lsm303MagRate rate); 181 | bool getEvent(sensors_event_t*); 182 | void getSensor(sensor_t*); 183 | 184 | lsm303MagData raw; // Last read magnetometer data will be available here 185 | lsm303MagGain magGain; 186 | bool autoRangeEnabled; 187 | 188 | private: 189 | int32_t _sensorID; 190 | 191 | void write8(byte address, byte reg, byte value); 192 | byte read8(byte address, byte reg); 193 | void read(void); 194 | }; 195 | 196 | /* Non Unified (old) driver for compatibility reasons */ 197 | class Adafruit_LSM303 198 | { 199 | public: 200 | bool begin(void); 201 | void read(void); 202 | void setMagGain(lsm303MagGain gain); 203 | 204 | lsm303AccelData accelData; // Last read accelerometer data will be available here 205 | lsm303MagData magData; // Last read magnetometer data will be available here 206 | 207 | void write8(byte address, byte reg, byte value); 208 | byte read8(byte address, byte reg); 209 | }; 210 | 211 | #endif 212 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Adafruit LSM303DLHC Driver (Accelerometer + Magnetometer) 2 | 3 | This library has been replaced by the following libraries and will no longer be supported. Please switch to the new libraries. 4 | 5 | [Adafruit_LSM303_Accel](https://github.com/adafruit/Adafruit_LSM303_Accel) for the accelerometer and 6 | 7 | [Adafruit_LSM303DLH_Mag](https://github.com/adafruit/Adafruit_LSM303DLH_Mag) for the magnetometer. 8 | 9 | To use the new libraries, consult [the LSM303 guide on the Adafruit Learning System](https://learn.adafruit.com/lsm303-accelerometer-slash-compass-breakout/coding) for more info 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/accelsensor/accelsensor.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* Assign a unique ID to this sensor at the same time */ 6 | Adafruit_LSM303_Accel_Unified accel = Adafruit_LSM303_Accel_Unified(54321); 7 | 8 | void displaySensorDetails(void) 9 | { 10 | sensor_t sensor; 11 | accel.getSensor(&sensor); 12 | Serial.println("------------------------------------"); 13 | Serial.print ("Sensor: "); Serial.println(sensor.name); 14 | Serial.print ("Driver Ver: "); Serial.println(sensor.version); 15 | Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id); 16 | Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" m/s^2"); 17 | Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" m/s^2"); 18 | Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" m/s^2"); 19 | Serial.println("------------------------------------"); 20 | Serial.println(""); 21 | delay(500); 22 | } 23 | 24 | void setup(void) 25 | { 26 | #ifndef ESP8266 27 | while (!Serial); // will pause Zero, Leonardo, etc until serial console opens 28 | #endif 29 | Serial.begin(9600); 30 | Serial.println("Accelerometer Test"); Serial.println(""); 31 | 32 | /* Initialise the sensor */ 33 | if(!accel.begin()) 34 | { 35 | /* There was a problem detecting the ADXL345 ... check your connections */ 36 | Serial.println("Ooops, no LSM303 detected ... Check your wiring!"); 37 | while(1); 38 | } 39 | 40 | /* Display some basic information on this sensor */ 41 | displaySensorDetails(); 42 | } 43 | 44 | void loop(void) 45 | { 46 | /* Get a new sensor event */ 47 | sensors_event_t event; 48 | accel.getEvent(&event); 49 | 50 | /* Display the results (acceleration is measured in m/s^2) */ 51 | Serial.print("X: "); Serial.print(event.acceleration.x); Serial.print(" "); 52 | Serial.print("Y: "); Serial.print(event.acceleration.y); Serial.print(" "); 53 | Serial.print("Z: "); Serial.print(event.acceleration.z); Serial.print(" ");Serial.println("m/s^2 "); 54 | 55 | /* Note: You can also get the raw (non unified values) for */ 56 | /* the last data sample as follows. The .getEvent call populates */ 57 | /* the raw values used below. */ 58 | //Serial.print("X Raw: "); Serial.print(accel.raw.x); Serial.print(" "); 59 | //Serial.print("Y Raw: "); Serial.print(accel.raw.y); Serial.print(" "); 60 | //Serial.print("Z Raw: "); Serial.print(accel.raw.z); Serial.println(""); 61 | 62 | /* Delay before the next sample */ 63 | delay(500); 64 | } 65 | -------------------------------------------------------------------------------- /examples/magsensor/magsensor.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* Assign a unique ID to this sensor at the same time */ 6 | Adafruit_LSM303_Mag_Unified mag = Adafruit_LSM303_Mag_Unified(12345); 7 | 8 | void displaySensorDetails(void) 9 | { 10 | sensor_t sensor; 11 | mag.getSensor(&sensor); 12 | Serial.println("------------------------------------"); 13 | Serial.print ("Sensor: "); Serial.println(sensor.name); 14 | Serial.print ("Driver Ver: "); Serial.println(sensor.version); 15 | Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id); 16 | Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" uT"); 17 | Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" uT"); 18 | Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" uT"); 19 | Serial.println("------------------------------------"); 20 | Serial.println(""); 21 | delay(500); 22 | } 23 | 24 | void setup(void) 25 | { 26 | #ifndef ESP8266 27 | while (!Serial); // will pause Zero, Leonardo, etc until serial console opens 28 | #endif 29 | Serial.begin(9600); 30 | Serial.println("Magnetometer Test"); Serial.println(""); 31 | 32 | /* Enable auto-gain */ 33 | mag.enableAutoRange(true); 34 | 35 | /* Initialise the sensor */ 36 | if(!mag.begin()) 37 | { 38 | /* There was a problem detecting the LSM303 ... check your connections */ 39 | Serial.println("Ooops, no LSM303 detected ... Check your wiring!"); 40 | while(1); 41 | } 42 | 43 | /* Display some basic information on this sensor */ 44 | displaySensorDetails(); 45 | } 46 | 47 | void loop(void) 48 | { 49 | /* Get a new sensor event */ 50 | sensors_event_t event; 51 | mag.getEvent(&event); 52 | 53 | /* Display the results (magnetic vector values are in micro-Tesla (uT)) */ 54 | Serial.print("X: "); Serial.print(event.magnetic.x); Serial.print(" "); 55 | Serial.print("Y: "); Serial.print(event.magnetic.y); Serial.print(" "); 56 | Serial.print("Z: "); Serial.print(event.magnetic.z); Serial.print(" ");Serial.println("uT"); 57 | 58 | /* Note: You can also get the raw (non unified values) for */ 59 | /* the last data sample as follows. The .getEvent call populates */ 60 | /* the raw values used below. */ 61 | // Serial.print("X Raw: "); Serial.print(mag.raw.x); Serial.print(" "); 62 | // Serial.print("Y Raw: "); Serial.print(mag.raw.y); Serial.print(" "); 63 | // Serial.print("Z Raw: "); Serial.print(mag.raw.z); Serial.println(""); 64 | 65 | /* Delay before the next sample */ 66 | delay(500); 67 | } 68 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=Adafruit LSM303DLHC 2 | version=1.0.4 3 | author=Adafruit 4 | maintainer=Adafruit 5 | sentence=Unified sensor driver for Adafruit's LSM303 Breakout (Accelerometer + Magnetometer) 6 | paragraph=Unified sensor driver for Adafruit's LSM303 Breakout (Accelerometer + Magnetometer) 7 | category=Sensors 8 | url=https://github.com/adafruit/Adafruit_LSM303DLHC 9 | architectures=* 10 | depends=Adafruit Unified Sensor 11 | --------------------------------------------------------------------------------