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
Revision:
0:b07c3d3e3d9c
Child:
1:a74f8c175f6c
diff -r 000000000000 -r b07c3d3e3d9c lsm303d.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lsm303d.cpp	Thu Jan 21 21:30:19 2021 +0000
@@ -0,0 +1,122 @@
+#include "lsm303d.h"
+
+LSM303D::LSM303D(PinName sda, PinName scl, unsigned char i2c_addr) :
+    i2c_(sda, scl), addr_8bit_(i2c_addr << 1) {
+
+    // Check device responds correctly
+    MBED_ASSERT(WHO_AM_I() == 0x49);
+    CTRL1 = 0x57; // Enable accelerometers, 50Hz
+    setOption(AccelUpdateRate::rate_50Hz);
+    CTRL3 = 0x04; // Enable accel data interrupt
+    CTRL5 = 0xF0; // Enable temperature, 50Hz
+    CTRL7 = 0x00; // Enable magnetometer, continuous conversion
+    
+    // Grab current accelerometer and magnetometer scales from registers
+    static unsigned char const accel_lookup[] = {2, 4, 6, 8, 16};
+    accel_scale_ = accel_lookup[(CTRL2() & 0x38) >> 3];
+    static unsigned char const mag_lookup[] = {2, 4, 8, 12};
+    mag_scale_ = mag_lookup[(CTRL6() & 0x60) >> 5];
+}
+    
+void LSM303D::setAccelScale(unsigned char scale) {
+    unsigned short ctrl2 = CTRL2() & 0xC7;
+    switch (scale) {
+        case 2:
+            ctrl2 |= 0 << 3;
+            break;
+        case 4:
+            ctrl2 |= 1 << 3;
+            break;
+        case 6:
+            ctrl2 |= 2 << 3;
+            break;
+        case 8:
+            ctrl2 |= 3 << 3;
+            break;
+        case 16:
+            ctrl2 |= 4 << 3;
+            break;
+        default:
+            mbed_assert_internal( \
+                "Accelerometer scale must be 2, 4, 6, 8 or 16", \
+                __FILE__, __LINE__);
+    }
+    CTRL2 = ctrl2;
+    accel_scale_ = scale;
+}
+
+void LSM303D::setMagScale(unsigned char scale) {
+    switch (scale) {
+        case 2:
+            CTRL6 = 0x00;
+            break;
+        case 4:
+            CTRL6 = 0x20;
+            break;
+        case 8:
+            CTRL6 = 0x40;
+            break;
+        case 12:
+            CTRL6 = 0x60;
+            break;
+        default:
+            mbed_assert_internal( \
+                "Magnetometer scale must be 2, 4, 8 or 12", \
+                __FILE__, __LINE__);
+    }
+    mag_scale_ = scale;
+}
+
+void LSM303D::getRawAccelInto(short &x, short &y, short &z) {
+    i16_3 xyz = OUT_A();
+    x = xyz.x;
+    y = xyz.y;
+    z = xyz.z;
+}
+
+void LSM303D::getAccelInto(float &x, float &y, float &z) {
+    i16_3 xyz = OUT_A();
+    float scale = accel_scale_ / 32768.0;
+    x = xyz.x * scale;
+    y = xyz.y * scale;
+    z = xyz.z * scale;
+}
+
+void LSM303D::getRawMagInto(short &x, short &y, short &z) {
+    i16_3 xyz = OUT_M();
+    x = xyz.x;
+    y = xyz.y;
+    z = xyz.z;
+}
+
+void LSM303D::getMagInto(float &x, float &y, float &z) {
+    i16_3 xyz = OUT_M();
+    float scale = mag_scale_ / 32768.0;
+    x = xyz.x * scale;
+    y = xyz.y * scale;
+    z = xyz.z * scale;        
+}
+
+void LSM303D::setOption(LSM303DOption const &option) {
+    option.apply(*this);
+}
+
+
+AccelUpdateRate const AccelUpdateRate::rate_3_125Hz(0x1);
+AccelUpdateRate const AccelUpdateRate::rate_6_25Hz(0x2);
+AccelUpdateRate const AccelUpdateRate::rate_12_5Hz(0x3);
+AccelUpdateRate const AccelUpdateRate::rate_25Hz(0x4);
+AccelUpdateRate const AccelUpdateRate::rate_50Hz(0x5);
+AccelUpdateRate const AccelUpdateRate::rate_100Hz(0x6);
+AccelUpdateRate const AccelUpdateRate::rate_200Hz(0x7);
+AccelUpdateRate const AccelUpdateRate::rate_400Hz(0x8);
+AccelUpdateRate const AccelUpdateRate::rate_800Hz(0x9);
+AccelUpdateRate const AccelUpdateRate::rate_1600Hz(0xA);
+void AccelUpdateRate::apply(LSM303D &lsm303d) const {
+    lsm303d.CTRL1 = (lsm303d.CTRL1() & 0x0F) | (rate_ << 4);
+}
+
+CTRL1EnableOption const EnableOption::accel_all(0x03);
+void CTRL1EnableOption::apply(LSM303D &lsm303d) const {
+    lsm303d.CTRL1 |= mask_;
+}