you can use LPS25HB sensor on mbed.
Dependents: cansattougoutest mbed_LPS25HB koubousattttttttttttttttttttttdddddyorooooo koubousattttttttttttttttttttttddooaass ... more
Revision 0:4ea758df868a, committed 2018-12-22
- Comitter:
- tajiri1999
- Date:
- Sat Dec 22 16:44:40 2018 +0000
- Commit message:
- LPS25HB_i2c for mbed
Changed in this revision
diff -r 000000000000 -r 4ea758df868a LPS.cpp --- /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,®,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
diff -r 000000000000 -r 4ea758df868a LPS.h --- /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
diff -r 000000000000 -r 4ea758df868a sample.txt --- /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