Chandra Tjhai
/
ENGO333_Lab_tiltmeter
Simple tiltmeter using accelerometer
Revision 0:7d6134e052e0, committed 2019-11-23
- Comitter:
- chtjhai
- Date:
- Sat Nov 23 04:58:09 2019 +0000
- Commit message:
- Simple tiltmeter using accelerometer
Changed in this revision
--- /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, ®isterAddress, 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, ®isterAddress, 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