you can use LPS25HB sensor on mbed.

Dependents:   cansattougoutest mbed_LPS25HB koubousattttttttttttttttttttttdddddyorooooo koubousattttttttttttttttttttttddooaass ... more

Files at this revision

API Documentation at this revision

Comitter:
tajiri1999
Date:
Sat Dec 22 16:44:40 2018 +0000
Commit message:
LPS25HB_i2c for mbed

Changed in this revision

LPS.cpp Show annotated file Show diff for this revision Revisions of this file
LPS.h Show annotated file Show diff for this revision Revisions of this file
sample.txt Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LPS.cpp	Sat Dec 22 16:44:40 2018 +0000
@@ -0,0 +1,212 @@
+#include "LPS.h"
+#include "mbed.h"
+
+// Defines ///////////////////////////////////////////////////////////
+
+// The Arduino two-wire interface uses a 7-bit number for the address,
+#define SA0_LOW_ADDRESS  0b1011100
+#define SA0_HIGH_ADDRESS 0b1011101
+
+#define TEST_REG_NACK -1
+
+#define LPS331AP_WHO_ID 0xBB
+#define LPS25H_WHO_ID   0xBD
+
+// Constructors //////////////////////////////////////////////////////
+
+LPS::LPS(I2C& p_i2c):_i2c(p_i2c)
+{
+    _device = device_auto;
+  
+    // Pololu board pulls SA0 high, so default assumption is that it is
+    // high
+    address = SA0_HIGH_ADDRESS;
+}
+
+// Public Methods ////////////////////////////////////////////////////
+
+// sets or detects device type and slave address; returns bool indicating success
+bool LPS::init(deviceType device, uint8_t sa0)
+{
+    if (!detectDeviceAndAddress(device, (sa0State)sa0))
+        return false;
+    
+    switch (_device)
+    {
+        case device_25H:
+        translated_regs[-INTERRUPT_CFG] = LPS25H_INTERRUPT_CFG;
+        translated_regs[-INT_SOURCE]    = LPS25H_INT_SOURCE;
+        translated_regs[-THS_P_L]       = LPS25H_THS_P_L;
+        translated_regs[-THS_P_H]       = LPS25H_THS_P_H;
+        return true;
+        break;
+      
+        case device_331AP:
+        translated_regs[-INTERRUPT_CFG] = LPS331AP_INTERRUPT_CFG;
+        translated_regs[-INT_SOURCE]    = LPS331AP_INT_SOURCE;
+        translated_regs[-THS_P_L]       = LPS331AP_THS_P_L;
+        translated_regs[-THS_P_H]       = LPS331AP_THS_P_H;
+        return true;
+        break;
+    }
+}
+
+// turns on sensor and enables continuous output
+void LPS::enableDefault(void)
+{
+    if (_device == device_25H)
+    {
+        // 0xB0 = 0b10110000
+        // PD = 1 (active mode);  ODR = 011 (12.5 Hz pressure & temperature output data rate)
+        writeReg(CTRL_REG1, 0xB0);
+    }
+    else if (_device == device_331AP)
+    {
+        // 0xE0 = 0b11100000
+        // PD = 1 (active mode);  ODR = 110 (12.5 Hz pressure & temperature output data rate)
+        writeReg(CTRL_REG1, 0xE0);
+    }
+}
+
+// writes register
+void LPS::writeReg(char reg, char value)
+{
+    // if dummy register address, look up actual translated address (based on device type)
+    if (reg < 0)
+    {
+        reg = translated_regs[-reg];
+    }
+    char command[] = {reg,value};
+    _i2c.write(address << 1,command,2);
+}
+
+// reads register
+int8_t LPS::readReg(char reg)
+{
+    char value;
+    // if dummy register address, look up actual translated address (based on device type)
+    if(reg < 0)
+    {
+        reg = translated_regs[-reg];
+    }
+    _i2c.write(address << 1,&reg,1);
+    _i2c.read((address << 1)|1,&value,1);
+  
+    return value;
+}
+
+// reads pressure in millibars (mbar)/hectopascals (hPa)
+float LPS::readPressureMillibars(void)
+{
+    return (float)readPressureRaw() / 4096;
+}
+
+// reads pressure in inches of mercury (inHg)
+float LPS::readPressureInchesHg(void)
+{
+    return (float)readPressureRaw() / 138706.5;
+}
+
+// reads pressure and returns raw 24-bit sensor output
+int32_t LPS::readPressureRaw(void)
+{
+    // assert MSB to enable register address auto-increment
+  
+    char command = PRESS_OUT_XL | (1 << 7);
+    char p[3];
+    _i2c.write(address << 1,&command,1);
+    _i2c.read((address << 1)| 1,p,3);
+  
+    // combine int8_ts
+    return (int32_t)(int8_t)p[2] << 16 | (uint16_t)p[1] << 8 | p[0];
+}
+
+// reads temperature in degrees C
+float LPS::readTemperatureC(void)
+{
+    return 42.5 + (float)readTemperatureRaw() / 480;
+}
+
+// reads temperature in degrees F
+float LPS::readTemperatureF(void)
+{
+    return 108.5 + (float)readTemperatureRaw() / 480 * 1.8;
+}
+
+// reads temperature and returns raw 16-bit sensor output
+int16_t LPS::readTemperatureRaw(void)
+{
+    char command = TEMP_OUT_L | (1 << 7);
+  
+    // assert MSB to enable register address auto-increment
+    char t[2];
+    _i2c.write(address << 1,&command,1);
+    _i2c.read((address << 1)| 1,t,2);
+
+    // combine bytes
+    return (int16_t)(t[1] << 8 | t[0]);
+}
+
+// converts pressure in mbar to altitude in meters, using 1976 US
+// Standard Atmosphere model (note that this formula only applies to a
+// height of 11 km, or about 36000 ft)
+//  If altimeter setting (QNH, barometric pressure adjusted to sea
+//  level) is given, this function returns an indicated altitude
+//  compensated for actual regional pressure; otherwise, it returns
+//  the pressure altitude above the standard pressure level of 1013.25
+//  mbar or 29.9213 inHg
+float LPS::pressureToAltitudeMeters(double pressure_mbar, double altimeter_setting_mbar)
+{
+    return (1 - pow(pressure_mbar / altimeter_setting_mbar, 0.190263)) * 44330.8;//pressure;
+}
+
+// converts pressure in inHg to altitude in feet; see notes above
+float LPS::pressureToAltitudeFeet(double pressure_inHg, double altimeter_setting_inHg)
+{
+    return (1 - pow(pressure_inHg / altimeter_setting_inHg, 0.190263)) * 145442;//pressure;
+}
+
+// Private Methods ///////////////////////////////////////////////////
+
+bool LPS::detectDeviceAndAddress(deviceType device, sa0State sa0)
+{
+    if (sa0 == sa0_auto || sa0 == sa0_high)
+    {
+        address = SA0_HIGH_ADDRESS;
+        if (detectDevice(device)) return true;
+    }
+    if (sa0 == sa0_auto || sa0 == sa0_low)
+    {
+        address = SA0_LOW_ADDRESS;
+        if (detectDevice(device)) return true;
+    }
+
+    return false;
+}
+
+bool LPS::detectDevice(deviceType device)
+{
+    uint8_t id = testWhoAmI(address);
+  
+    if ((device == device_auto || device == device_25H) && id == (uint8_t)LPS25H_WHO_ID)
+    {
+        _device = device_25H;
+        return true;
+    }
+    if ((device == device_auto || device == device_331AP) && id == (uint8_t)LPS331AP_WHO_ID)
+    {
+        _device = device_331AP;
+        return true;
+    }
+
+    return false;
+}
+
+int LPS::testWhoAmI(uint8_t address)
+{
+    char command = WHO_AM_I;
+    char status = 0;
+    _i2c.write(address << 1,&command,1);
+    _i2c.read((address << 1)| 1,&status,1);
+    return status;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LPS.h	Sat Dec 22 16:44:40 2018 +0000
@@ -0,0 +1,111 @@
+#ifndef LPS_h
+#define LPS_h
+
+#include "mbed.h" // for int8_t data type
+
+class LPS
+{
+  public:
+    enum deviceType { device_331AP, device_25H, device_auto };
+    enum sa0State { sa0_low, sa0_high, sa0_auto };
+
+    // register addresses
+    // Note: where register names differ between the register mapping table and
+    // the register descriptions in the datasheets, the names from the register
+    // descriptions are used here.
+    enum regAddr
+    {
+      REF_P_XL                = 0x08,
+      REF_P_L                 = 0x09,
+      REF_P_H                 = 0x0A,
+                              
+      WHO_AM_I                = 0x0F,
+                              
+      RES_CONF                = 0x10,
+                              
+      CTRL_REG1               = 0x20,
+      CTRL_REG2               = 0x21,
+      CTRL_REG3               = 0x22,
+      CTRL_REG4               = 0x23, // 25H
+              
+      STATUS_REG              = 0x27,
+                            
+      PRESS_OUT_XL            = 0x28,
+      PRESS_OUT_L             = 0x29,
+      PRESS_OUT_H             = 0x2A,
+
+      TEMP_OUT_L              = 0x2B,
+      TEMP_OUT_H              = 0x2C,
+      
+      FIFO_CTRL               = 0x2E, // 25H
+      FIFO_STATUS             = 0x2F, // 25H
+      
+      AMP_CTRL                = 0x30, // 331AP
+      
+      RPDS_L                  = 0x39, // 25H
+      RPDS_H                  = 0x3A, // 25H
+      
+      DELTA_PRESS_XL          = 0x3C, // 331AP
+      DELTA_PRESS_L           = 0x3D, // 331AP
+      DELTA_PRESS_H           = 0x3E, // 331AP
+      
+      
+      // dummy addresses for registers in different locations on different devices;
+      // the library translates these based on device type
+      // value with sign flipped is used as index into translated_regs array
+    
+      INTERRUPT_CFG    = -1,
+      INT_SOURCE       = -2,
+      THS_P_L          = -3,
+      THS_P_H          = -4,
+      // update dummy_reg_count if registers are added here!
+      
+      
+      // device-specific register addresses
+      
+      LPS331AP_INTERRUPT_CFG  = 0x23,
+      LPS331AP_INT_SOURCE     = 0x24,
+      LPS331AP_THS_P_L        = 0x25,
+      LPS331AP_THS_P_H        = 0x26,
+      
+      LPS25H_INTERRUPT_CFG    = 0x24,
+      LPS25H_INT_SOURCE       = 0x25,
+      LPS25H_THS_P_L          = 0x30,
+      LPS25H_THS_P_H          = 0x31,
+    };
+
+    LPS(I2C& p_i2c);
+
+    bool init(deviceType device = device_auto,uint8_t sa0 = sa0_auto);
+    deviceType getDeviceType(void) { return _device; }
+    int8_t getAddress(void) { return address; }
+
+    void enableDefault(void);
+
+    void writeReg(char reg, char value);
+    int8_t readReg(char reg);
+
+    float readPressureMillibars(void);
+    float readPressureInchesHg(void);
+    int32_t readPressureRaw(void);
+    float readTemperatureC(void);
+    float readTemperatureF(void);
+    int16_t readTemperatureRaw(void);
+
+    static float pressureToAltitudeMeters(double pressure_mbar, double altimeter_setting_mbar = 1013.25);
+    static float pressureToAltitudeFeet(double pressure_inHg, double altimeter_setting_inHg = 29.9213);
+
+  private:
+    deviceType _device; // chip type (331AP or 25H)
+    I2C &_i2c;
+    uint8_t address;
+    
+    static const int dummy_reg_count = 4;
+    regAddr translated_regs[dummy_reg_count + 1]; // index 0 not used
+
+    bool detectDeviceAndAddress(deviceType device, sa0State sa0);
+    bool detectDevice(deviceType device);
+    int testWhoAmI(uint8_t address);
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sample.txt	Sat Dec 22 16:44:40 2018 +0000
@@ -0,0 +1,23 @@
+#include "mbed.h"
+#include "LPS.h"
+
+I2C i2c(D14,D15);
+LPS ps(i2c);
+
+int main(){
+    wait_ms(100);
+    if (!ps.init()){
+        printf("Failed to autodetect pressure sensor!\r\n");
+        while (1);
+    }
+    ps.enableDefault();
+    
+    while(1){
+        float pressure = ps.readPressureMillibars();
+        float altitude = ps.pressureToAltitudeMeters(pressure);
+        float temperature = ps.readTemperatureC();
+  
+        printf("p:%.2f\t mbar\ta:%.2f m\tt:%.2f deg C\r\n",pressure,altitude,temperature);
+    }
+    wait_ms(100);
+}
\ No newline at end of file