Driver for the LSM303D digital compass. Permits access to all LSM303D registers by name, including multi-byte register sets, and has convenience methods for floating-point accelerometer and magnetometer reads scaled according to the device settings. Written from scratch for Mbed 6.0

Dependents:   UoY-32C-lab8-exercise UoY-32C-lab5-lsm303d

Driver for the LSM303D digital compass

Permits access to all LSM303D registers by name, including multi-byte register sets. Convenience methods are included for sensor reads, including floating-point accelerometer and magnetometer reads scaled according to the device settings, and for the more common settings (data rates and scales).

I2C connection only. Written from scratch for Mbed 6.0.

The interface is subject to minor changes with each version. Deprecation warnings will be issued where possible.

Defaults

The class constructor checks that an LSM303D is present on the I2C bus, then enables all sensors. The accelerometer and magnetometer update rates are both set to 50Hz, and the scales are left at their device defaults of +-2g for the accelerometer and +-4gauss for the magnetometer.

Basic usage

Some usage examples

#include "lsm303d.h"

LSM303D lsm303d(D14, D15);  // SDA and SCL pins for I2C

lsm303d.setAccelScale(LSM303D::AccelScale::scale_4g); // set +-4g range

lsm303d.INT1_enable_DRDY_A(); // set DRDY_A bit in CTRL3 register (enable INT1 on accel data ready)

short rawX = lsm303d.getAccelX(); // returns 16-bit signed result, unscaled

float x, y, z;
lsm303d.getAccelInto(x, y, z); // overwrites parameters, values in g

float mX = lsm303d.getMagX(); // returns value in gauss
Committer:
ajp109
Date:
Thu Jan 21 21:30:19 2021 +0000
Revision:
0:b07c3d3e3d9c
Child:
1:a74f8c175f6c
Initial commit.  About to refactor registers.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ajp109 0:b07c3d3e3d9c 1 #include "lsm303d.h"
ajp109 0:b07c3d3e3d9c 2
ajp109 0:b07c3d3e3d9c 3 LSM303D::LSM303D(PinName sda, PinName scl, unsigned char i2c_addr) :
ajp109 0:b07c3d3e3d9c 4 i2c_(sda, scl), addr_8bit_(i2c_addr << 1) {
ajp109 0:b07c3d3e3d9c 5
ajp109 0:b07c3d3e3d9c 6 // Check device responds correctly
ajp109 0:b07c3d3e3d9c 7 MBED_ASSERT(WHO_AM_I() == 0x49);
ajp109 0:b07c3d3e3d9c 8 CTRL1 = 0x57; // Enable accelerometers, 50Hz
ajp109 0:b07c3d3e3d9c 9 setOption(AccelUpdateRate::rate_50Hz);
ajp109 0:b07c3d3e3d9c 10 CTRL3 = 0x04; // Enable accel data interrupt
ajp109 0:b07c3d3e3d9c 11 CTRL5 = 0xF0; // Enable temperature, 50Hz
ajp109 0:b07c3d3e3d9c 12 CTRL7 = 0x00; // Enable magnetometer, continuous conversion
ajp109 0:b07c3d3e3d9c 13
ajp109 0:b07c3d3e3d9c 14 // Grab current accelerometer and magnetometer scales from registers
ajp109 0:b07c3d3e3d9c 15 static unsigned char const accel_lookup[] = {2, 4, 6, 8, 16};
ajp109 0:b07c3d3e3d9c 16 accel_scale_ = accel_lookup[(CTRL2() & 0x38) >> 3];
ajp109 0:b07c3d3e3d9c 17 static unsigned char const mag_lookup[] = {2, 4, 8, 12};
ajp109 0:b07c3d3e3d9c 18 mag_scale_ = mag_lookup[(CTRL6() & 0x60) >> 5];
ajp109 0:b07c3d3e3d9c 19 }
ajp109 0:b07c3d3e3d9c 20
ajp109 0:b07c3d3e3d9c 21 void LSM303D::setAccelScale(unsigned char scale) {
ajp109 0:b07c3d3e3d9c 22 unsigned short ctrl2 = CTRL2() & 0xC7;
ajp109 0:b07c3d3e3d9c 23 switch (scale) {
ajp109 0:b07c3d3e3d9c 24 case 2:
ajp109 0:b07c3d3e3d9c 25 ctrl2 |= 0 << 3;
ajp109 0:b07c3d3e3d9c 26 break;
ajp109 0:b07c3d3e3d9c 27 case 4:
ajp109 0:b07c3d3e3d9c 28 ctrl2 |= 1 << 3;
ajp109 0:b07c3d3e3d9c 29 break;
ajp109 0:b07c3d3e3d9c 30 case 6:
ajp109 0:b07c3d3e3d9c 31 ctrl2 |= 2 << 3;
ajp109 0:b07c3d3e3d9c 32 break;
ajp109 0:b07c3d3e3d9c 33 case 8:
ajp109 0:b07c3d3e3d9c 34 ctrl2 |= 3 << 3;
ajp109 0:b07c3d3e3d9c 35 break;
ajp109 0:b07c3d3e3d9c 36 case 16:
ajp109 0:b07c3d3e3d9c 37 ctrl2 |= 4 << 3;
ajp109 0:b07c3d3e3d9c 38 break;
ajp109 0:b07c3d3e3d9c 39 default:
ajp109 0:b07c3d3e3d9c 40 mbed_assert_internal( \
ajp109 0:b07c3d3e3d9c 41 "Accelerometer scale must be 2, 4, 6, 8 or 16", \
ajp109 0:b07c3d3e3d9c 42 __FILE__, __LINE__);
ajp109 0:b07c3d3e3d9c 43 }
ajp109 0:b07c3d3e3d9c 44 CTRL2 = ctrl2;
ajp109 0:b07c3d3e3d9c 45 accel_scale_ = scale;
ajp109 0:b07c3d3e3d9c 46 }
ajp109 0:b07c3d3e3d9c 47
ajp109 0:b07c3d3e3d9c 48 void LSM303D::setMagScale(unsigned char scale) {
ajp109 0:b07c3d3e3d9c 49 switch (scale) {
ajp109 0:b07c3d3e3d9c 50 case 2:
ajp109 0:b07c3d3e3d9c 51 CTRL6 = 0x00;
ajp109 0:b07c3d3e3d9c 52 break;
ajp109 0:b07c3d3e3d9c 53 case 4:
ajp109 0:b07c3d3e3d9c 54 CTRL6 = 0x20;
ajp109 0:b07c3d3e3d9c 55 break;
ajp109 0:b07c3d3e3d9c 56 case 8:
ajp109 0:b07c3d3e3d9c 57 CTRL6 = 0x40;
ajp109 0:b07c3d3e3d9c 58 break;
ajp109 0:b07c3d3e3d9c 59 case 12:
ajp109 0:b07c3d3e3d9c 60 CTRL6 = 0x60;
ajp109 0:b07c3d3e3d9c 61 break;
ajp109 0:b07c3d3e3d9c 62 default:
ajp109 0:b07c3d3e3d9c 63 mbed_assert_internal( \
ajp109 0:b07c3d3e3d9c 64 "Magnetometer scale must be 2, 4, 8 or 12", \
ajp109 0:b07c3d3e3d9c 65 __FILE__, __LINE__);
ajp109 0:b07c3d3e3d9c 66 }
ajp109 0:b07c3d3e3d9c 67 mag_scale_ = scale;
ajp109 0:b07c3d3e3d9c 68 }
ajp109 0:b07c3d3e3d9c 69
ajp109 0:b07c3d3e3d9c 70 void LSM303D::getRawAccelInto(short &x, short &y, short &z) {
ajp109 0:b07c3d3e3d9c 71 i16_3 xyz = OUT_A();
ajp109 0:b07c3d3e3d9c 72 x = xyz.x;
ajp109 0:b07c3d3e3d9c 73 y = xyz.y;
ajp109 0:b07c3d3e3d9c 74 z = xyz.z;
ajp109 0:b07c3d3e3d9c 75 }
ajp109 0:b07c3d3e3d9c 76
ajp109 0:b07c3d3e3d9c 77 void LSM303D::getAccelInto(float &x, float &y, float &z) {
ajp109 0:b07c3d3e3d9c 78 i16_3 xyz = OUT_A();
ajp109 0:b07c3d3e3d9c 79 float scale = accel_scale_ / 32768.0;
ajp109 0:b07c3d3e3d9c 80 x = xyz.x * scale;
ajp109 0:b07c3d3e3d9c 81 y = xyz.y * scale;
ajp109 0:b07c3d3e3d9c 82 z = xyz.z * scale;
ajp109 0:b07c3d3e3d9c 83 }
ajp109 0:b07c3d3e3d9c 84
ajp109 0:b07c3d3e3d9c 85 void LSM303D::getRawMagInto(short &x, short &y, short &z) {
ajp109 0:b07c3d3e3d9c 86 i16_3 xyz = OUT_M();
ajp109 0:b07c3d3e3d9c 87 x = xyz.x;
ajp109 0:b07c3d3e3d9c 88 y = xyz.y;
ajp109 0:b07c3d3e3d9c 89 z = xyz.z;
ajp109 0:b07c3d3e3d9c 90 }
ajp109 0:b07c3d3e3d9c 91
ajp109 0:b07c3d3e3d9c 92 void LSM303D::getMagInto(float &x, float &y, float &z) {
ajp109 0:b07c3d3e3d9c 93 i16_3 xyz = OUT_M();
ajp109 0:b07c3d3e3d9c 94 float scale = mag_scale_ / 32768.0;
ajp109 0:b07c3d3e3d9c 95 x = xyz.x * scale;
ajp109 0:b07c3d3e3d9c 96 y = xyz.y * scale;
ajp109 0:b07c3d3e3d9c 97 z = xyz.z * scale;
ajp109 0:b07c3d3e3d9c 98 }
ajp109 0:b07c3d3e3d9c 99
ajp109 0:b07c3d3e3d9c 100 void LSM303D::setOption(LSM303DOption const &option) {
ajp109 0:b07c3d3e3d9c 101 option.apply(*this);
ajp109 0:b07c3d3e3d9c 102 }
ajp109 0:b07c3d3e3d9c 103
ajp109 0:b07c3d3e3d9c 104
ajp109 0:b07c3d3e3d9c 105 AccelUpdateRate const AccelUpdateRate::rate_3_125Hz(0x1);
ajp109 0:b07c3d3e3d9c 106 AccelUpdateRate const AccelUpdateRate::rate_6_25Hz(0x2);
ajp109 0:b07c3d3e3d9c 107 AccelUpdateRate const AccelUpdateRate::rate_12_5Hz(0x3);
ajp109 0:b07c3d3e3d9c 108 AccelUpdateRate const AccelUpdateRate::rate_25Hz(0x4);
ajp109 0:b07c3d3e3d9c 109 AccelUpdateRate const AccelUpdateRate::rate_50Hz(0x5);
ajp109 0:b07c3d3e3d9c 110 AccelUpdateRate const AccelUpdateRate::rate_100Hz(0x6);
ajp109 0:b07c3d3e3d9c 111 AccelUpdateRate const AccelUpdateRate::rate_200Hz(0x7);
ajp109 0:b07c3d3e3d9c 112 AccelUpdateRate const AccelUpdateRate::rate_400Hz(0x8);
ajp109 0:b07c3d3e3d9c 113 AccelUpdateRate const AccelUpdateRate::rate_800Hz(0x9);
ajp109 0:b07c3d3e3d9c 114 AccelUpdateRate const AccelUpdateRate::rate_1600Hz(0xA);
ajp109 0:b07c3d3e3d9c 115 void AccelUpdateRate::apply(LSM303D &lsm303d) const {
ajp109 0:b07c3d3e3d9c 116 lsm303d.CTRL1 = (lsm303d.CTRL1() & 0x0F) | (rate_ << 4);
ajp109 0:b07c3d3e3d9c 117 }
ajp109 0:b07c3d3e3d9c 118
ajp109 0:b07c3d3e3d9c 119 CTRL1EnableOption const EnableOption::accel_all(0x03);
ajp109 0:b07c3d3e3d9c 120 void CTRL1EnableOption::apply(LSM303D &lsm303d) const {
ajp109 0:b07c3d3e3d9c 121 lsm303d.CTRL1 |= mask_;
ajp109 0:b07c3d3e3d9c 122 }