Simple tiltmeter using accelerometer

Dependencies:   mbed C12832

Files at this revision

API Documentation at this revision

Comitter:
chtjhai
Date:
Sat Nov 23 04:58:09 2019 +0000
Commit message:
Simple tiltmeter using accelerometer

Changed in this revision

C12832.lib Show annotated file Show diff for this revision Revisions of this file
ENGO333_I2C.cpp Show annotated file Show diff for this revision Revisions of this file
ENGO333_I2C.h Show annotated file Show diff for this revision Revisions of this file
ENGO333_MMA7660.cpp Show annotated file Show diff for this revision Revisions of this file
ENGO333_MMA7660.h Show annotated file Show diff for this revision Revisions of this file
ENGO333_MPU9150.cpp Show annotated file Show diff for this revision Revisions of this file
ENGO333_MPU9150.h Show annotated file Show diff for this revision Revisions of this file
Tiltmeter.cpp Show annotated file Show diff for this revision Revisions of this file
Tiltmeter.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C12832.lib	Sat Nov 23 04:58:09 2019 +0000
@@ -0,0 +1,1 @@
+https://developer.mbed.org/users/mpetovello/code/C12832/#878d97d7c263
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ENGO333_I2C.cpp	Sat Nov 23 04:58:09 2019 +0000
@@ -0,0 +1,40 @@
+#include "ENGO333_I2C.h"
+
+ENGO333_I2C::ENGO333_I2C(PinName sda, PinName scl) : i2c(sda, scl)
+{
+    // Do nothing
+}
+
+ENGO333_I2C::~ENGO333_I2C()
+{
+    // Do nothing
+}
+
+void ENGO333_I2C::setSpeed(int freq)
+{
+    this->i2c.frequency(freq);
+}
+
+void ENGO333_I2C::writeOneByte(char deviceAddress, char registerAddress, char value)
+{
+    char temp[2];
+    temp[0] = registerAddress;
+    temp[1] = value;
+    this->i2c.write(deviceAddress, temp, 2);
+}
+
+char ENGO333_I2C::readOneByte(char deviceAddress, char registerAddress)
+{
+    char temp = 0;
+    this->i2c.write(deviceAddress, &registerAddress, 1);
+    this->i2c.read(deviceAddress, &temp, 1);
+    return (char)temp;
+}
+
+void ENGO333_I2C::readBytes(char deviceAddress, char registerAddress, char* value, int length)
+{
+    this->i2c.write(deviceAddress, &registerAddress, 1);
+    this->i2c.read(deviceAddress, value, length);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ENGO333_I2C.h	Sat Nov 23 04:58:09 2019 +0000
@@ -0,0 +1,85 @@
+/**
+ * File : ENGO333_I2C.h
+ * Created by : Chandra Tjhai
+ * Created on : September 10, 2016
+ *
+ * Description :
+ * This file contains a class to handle I2C bus operation for ENGO 333.
+ */
+
+#ifndef ENGO333_I2C_H
+#define ENGO333_I2C_H
+
+#include "mbed.h"
+
+/**
+ * Class
+ *  A class to handle I2C read/write operation
+ */
+class ENGO333_I2C
+{
+private:
+    I2C i2c;    // Object for handling I2C bus operations
+    
+public:
+    /**
+     * Constructor
+     *
+     * Input
+     *  sda = SDA or I2C serial data pin
+     *  scl = SCL or I2C serial clock pin
+     */
+    ENGO333_I2C(PinName sda, PinName scl);
+    
+    /**
+     * Destructor
+     */
+    ~ENGO333_I2C();
+    
+    /**
+     * Function :
+     *  Set I2C bus frequency
+     *
+     * Input :
+     *  freq = desired frequency in Hz
+     */
+    void setSpeed(int freq);
+    
+    /**
+     * Function :
+     *  Write one byte data into device's register
+     *
+     * Input :
+     *  deviceAddress = Device's I2C address
+     *  registerAddress = Device's register address to be written on
+     *  value = Value to be written on device's register address
+     */
+    void writeOneByte(char deviceAddress, char registerAddress, char value);
+    
+    /**
+     * Function :
+     *  Read one byte from device's register address
+     *
+     * Input :
+     *  deviceAddress = Device's I2C address
+     *  registerAddress = Device's register address to be read
+     *
+     * Return :
+     *  One byte data read from device's register
+     */
+    char readOneByte(char deviceAddress, char registerAddress);
+    
+    /**
+     * Function :
+     *  Read multiple bytes from device's register address
+     *
+     * Input :
+     *  deviceAddress = Device's I2C address
+     *  registerAddress = Device's register address to be read
+     *  value = Array of data to store values read from device's register
+     */
+    void readBytes(char deviceAddress, char registerAddress, char* value, int length);
+};
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ENGO333_MMA7660.cpp	Sat Nov 23 04:58:09 2019 +0000
@@ -0,0 +1,83 @@
+#include "ENGO333_MMA7660.h"
+
+const float GRAVITY = 9.8086;
+
+ENGO333_MMA7660::ENGO333_MMA7660() : i2c(p28, p27)
+{
+    SetActiveMode();
+    SetSamplingRateAM(MMA7660_AMSR8);
+    measAccel[0] = measAccel[1] = measAccel[2] = 0;
+}
+
+bool ENGO333_MMA7660::TestConnection() 
+{
+    char data[3] = {128, 128, 128};
+    bool alert;
+
+    // Check data validity
+    alert = false;
+    i2c.readBytes(MMA7660_ADDRESS, MMA7660_XOUT_REG, data, 3);
+    for (int i = 0; i < 3; ++i) {
+        if (data[i] > 63)
+            alert = true;
+    }
+    
+    if (alert == false) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+void ENGO333_MMA7660::SetActiveMode()
+{
+    i2c.writeOneByte(MMA7660_ADDRESS, MMA7660_MODE_REG, 0x01);
+}
+
+void ENGO333_MMA7660::SetSamplingRateAM(MMA7660_AMSR_t samplingRate)
+{
+    char oldValue, newValue;
+    oldValue = i2c.readOneByte(MMA7660_ADDRESS, MMA7660_SR_REG);
+    oldValue = oldValue & 0x07;
+    newValue = oldValue | samplingRate;
+    i2c.writeOneByte(MMA7660_ADDRESS, MMA7660_SR_REG, newValue);
+}
+
+void ENGO333_MMA7660::ReadAccelerometers()
+{
+    char data[3];
+    bool alert;
+
+    // Check data validity
+    do {
+        alert = false;
+        i2c.readBytes(MMA7660_ADDRESS, MMA7660_XOUT_REG, data, 3);
+        for (int i = 0; i < 3; ++i) {
+            if (data[i] > 63)
+                alert = true;
+            if (data[i] > 31)
+                data[i] += 128 + 64;
+        }
+    } while (alert);
+    
+    measAccel[0] = (signed char)(data[0]) / MMA7660_SCALE * GRAVITY;
+    measAccel[1] = (signed char)(data[1]) / MMA7660_SCALE * GRAVITY;
+    measAccel[2] = (signed char)(data[2]) / MMA7660_SCALE * GRAVITY;
+}
+
+float ENGO333_MMA7660::GetAccelX() const
+{
+    return measAccel[0];
+}
+
+float ENGO333_MMA7660::GetAccelY() const
+{
+    return measAccel[1];
+}
+
+float ENGO333_MMA7660::GetAccelZ() const
+{
+    return measAccel[2];
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ENGO333_MMA7660.h	Sat Nov 23 04:58:09 2019 +0000
@@ -0,0 +1,154 @@
+/**
+ * File : ENGO333_MMA7660.h
+ * Created by : Chandra Tjhai
+ * Created on : September 10, 2016
+ *
+ * Description :
+ * This library is created for ENGO 333 class. The accelerometer is mounted
+ * on the mbed Application Board. The I2C connection is permanently set to p28
+ * (SDA) and p27 (SCL).
+ */
+
+#ifndef ENGO333_MMA7660_H
+#define ENGO333_MMA7660_H
+
+#include "ENGO333_I2C.h"
+#include "Tiltmeter.h"
+
+// Sensor I2C address
+#define MMA7660_ADDRESS 0x98
+
+// Define sensor registers
+#define MMA7660_XOUT_REG 0x00
+#define MMA7660_YOUT_REG 0x01
+#define MMA7660_ZOUT_REG 0x02
+#define MMA7660_TILT_REG 0x03
+#define MMA7660_SRST_REG 0x04
+#define MMA7660_SPCNT_REG 0x05
+#define MMA7660_INTSU_REG 0x06
+#define MMA7660_MODE_REG 0x07
+#define MMA7660_SR_REG 0x08
+#define MMA7660_PDET_REF 0x09
+#define MMA7660_PD_REG 0x0A
+
+// Define acceleration scale
+#define MMA7660_SCALE (21.33)
+
+// Define AMSR values
+typedef enum
+{
+    MMA7660_AMSR120 = 0,
+    MMA7660_AMSR64 = 1,
+    MMA7660_AMSR32 = 2,
+    MMA7660_AMSR16 = 3,
+    MMA7660_AMSR8 = 4,
+    MMA7660_AMSR4 = 5,
+    MMA7660_AMSR2 = 6,
+    MMA7660_AMSR1 = 7
+}MMA7660_AMSR_t;
+
+/**
+ * Class
+ *  A class to handle MMA7660 3-DOF accelerometer
+ */
+class ENGO333_MMA7660
+{
+private:
+    ENGO333_I2C i2c;    // I2C communication connection
+    float measAccel[3];  // Measured acceleration values in units of m/s/s
+
+public:
+    /**
+     * Default Constructor
+     *  Once called, trigger active mode and set MMA7660_AMSR8
+     */
+    ENGO333_MMA7660();
+    
+    /**
+     * Function :
+     *  Test device's accelerometer connection. MMA7660 does not have identifier
+     *  registers. Thus, this function will simply take measurements and check 
+     *  their validity.
+     *
+     * Argument :
+     *  NONE
+     *
+     * Return :
+     *  Return TRUE if connection is good, otherwise FALSSE
+     */
+    virtual bool TestConnection();
+
+
+private:
+
+   // Read the accelerometer data and store the values for later use. You can access the values by
+   // calling the GetAccelX(), GetAccelY() and/or GetAccelZ();
+   //
+   // Arguments:
+   //    None
+   //
+   // Returns:
+   //    Nothing
+   //
+   // Remarks:
+   //    The data will be stored in the 'MeasuredAccel' member variable in units of m/s/s
+   virtual void ReadAccelerometers();
+
+
+   // Get the most recently measured X-axis acceleration as stored during the last call to
+   // ReadAccelerometer()
+   //
+   // Arguments:
+   //    None
+   //
+   // Returns:
+   //    The function returns the most recently measured X-axis acceleration in units of m/s/s
+   virtual float GetAccelX() const;
+
+
+   // Get the most recently measured Y-axis acceleration as stored during the last call to
+   // ReadAccelerometer()
+   //
+   // Arguments:
+   //    None
+   //
+   // Returns:
+   //    The function returns the most recently measured Y-axis acceleration in units of m/s/s
+   virtual float GetAccelY() const;
+
+
+   // Get the most recently measured Z-axis acceleration as stored during the last call to
+   // ReadAccelerometer()
+   //
+   // Arguments:
+   //    None
+   //
+   // Returns:
+   //    The function returns the most recently measured Z-axis acceleration in units of m/s/s
+   virtual float GetAccelZ() const;
+   
+   
+   // Set the device to 'active' mode
+   //
+   // Arguments: 
+   //    None
+   //
+   // Returns:
+   //    Nothing
+   void SetActiveMode();
+   
+   
+   // Set the device sampling rate through AM bits, see MMA7660_SR_REG
+   //
+   // Arguments:
+   //    samplingRate = setting of AM bits in MMA7660_SR_REG
+   //
+   // Returns:
+   //    Nothing
+   void SetSamplingRateAM(MMA7660_AMSR_t samplingRate);
+    
+};
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ENGO333_MPU9150.cpp	Sat Nov 23 04:58:09 2019 +0000
@@ -0,0 +1,73 @@
+#include "ENGO333_MPU9150.h"
+
+const float GRAVITY = 9.8086;
+
+ENGO333_MPU9150::ENGO333_MPU9150() : i2c(p28, p27)
+{
+    i2c.setSpeed(MPU9150_I2C_FAST_MODE);
+    setSleepMode(false);
+    setAccelRange(MPU9150_ACCEL_RANGE_2G);
+    
+    measAccel[0] = measAccel[1] = measAccel[2] = 0;
+}
+
+void ENGO333_MPU9150::setSleepMode(bool state)
+{
+    char temp;
+    temp = i2c.readOneByte(MPU9150_ADDRESS, MPU9150_PWR_MGMT_1_REG);
+    if (state == true)
+        temp |= 1 << MPU9150_SLEEP_BIT;
+    if (state == false)
+        temp &= ~(1 << MPU9150_SLEEP_BIT);
+    i2c.writeOneByte(MPU9150_ADDRESS, MPU9150_PWR_MGMT_1_REG, temp);
+}
+
+bool ENGO333_MPU9150::TestConnection()
+{
+    char temp;
+    temp = i2c.readOneByte(MPU9150_ADDRESS, MPU9150_WHO_AM_I_REG);
+    return (temp == (0x68 & 0xFE));
+}
+
+void ENGO333_MPU9150::setAccelRange(char range)
+{
+    char temp;
+    range = range & 0x03;
+    
+    temp = i2c.readOneByte(MPU9150_ADDRESS, MPU9150_ACCEL_CONFIG_REG);
+    temp &= ~(3 << 3);
+    temp = temp + (range << 3);
+    i2c.writeOneByte(MPU9150_ADDRESS, MPU9150_ACCEL_CONFIG_REG, temp);
+}
+
+void ENGO333_MPU9150::ReadAccelerometers()
+{
+    char temp[6];
+    
+    while ((i2c.readOneByte(MPU9150_ADDRESS, MPU9150_INT_STATUS_REG) & 0x01) != 0x01)
+    {
+        // wait data to be ready
+    }
+    
+    i2c.readBytes(MPU9150_ADDRESS, MPU9150_ACCEL_XOUT_H_REG, temp, 6);
+    measAccel[0] = ((short)((temp[0] << 8) + temp[1])) / 16384.0 * GRAVITY;
+    measAccel[1] = ((short)((temp[2] << 8) + temp[3])) / 16384.0 * GRAVITY;
+    measAccel[2] = ((short)((temp[4] << 8) + temp[5])) / 16384.0 * GRAVITY;
+}
+
+float ENGO333_MPU9150::GetAccelX() const
+{
+    return measAccel[0];
+}
+
+float ENGO333_MPU9150::GetAccelY() const
+{
+    return measAccel[1];
+}
+
+float ENGO333_MPU9150::GetAccelZ() const
+{
+    return measAccel[2];
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ENGO333_MPU9150.h	Sat Nov 23 04:58:09 2019 +0000
@@ -0,0 +1,159 @@
+/**
+ * File : ENGO333_MPU9150.h
+ * Created by : Chandra Tjhai
+ * Created on : September 19, 2016
+ *
+ * Description :
+ * This library is created for ENGO 333 class. The inertial sensor needs to be 
+ * mounted on the mbed Application Board. The I2C connection is automatically 
+ * set to p28 (SDA) and p27 (SCL).
+ */
+ 
+#ifndef ENGO333_MPU9150_H
+#define ENGO333_MPU9150_H
+
+#include "ENGO333_I2C.h"
+#include "Tiltmeter.h"
+
+/**
+ * Define Macros: Device I2C slave addresses (R/W)
+ */
+#define MPU9150_ADDRESS         (0x68 << 1)
+
+ /**
+ * Define Macros: Configuration Registers
+ */
+#define MPU9150_CONFIG_REG              0x1A
+#define MPU9150_ACCEL_CONFIG_REG        0x1C
+#define MPU9150_INT_STATUS_REG          0x3A
+#define MPU9150_INT_PIN_CFG_REG         0x37
+#define MPU9150_PWR_MGMT_1_REG          0x6B
+#define MPU9150_WHO_AM_I_REG            0x75
+
+/**
+ * Define Macros: Measurement Data Registers
+ */
+#define MPU9150_ACCEL_XOUT_H_REG        0x3B
+#define MPU9150_ACCEL_YOUT_H_REG        0x3D
+#define MPU9150_ACCEL_ZOUT_H_REG        0x3F
+
+/**
+ * Define Macros: IMU Definitions
+ */
+#define MPU9150_SLEEP_BIT               6
+#define MPU9150_ACCEL_RANGE_2G          0
+#define MPU9150_ACCEL_RANGE_4G          1
+#define MPU9150_ACCEL_RANGE_8G          2
+#define MPU9150_ACCEL_RANGE_16G         3
+#define MPU9150_I_AM                    0x68
+#define MPU9150_I2C_FAST_MODE           400000
+#define MPU9150_I2C_STD_MODE            100000
+
+/**
+ * Class
+ *  A class to handle MPU-9150 9-DOF sensor
+ */
+class ENGO333_MPU9150
+{
+private:
+    ENGO333_I2C i2c;
+    float measAccel[3];  // Measured acceleration values in units of m/s/s
+
+public:
+    /**
+     * Default Constructor
+     *  Once called, triggering device initialization and set data variables to 
+     *  zero. Accelerometer is set to +-2G by default.
+     */
+    ENGO333_MPU9150();
+    
+    /**
+     * Function :
+     *  Enable/disable device sleep mode
+     * 
+     * Argument :
+     *  state = TRUE/FALSE
+     *
+     * Return :
+     *  NONE
+     */
+    void setSleepMode(bool state);
+    
+    /**
+     * Function :
+     *  Test device's accelerometer connection
+     * 
+     * Argument :
+     *  NONE
+     *
+     * Return :
+     *  Return TRUE if connection is good, otherwise FALSSE
+     */
+    virtual bool TestConnection();
+    
+     /**
+     * Function :
+     *  Set accelerometer full scale range, see MPU9150_ACCEL_RANGE_XG
+     * 
+     * Argument :
+     *  range = values of MPU9150_ACCEL_RANGE_XG
+     *
+     * Return :
+     *  NONE
+     */
+    void setAccelRange(char range);
+    
+    /**
+     * Function :
+     *  Read raw accelerometer data, 3 axes
+     * 
+     * Argument :
+     *  NONE
+     *
+     * Return :
+     *  NONE
+     */
+    virtual void ReadAccelerometers();
+    
+     /**
+     * Function :
+     *  Get raw X-axis acceleration
+     * 
+     * Argument :
+     *  NONE
+     *
+     * Return :
+     *  Raw X-axis acceleration
+     */
+    virtual float GetAccelX() const;
+    
+    /**
+     * Function :
+     *  Get raw Y-axis acceleration
+     * 
+     * Argument :
+     *  NONE
+     *
+     * Return :
+     *  Raw Y-axis acceleration
+     */
+    virtual float GetAccelY() const;
+    
+    /**
+     * Function :
+     *  Get raw Z-axis acceleration
+     * 
+     * Argument :
+     *  NONE
+     *
+     * Return :
+     *  Raw Z-axis acceleration
+     */
+    virtual float GetAccelZ() const;
+    
+};
+
+#endif
+ 
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tiltmeter.cpp	Sat Nov 23 04:58:09 2019 +0000
@@ -0,0 +1,8 @@
+#include "Tiltmeter.h"
+
+#include "math.h"
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Paste your code from the pre-lab assignment here
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tiltmeter.h	Sat Nov 23 04:58:09 2019 +0000
@@ -0,0 +1,112 @@
+#ifndef TILTMETER_H
+#define TILTMETER_H
+
+class Tiltmeter
+{
+public:
+
+   // Default constructor
+   Tiltmeter();
+
+
+   // Detect the presence of tiltmeter sensor and ensure its status is appropriately set.
+   //
+   // Arguments:
+   //    None
+   //
+   // Returns:
+   //    The function returns true if the sensor is present and ready to use, and false otherwise.
+   virtual bool TestConnection() = 0;
+
+
+   // Compute the tilt angles and store them internally; you can access the computed values by
+   // calling the GetRoll() and GetPitch() functions.
+   //
+   // Arguments:
+   //    None
+   //
+   // Returns:
+   //    Nothing
+   void ComputeTiltAngles();
+
+
+   // Get the most recent roll angle as computed by calling ComputeTilt()
+   //
+   // Arguments:
+   //    None
+   //
+   // Returns:
+   //    The function returns the roll angle in units of degrees
+   float GetRoll() const;
+
+
+   // Get the most recent roll angle as computed by calling ComputeTilt()
+   //
+   // Arguments:
+   //    None
+   //
+   // Returns:
+   //    The function returns the roll angle in units of degrees
+   float GetPitch() const;
+
+
+private:
+
+   // Read the accelerometer data and store the values for later use. You can access the values by
+   // calling the GetAccelX(), GetAccelY() and/or GetAccelZ();
+   //
+   // Arguments:
+   //    None
+   //
+   // Returns:
+   //    Nothing
+   //
+   // Remarks:
+   //    The data will be stored in the 'MeasuredAccel' member variable in units of m/s/s
+   virtual void ReadAccelerometers() = 0;
+
+
+   // Get the most recently measured X-axis acceleration as stored during the last call to
+   // ReadAccelerometer()
+   //
+   // Arguments:
+   //    None
+   //
+   // Returns:
+   //    The function returns the most recently measured X-axis acceleration in units of m/s/s
+   virtual float GetAccelX() const = 0;
+
+
+   // Get the most recently measured Y-axis acceleration as stored during the last call to
+   // ReadAccelerometer()
+   //
+   // Arguments:
+   //    None
+   //
+   // Returns:
+   //    The function returns the most recently measured Y-axis acceleration in units of m/s/s
+   virtual float GetAccelY() const = 0;
+
+
+   // Get the most recently measured Z-axis acceleration as stored during the last call to
+   // ReadAccelerometer()
+   //
+   // Arguments:
+   //    None
+   //
+   // Returns:
+   //    The function returns the most recently measured Z-axis acceleration in units of m/s/s
+   virtual float GetAccelZ() const = 0;
+
+
+private:
+
+   // Variables to store the roll and pitch values in units of degrees
+   float RollAngle, PitchAngle;
+
+
+};
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sat Nov 23 04:58:09 2019 +0000
@@ -0,0 +1,172 @@
+#include "mbed.h"
+#include <string>
+#include "C12832.h"
+#include "ENGO333_MMA7660.h"
+#include "ENGO333_MPU9150.h"
+#include "Tiltmeter.h"
+
+// Enumeration of accelerometer types
+// For more information, see the following links
+//  - https://en.cppreference.com/w/c/language/enum
+//  - http://www.cplusplus.com/doc/tutorial/other_data_types/
+enum AccelType
+{
+    MMA7660,    // MMA7660 accelerometer on the mbed application board
+    MPU9150     // MPU9150 IMU (external to mbed application board)
+};
+
+
+// Function to prompt the user to select between the MMA7660 accelerometer or
+// the MPU9150 IMU. The user can select between these choices by moving the 
+// joystick left or right; they make their selection by pressing the joystick
+// button.
+//
+// Arguments:
+//    lcd = The LCD screen to use for display
+//    joystick = Object linked to the joystick to be used
+//
+// Returns:
+//    The function returns an enumeration identifying the sensor selected
+AccelType SelectAccelerometer( C12832& lcd, BusIn& joystick );
+
+
+int main()
+{
+    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    // START: Setup/variable declaration
+
+
+    // Create LCD object for LCD screen operations
+    C12832 lcd(p5, p7, p6, p8, p11);
+
+    // Create digital outputs for LED1 and LED2 that will be used to indicate
+    // if things are working properly -- both values are to LOW (off)
+    DigitalOut led1(LED1);
+    DigitalOut led2(LED2);
+    led1 = 0;
+    led2 = 0;
+
+    // Create bus input for joystick
+    BusIn joystick(p13, p16, p14);     // Binary [ Centre | Right | Left ] joystick
+    
+    
+    // END: Setup/variable declaration
+    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    // START: Take Measurements
+    
+    
+    // Create an accelerometer object
+    ENGO333_MMA7660 accelerometer;  
+    
+    
+    // Detect sensor
+    if( accelerometer.TestConnection() ) 
+    {
+        // Turn on the first LED to show that the connection was detected
+        led1 = 1;
+    } 
+    else 
+    {
+        lcd.locate(1, 11);
+        lcd.printf("ERROR: Unknown sensor");
+        return 1;
+    }
+
+
+    // Prepare the screen
+    lcd.cls();
+    lcd.locate(1, 1);
+    lcd.printf("Press joystick to measure");
+
+    
+    // Variable to store the value/status of the joystick. It is initialized
+    // to represent pushing the joystick button. Since the loop below 
+    while( true ) 
+    {
+        // Check if the joystick button is being pressed
+        if (joystick.read() == 4) 
+        {
+            // Turn on second LED to indicate a measurement is being made
+            led2 = 1;
+            
+            
+            // Get the tilt angles
+            accelerometer.ComputeTiltAngles();            
+            
+            
+            // Print the roll
+            lcd.locate(1, 11);
+            lcd.printf("Roll (deg)");
+            lcd.locate(50, 11);
+            lcd.printf(": % 8.2f", accelerometer.GetRoll());
+            
+            // Print the pitch
+            lcd.locate(1, 21);
+            lcd.printf("Pitch (deg)");
+            lcd.locate(50, 21);
+            lcd.printf(": % 8.2f", accelerometer.GetPitch());
+            
+            
+            // Short delay to avoid multiple measurements being displayed
+            wait_ms(250);
+
+
+            // Turn off second LED to indicate a measurement is complete
+            led2 = 0;
+        }
+        
+    }
+    
+    
+    // END: Take Measurements
+    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    
+}
+
+
+AccelType SelectAccelerometer( C12832& lcd, BusIn& joystick )
+{
+    // This is the current choice
+    AccelType choice = MMA7660;
+    
+    // This is the string to display the current choice (using asterisk)
+    string sensorChoice = "MMA7660 *       MPU9150";
+    
+    // Print the default choice
+    lcd.cls();
+    lcd.locate(1, 1);
+    lcd.printf("Move L/R to select sensor:");
+    lcd.locate(1, 18);
+    lcd.printf("%s", sensorChoice.c_str());
+
+  
+    // Create while-loop for user to select sensor
+    while(1) 
+    {
+        // read the joystick
+        int joy = joystick.read();
+        
+        
+        if (joy == 2)       // joystick pushed to the right
+        {                  
+            sensorChoice = "MMA7660       * MPU9150";
+            choice = MPU9150;
+            lcd.locate(1, 18);
+            lcd.printf("%s", sensorChoice.c_str());
+        } 
+        else if (joy == 1)  // joystick pushed to the left
+        {
+            sensorChoice = "MMA7660 *       MPU9150";
+            choice = MMA7660;
+            lcd.locate(1, 18);
+            lcd.printf("%s", sensorChoice.c_str());
+        } 
+        else if (joy == 4)  // joystick "button" pushed (i.e., "select")
+        {      
+            break;
+        } 
+    }
+    
+    // return the current choice
+    return choice;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Sat Nov 23 04:58:09 2019 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/mbed_official/code/mbed/builds/65be27845400
\ No newline at end of file