This is a simple wrapper class for the MPL3115A5 pressure and temperature sensor. It allows either single readings for continuous readings using polling or interrupts. It also contains a wrapper class for mbed-rpc.

Files at this revision

API Documentation at this revision

Comitter:
rhourahane
Date:
Sun Mar 22 20:55:38 2015 +0000
Commit message:
Initial revision.

Changed in this revision

RpcMPL3115A2.cpp Show annotated file Show diff for this revision Revisions of this file
RpcMPL3115A2.h Show annotated file Show diff for this revision Revisions of this file
mpl3115a2.cpp Show annotated file Show diff for this revision Revisions of this file
mpl3115a2.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r b12a7d396be9 RpcMPL3115A2.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RpcMPL3115A2.cpp	Sun Mar 22 20:55:38 2015 +0000
@@ -0,0 +1,66 @@
+#include "RpcMPL3115A2.h"
+
+RpcMPL3115A2::RpcMPL3115A2(PinName sda, PinName scl, const char *name) : 
+    RPC(name),
+    chip(sda, scl) 
+{
+}
+
+int RpcMPL3115A2::id(void) {
+    return chip.getId();
+}
+
+void RpcMPL3115A2::setMode(int mode) {
+    chip.setDataMode(static_cast<MPL3115A2::DataMode>(mode));
+}
+
+int RpcMPL3115A2::getMode(void) {
+    return chip.getDataMode();
+}
+
+void RpcMPL3115A2::setOverSampling(int rate) {
+    chip.setOverSampling(rate);
+}
+
+int RpcMPL3115A2::getOverSampling() {
+    return chip.getOverSampling();
+}
+
+void RpcMPL3115A2::read(Arguments *args, Reply *reply) {
+    float pres;
+    float temp;
+    
+    chip.getReadings(pres, temp);
+    
+    reply->putData(pres);
+    reply->putData(temp);
+}
+
+
+const struct rpc_method *RpcMPL3115A2::get_rpc_methods() {
+    static const rpc_method rpc_methods[] = {
+        {"id", rpc_method_caller<int, RpcMPL3115A2, &RpcMPL3115A2::id>},
+        {"read", rpc_method_caller<RpcMPL3115A2, &RpcMPL3115A2::read> },
+        {"writeMode", rpc_method_caller<RpcMPL3115A2, int, &RpcMPL3115A2::setMode> },
+        {"readMode", rpc_method_caller<int, RpcMPL3115A2, &RpcMPL3115A2::getMode> },
+        {"writeSamples", rpc_method_caller<RpcMPL3115A2, int, &RpcMPL3115A2::setOverSampling> },
+        {"readSamples", rpc_method_caller<int, RpcMPL3115A2, &RpcMPL3115A2::getOverSampling> },
+        RPC_METHOD_SUPER(RPC)
+    };
+    
+    return rpc_methods;
+}
+
+const char *RpcMPL3115A2::get_rpc_class_name() {
+    return get_rpc_class()->name;
+}
+
+struct rpc_class *RpcMPL3115A2::get_rpc_class() {
+    static const rpc_function funcs[] = {
+        {"new", rpc_function_caller<const char*, PinName, PinName, const char*, &RPC::construct<RpcMPL3115A2, PinName, PinName, const char*> >},
+        RPC_METHOD_END
+    };
+    static rpc_class c = {"MPL3115A2", funcs, NULL};
+    
+    return &c;
+}
diff -r 000000000000 -r b12a7d396be9 RpcMPL3115A2.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RpcMPL3115A2.h	Sun Mar 22 20:55:38 2015 +0000
@@ -0,0 +1,72 @@
+#ifndef PRCMPL3115A2_H
+#define RPCMPL3115A2_H
+
+#include "rpc.h"
+#include "mpl3115a2.h"
+
+/// RPC wrapper class for MPL3115A2 driver class.
+/// This class provides a simple single shot interface to the 
+/// MPL3115A2 allowing the user to get the altimeter/barometric
+/// mode and number of samples per reading.
+class RpcMPL3115A2 : public mbed::RPC {
+public:
+    /// Create a new instance of the class using the specified pins for the I2C bus.
+    /// @param sda The pin name for the sda line of the I2C bus.
+    /// @param scl The pin name for the scl line of the I2C bus.
+    RpcMPL3115A2(PinName sda, PinName scl, const char *name=NULL);
+
+    /// Read the chip id, this is a fixed value of 0xC4. This method is
+    /// linked to the RPC method method "id".
+    /// @returns Chip id.
+    int id(void);
+    
+    /// Set the how the pressure is read. The default is BarometricMode if 
+    /// it is to be change then is must be called before getReadings or activate.
+    /// This method is linked to to the RPC method "writeMode".
+    /// @param mode New mode to read pressure in.
+    void setMode(int mode);
+
+    /// Get the current setting for the pressure reading mode.
+    /// This method is linked to the RPC method "readMode".
+    /// @returns Current pressure reading mode.
+    int getMode(void);
+    
+    /// Set the number of samples to be used for each reading.
+    /// The number must be a power of two between 1 and 128.
+    /// This method is linked to the RPC method "writeSamples".
+    /// @param samples Number of samples per reading.
+    void setOverSampling(int rate);
+    
+    /// Get the number of samples to be used for each reading.
+    /// This method is linked to the RPC method "readSamples".
+    /// @returns Number of samples per reading.
+    int getOverSampling();
+    
+    /// Reads both pressure and temperature. Returns pressure 
+    /// in the units set by mode and the temperature in Celsius,
+    /// the values are separated by a space.
+    /// This method is linked to the RPC method "read".
+    void read(Arguments*, Reply*);
+
+    /// Override of RPC method to return array of methods
+    /// that can be called through RPC.
+    /// @returns array of method structures terminated by a
+    /// null structure.
+    virtual const struct rpc_method *get_rpc_methods();
+    
+    /// Override of RPC method to return the RPC name of the class
+    /// for this object.
+    /// @returns RPC name of class for this instance.
+    virtual const char *get_rpc_class_name();
+    
+    /// Get the predefined RPC class structure for this
+    /// class. Allows using template to register class
+    /// this RPC.
+    /// @returns Point to RPC class information structure.
+    static struct rpc_class *get_rpc_class();
+    
+private:
+    MPL3115A2 chip;
+};
+
+#endif
\ No newline at end of file
diff -r 000000000000 -r b12a7d396be9 mpl3115a2.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mpl3115a2.cpp	Sun Mar 22 20:55:38 2015 +0000
@@ -0,0 +1,318 @@
+#include <mbed.h>
+#include "mpl3115a2.h"
+
+namespace {
+const char STATUS = 0x00;
+const char OUT_P_MSB = 0x01;
+const char OUT_T_MSB = 0x04;
+const char WHO_AM_I = 0x0C;
+const char SYSMOD = 0x11;
+const char PT_DATA_CFG = 0x13;
+const char CTRL_REG1 = 0x26;
+const char CTRL_REG2 = 0x27;
+const char CTRL_REG3 = 0x28;
+const char CTRL_REG4 = 0x29;
+const char CTRL_REG5 = 0x2A;
+
+// Values for bits in STATUS
+const char STATUS_TDR = 0x02;
+const char STATUS_PDR = 0x04;
+const char STATUS_TPDR = 0x08;
+const char STATUS_DR_MASK = 0x0E;
+const char STATUS_TOW = 0x20;
+const char STATUS_POW = 0x40;
+const char STATUS_TPOW = 0x80;
+const char STATUS_OW_MASK = 0xE0;
+
+// Values for bits in PT_DATA_CFG
+const char PT_DATA_CFG_TDEFE = 0x01;
+const char PT_DATA_CFG_PDEFE = 0x02;
+const char PT_DATA_CFG_DREM = 0x04;
+
+// Values for bits in CTRL_REG1
+const char CTRL_REG1_SBYB = 0x01;
+const char CTRL_REG1_OSB = 0x02;
+const char CTRL_REG1_RST = 0x04;
+const char CTRL_REG1_OS_MASK = 0x38;
+const char CTRL_REG1_RAW = 0x40;
+const char CTRL_REG1_ALT = 0x80;
+
+// Values for bits in CTRL_REG2
+const char CTRL_REG2_ST_MASK = 0x0F;
+const char CTRL_REG2_ALARM_SEL = 0x10;
+const char CTRL_REG2_LOAD_OUTPUT = 0x20;
+
+// Values for bits in CTRL_REG4
+const char CTRL_REG4_INT_EN_TCHG = 0x01;
+const char CTRL_REG4_INT_EN_PCHG = 0x02;
+const char CTRL_REG4_INT_EN_TTH = 0x04;
+const char CTRL_REG4_INT_EN_PTH = 0x08;
+const char CTRL_REG4_INT_EN_TW = 0x10;
+const char CTRL_REG4_INT_EN_PW = 0x20;
+const char CTRL_REG4_INT_EN_FIFO = 0x40;
+const char CTRL_REG4_INT_EN_DRDY = 0x80;
+
+// Values for bits in CTRL_REG5
+const char CTRL_REG5_INT_CFG_TCHG = 0x01;
+const char CTRL_REG5_INT_CFG_PW = 0x20;
+const char CTRL_REG5_INT_CFG_TTH = 0x04;
+const char CTRL_REG5_INT_CFG_PTH = 0x08;
+const char CTRL_REG5_INT_CFG_TW = 0x10;
+const char CTRL_REG5_INT_CFG_PCHG = 0x02;
+const char CTRL_REG5_INT_CFG_FIFO = 0x40;
+const char CTRL_REG5_INT_CFG_DRDY = 0x80;
+};
+
+MPL3115A2::MPL3115A2(PinName sda, PinName scl) :
+    m_i2c(sda, scl),
+    m_addr(0x60<<1),
+    m_readMode(Single),
+    m_dataMode(BarometricMode),
+    m_overSample(0),
+    m_samplePeriod(0),
+    m_dataReadInt(INT2)
+{
+    // Reset the chip so we know where we are.
+    char data[2] = { CTRL_REG1, CTRL_REG1_RST};
+    writeRegs(data, 2);    
+    wait(0.1);
+    
+    // Configure to get data ready events.
+    data[0] = PT_DATA_CFG;
+    data[1] = PT_DATA_CFG_TDEFE | PT_DATA_CFG_PDEFE | PT_DATA_CFG_DREM;
+    writeRegs(data, 2);    
+}
+
+void MPL3115A2::setDataMode(DataMode mode) {
+    m_dataMode = mode;
+}
+
+MPL3115A2::DataMode MPL3115A2::getDataMode(void) {
+    return m_dataMode;
+}
+
+void MPL3115A2::setReadMode(ReadMode mode) {
+    m_readMode = mode;
+}
+
+MPL3115A2::ReadMode MPL3115A2::getReadMode(void) {
+    return m_readMode;
+}
+
+void MPL3115A2::setOverSampling(int samples) {
+    int pow = 0;
+    while (((samples % 2) != 1) && (pow < 8)) {
+        ++pow;
+        samples = samples >> 1;
+    }
+    m_overSample = pow;
+}
+
+int MPL3115A2::getOverSampling(void) {
+    return 1 << m_overSample;
+}
+
+void MPL3115A2::setSamplingPeriod(int period) {
+    int pow = 0;
+    while (((period % 2) != 1) && (pow < 16)) {
+        ++pow;
+        period = period >> 1;
+    }
+    m_samplePeriod = pow;
+}
+
+int MPL3115A2::getSamplingPeriod(void) {
+    return 1 << m_samplePeriod;
+}
+
+void MPL3115A2::setDataReadyInt(InterruptPin intPin) {
+    m_dataReadInt = intPin;
+}
+
+MPL3115A2::InterruptPin MPL3115A2::getDataReadyInt(void) {
+    return m_dataReadInt;
+}
+
+int MPL3115A2::getId(void) {
+    char id;
+    
+    // Read the WHO_AM_I register to get the value.
+    readRegs(WHO_AM_I, &id, 1);
+    return id;
+}
+
+int MPL3115A2::getStatus(void) {
+    char status;
+    
+    readRegs(STATUS, &status, 1);
+    return status;
+}
+
+bool MPL3115A2::isDataReady(void) {
+    char status;
+    
+    // Read the STATUS register and and in the data ready mask
+    // to get a boolean.
+    readRegs(STATUS, &status, 1);
+    return (status & STATUS_DR_MASK) != 0;
+};
+
+void MPL3115A2::activate() {
+    if (m_readMode != Single) {
+        char reg1 = CTRL_REG1_SBYB;
+        char reg2 = 0;
+        char reg4 = 0;
+        char reg5 = 0;
+        
+        // Set the data mode  and over sampling correctly
+        switch (m_dataMode) {
+        case BarometricMode:
+            // nothing to set.
+            break;
+            
+        case AltimeterMode:
+            reg1 |= CTRL_REG1_ALT;
+            break;
+            
+        case RawMode:
+            reg1 |= CTRL_REG1_RAW;
+            break;
+        }
+        reg1 |= (m_overSample << 3) & CTRL_REG1_OS_MASK;
+        
+        // Set the sampling period
+        reg2 = m_samplePeriod & CTRL_REG2_ST_MASK;
+        
+        // If we are using interupts then configure the
+        // interrupt registers.
+        if (m_readMode == Interupt) {
+            reg4 = CTRL_REG4_INT_EN_DRDY;
+            if (m_dataReadInt == INT1) {
+                reg5 = CTRL_REG5_INT_CFG_DRDY;
+            }
+        }
+        
+        char data[6] = { CTRL_REG1, reg1, reg2, 0, reg4, reg5 };
+        writeRegs(data, 6);
+    }
+}
+
+bool MPL3115A2::isActive() {
+    char status;
+    
+    // read the active status from the SYSMOD register
+    readRegs(SYSMOD, &status, 1);
+    return status != 0;
+}
+
+void MPL3115A2::standby() {
+    
+    // Clear the CTRL_REG1 to put the chip into standby.
+    char data[2] = { CTRL_REG1, 0 };
+    writeRegs(data, 2);
+}
+
+    
+bool MPL3115A2::getReadings(float &pres, float &temp) {
+    if (m_dataMode == RawMode) {
+        // Raw mode not supported.
+        return false;
+    }
+    
+    // If we're in single read mode then we need to initiate 
+    // a new read cycle.
+    if (m_readMode == Single) {
+        // Set the OSB bit to initiate a new reading.
+        char value = CTRL_REG1_OSB;
+        
+        // Add in oversampling
+        value |= (m_overSample << 3) & CTRL_REG1_OS_MASK;
+        
+        // Set the pressure reading mode to altimeter if needed.
+        if (m_dataMode == AltimeterMode) {
+            value |= CTRL_REG1_ALT;
+        }
+        
+        // Write the new value to CTRL_REG1 to kick things off.
+        char data[2] = { CTRL_REG1, value};
+        writeRegs(data, 2);    
+    }
+    
+    int status = 0;
+    
+    // Loop until the data is ready.
+    while ((status & STATUS_DR_MASK) == 0) {
+        status = getStatus();
+        printf("0x%X-", status);
+    }
+    
+    // Read the pressure and temperature data all at once
+    // and then convert it into real values.
+    char data[5];
+    readRegs(OUT_P_MSB, &data[0], 5);
+    if (m_dataMode == AltimeterMode) {
+        pres = convAltimeter(&data[0]);
+    } else {
+        pres = convPressure(&data[0]);
+    }
+    temp = convTemperature(&data[3]);
+    
+    return true;
+}
+
+
+float MPL3115A2::convTemperature(char *data) {
+    short temp;
+    float ftemp;
+    
+    // Move the signed byte up to the top of the short so
+    // that it is in the right place and or in the bottom
+    // 8bits.
+    temp = (data[0] << 8) | data[1];
+    
+    // shift out the bottom 4 0 bits and convert
+    // the integer temp into a float value by
+    // dividing by 16.
+    ftemp = (temp >> 4) / 16.0f;
+    return ftemp;
+}
+
+float MPL3115A2::convAltimeter(char *data) {
+    int altInt;
+    float altFloat;
+    
+    // Put the 3 byte value in the upper 24 bits so the sign
+    // is correct.
+    altInt = (data[0] << 24) | (data[1] << 16) | (data[2] << 8);
+    
+    // Shift down extending the sign as we go and then
+    // divide by 16 to get fractions.
+    altFloat = (altInt >> 12) / 16.0f;
+    
+    return altFloat;
+}
+
+float MPL3115A2::convPressure(char *data) {
+    int presInt;
+    float fprs;
+    
+    // Or in the three bytes containing the 18bit int
+    // into the top 18bits so the sign bit is correct.
+    presInt = (data[0] << 24) | (data[1] << 16) | (data[2] << 8);
+
+    // Shift the in into the correct position and then
+    // divide by 4 to generate the fractional part.
+    fprs = (presInt >> 12) / 4.0f;
+    
+    return fprs;
+}
+
+void MPL3115A2::readRegs(char addr, char *data, int len) {
+    m_i2c.write(m_addr, &addr, 1, true);
+    m_i2c.read(m_addr, data, len);
+}
+
+void MPL3115A2::writeRegs(const char *data, int len) {
+    m_i2c.write(m_addr, data, len);
+}
+
diff -r 000000000000 -r b12a7d396be9 mpl3115a2.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mpl3115a2.h	Sun Mar 22 20:55:38 2015 +0000
@@ -0,0 +1,150 @@
+#ifndef __MPL3115A2_H__
+#define __MPL3115A2_H__
+#include <mbed.h>
+
+/// Class to provide simple control of the Freescale MPL311A2 pressure and 
+/// temperature sensor. The class allows the user to read the pressure as
+/// barometric, altimeter or raw and the temperature in Celsius.
+///        
+/// Reading can be taken either on demand or continuously using either polling
+/// or interrupts to wait for the next reading. 
+///
+/// The correct modes should be get before either calling getReadings for
+/// single readings or activate to start continuous readings.
+class MPL3115A2 {
+public:
+    /// Enum for how the pressure data is to be read.
+    enum DataMode {
+        BarometricMode, ///< Barometric presure in Pascals
+        AltimeterMode,  ///< Altitude in meters
+        RawMode         ///< Raw values from internal DACs
+    };
+    
+    /// Enum for how consecutive readings are made
+    enum ReadMode {
+        Single,     ///< Make a single reading when calling getReadings, chip remains in standby the rest of the time
+        Polling,    ///< Make consecutive readings by polling isDataReady, chip is active all the time.
+        Interupt    ///< Make consecutive readings with an interrupt raised when data is ready, chip is active all the time.
+    };
+    
+    /// Enum to allow specifying which of the chips two interrupt pins to use.
+    enum InterruptPin {
+        INT1,   ///< Pin called INT1 on chip
+        INT2    ///< Pin called INT2 on chip
+    };
+    
+    /// Create a new instance of the class using the specified pins for the I2C bus.
+    /// Once initialised the chip is in standby mode.
+    /// @param sda The pin name for the sda line of the I2C bus.
+    /// @param scl The pin name for the scl line of the I2C bus.
+    MPL3115A2(PinName sda, PinName scl);
+    
+    /// Read the chip id, this is a fixed value of 0xC4.
+    /// @returns Chip id.
+    int getId(void);
+    
+    /// Set the how the pressure is read. The default is BarometricMode if to
+    /// be change then is must be called before getReadings or activate.
+    /// @param mode New mode to read pressure in.
+    void setDataMode(DataMode mode);
+    
+    /// Get the current setting for the pressure reading mode.
+    /// @returns Current pressure reading mode.
+    DataMode getDataMode(void);
+    
+    /// Set the how get continuous reading. The default is Single if to
+    /// be change then is must be called before getReadings or activate.
+    /// @param mode New continuous reading mode.
+    void setReadMode(ReadMode mode);
+    
+    /// Get the current setting for the continuous reading mode.
+    /// @returns Current continuous reading mode.
+    ReadMode getReadMode(void);
+    
+    /// Set the number of samples to be used for each reading.
+    /// The number must be a power of two between 1 and 128.
+    /// @param samples Number of samples per reading.
+    void setOverSampling(int samples);
+    
+    /// Get the number of samples to be used for each reading.
+    /// @returns Number of samples per reading.
+    int getOverSampling(void);
+    
+    /// Sets the number of seconds between consecutive readings.
+    /// The number must be a power of two between 1 and 32768.
+    /// @param period Number of seconds between consecutive readings.
+    void setSamplingPeriod(int period);
+    
+    /// Get the number of seconds between consecutive readings.
+    /// @returns Seconds between samples.
+    int getSamplingPeriod(void);
+    
+    /// Set which of the chips two interrupt pins should be used to signal
+    /// that the data is ready. It is up to the user to attach the interrupt
+    /// handler to the correct MCU pin and then call either getStatus or 
+    /// getReadings within the handler to clear the interrupt.
+    /// @param intPin Chip interrupt pin to signal data ready interrupts.
+    void setDataReadyInt(InterruptPin intPin);
+    
+    /// Get the configured interrupt pin used to signal that the data 
+    /// is ready.
+    /// @returns Current data ready interrupt pin.
+    InterruptPin getDataReadyInt(void);
+    
+    /// Read the chips STATUS register. The register contains data ready and
+    /// overwrite flags.
+    /// @returns Value of the STATUS register.
+    int getStatus(void);
+    
+    /// Returns true if there is data available to read.
+    /// @returns True is data is available to read otherwise false.
+    bool isDataReady(void);
+    
+    /// Put the chip into active state to allow taking of consecutive
+    /// samples. How often the samples are taken depends on the sampling
+    /// period, the maximum frequency is every one second and the minimum
+    /// every 9 hours.
+    void activate();
+    
+    /// Gives the active state of the chip
+    /// @returns True if the chip is in the active state otherwise false.
+    bool isActive();
+    
+    /// Puts the chip into the standby state and stops automatic readings.
+    void standby();
+    
+    /// Wait for and get the next readings for pressure and temperature.
+    /// If the reading mode is Single then the chip is setup and a wait
+    /// loop entered until the data is available.
+    /// If the reading mode is Polling then the wait loop is entered until
+    /// the next reading is available.
+    /// If the reading mode is Interrupt then the wait loop will exit imediately
+    /// as the data is already available. This will clear the interrupt.
+    /// @param pres Reference to variable to hold the pressure reading in Pascals
+    /// meters depending on the data mode.
+    /// @param temp Reference to variable to hold the temperature reading in
+    /// Celsius.
+    /// @returns True is the reading was sucessful otherwise false. The reading will
+    /// be unsuccessful if the data mode is raw.
+    bool getReadings(float &pres, float &temp);
+    
+private:
+    float convTemperature(char *data);
+    float convAltimeter(char *data);
+    float convPressure(char *data);
+    
+    void readRegs(char addr, char *data, int len);
+    void writeRegs(const char *data, int len);
+    
+private:
+    I2C m_i2c;
+    int m_addr;
+    
+    ReadMode m_readMode;
+    DataMode m_dataMode;
+    int m_overSample;
+    int m_samplePeriod;
+    InterruptPin m_dataReadInt;
+};
+
+#endif
\ No newline at end of file