Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update for product support and minor fixes #4

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 126 additions & 15 deletions LPS.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
#include <LPS.h>
#include "LPS.h"
#include <Wire.h>

/*
* For a rigorously complete implementation of the LPS25HB, see ST's github
* version at https://github.com/stm32duino/LPS25HB
*/

// Defines ///////////////////////////////////////////////////////////

// The Arduino two-wire interface uses a 7-bit number for the address,
Expand All @@ -18,7 +23,7 @@
LPS::LPS(void)
{
_device = device_auto;

// Pololu board pulls SA0 high, so default assumption is that it is
// high
address = SA0_HIGH_ADDRESS;
Expand All @@ -31,7 +36,7 @@ bool LPS::init(deviceType device, byte sa0)
{
if (!detectDeviceAndAddress(device, (sa0State)sa0))
return false;

switch (_device)
{
case device_25H:
Expand All @@ -41,7 +46,7 @@ bool LPS::init(deviceType device, byte sa0)
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;
Expand All @@ -50,9 +55,24 @@ bool LPS::init(deviceType device, byte sa0)
return true;
break;
}
return false;
}

// turns on sensor and enables 1Hz continuous output
// WARNING, this is absolute, intended for init section.
void LPS::enable1Hz(void)
{
if (_device == device_25H || _device == device_331AP)
{
// 0x90 = 0b10010000
// PD = 1 (active mode); ODR = 001b (1 Hz pressure & temperature output data rate)
writeReg(CTRL_REG1, 0x90);
}
}

// turns on sensor and enables continuous output

// turns on sensor and enables continuous output at 12.5 Hz
// WARNING, this is absolute, intended for init section.
void LPS::enableDefault(void)
{
if (_device == device_25H)
Expand All @@ -69,6 +89,28 @@ void LPS::enableDefault(void)
}
}

// sets the device to a specific FIFO mode
void LPS::enableFifo(fifoMode mode, bool decimate) {
if (_device == device_25H || _device == device_331AP){

// Set the correct FIFO_CTRL (2Eh)
byte fiforeg = readReg(FIFO_CTRL);
// The FIFO mode range is 3 bits wide at [7:5]
fiforeg &= ~(0b111 << 5);
fiforeg |= mode << 5;
writeReg(FIFO_CTRL, fiforeg);

// enable the FIFO mode in CTRL_REG2 (21h).
byte ctrlreg = readReg(CTRL_REG2);
bitSet(ctrlreg, 6);
// You can also decimate the FIFO in 1Hz mode here if you raise bit 4.
// Be sure to set the ODR to 0b001 in CTRL_REG1:[6:4] if you do. See enable1Hz() above.
if (decimate) bitSet(ctrlreg, 4);
writeReg(CTRL_REG2, ctrlreg);

}
}

// writes register
void LPS::writeReg(int reg, byte value)
{
Expand All @@ -88,7 +130,7 @@ void LPS::writeReg(int reg, byte value)
byte LPS::readReg(int reg)
{
byte value;

// if dummy register address, look up actual translated address (based on device type)
if (reg < 0)
{
Expand All @@ -108,7 +150,7 @@ byte LPS::readReg(int reg)
// reads pressure in millibars (mbar)/hectopascals (hPa)
float LPS::readPressureMillibars(void)
{
return (float)readPressureRaw() / 4096;
return (float)readPressureRaw() / 4096.0;
}

// reads pressure in inches of mercury (inHg)
Expand Down Expand Up @@ -139,13 +181,13 @@ int32_t LPS::readPressureRaw(void)
// reads temperature in degrees C
float LPS::readTemperatureC(void)
{
return 42.5 + (float)readTemperatureRaw() / 480;
return 42.5 + (float)readTemperatureRaw() / 480.0;
}

// reads temperature in degrees F
float LPS::readTemperatureF(void)
{
return 108.5 + (float)readTemperatureRaw() / 480 * 1.8;
return 108.5 + (float)readTemperatureRaw() / 480.0 * 1.8;
}

// reads temperature and returns raw 16-bit sensor output
Expand All @@ -169,20 +211,89 @@ int16_t LPS::readTemperatureRaw(void)
// 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
// If altimeter setting (QNH, barometric pressure adjusted to standard 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
// mbar or 29.921 inHg
float LPS::pressureToAltitudeMeters(float pressure_mbar, float altimeter_setting_mbar)
{
return (1 - pow(pressure_mbar / altimeter_setting_mbar, 0.190263)) * 44330.8;
return (1.0 - pow(pressure_mbar / altimeter_setting_mbar, 0.190263)) * 44330.8;
}

// converts pressure in inHg to altitude in feet; see notes above
float LPS::pressureToAltitudeFeet(float pressure_inHg, float altimeter_setting_inHg)
{
return (1 - pow(pressure_inHg / altimeter_setting_inHg, 0.190263)) * 145442;
return (1.0 - pow(pressure_inHg / altimeter_setting_inHg, 0.190263)) * 145442.0;
}

// Generic extension of the above two functions.
float LPS::pressureToAltitude(float pressure, float altimeter_setting, bool metric)
{
const float factor = (metric ? 44330.8 : 145442.0);
return (1.0 - pow(pressure / altimeter_setting, 0.190263)) * factor;
}

// Pressure (hPa), temp (C) and altitude (m), return sea level barometric pressure
// QFF is returned in millibars unless politely declined, in which case you get inHg
float LPS::altitudeToQFF(float altitude_meters, float tempC, bool please_return_mbars) {
const float factor = (please_return_mbars ? 1.0 : 33.864);
float pressure_mbar = LPS::readPressureMillibars();

float qff = pressure_mbar /
pow(((-0.0065 * altitude_meters) /
( 0.0065 * altitude_meters + 273.15 + tempC)), 5.2559);

return (qff / factor);
}

/*
* Use this when you first get your device. Tell it your local info and it will help
* you see what your RPDS_L (0x39) and/or RPDS_H (0x3A) should be. Then you can use the
* above to report accurately your local true sea level barometric pressure (QFF).
*/
int32_t LPS::opcHelper(float my_local_qff_mbar, float my_local_altitude_meters) {
// real programmers would turn on BDU here, first.
int32_t currentRawPressure = LPS::readPressureRaw();
byte rpds_low, rpds_high;
int16_t returnVal;

rpds_low = readReg(LPS::RPDS_L);
rpds_high = readReg(LPS::RPDS_H);

Serial.print("Your local pressure:\t\t");
Serial.print(my_local_qff_mbar);
Serial.print(" mbar, which is ");

Serial.print((int32_t)(my_local_qff_mbar * 4096.0));
Serial.println(" int32_t");

Serial.print("Your local altitude:\t\t");
Serial.print(my_local_altitude_meters);
Serial.println(" m");

Serial.println("According to the current device state, your local QFF should be:");
Serial.println(LPS::altitudeToQFF(my_local_altitude_meters));

Serial.print("Sensor raw pressure:\t\t");
Serial.print(currentRawPressure);
Serial.println(" int32_t");

Serial.print("Sensor millibars:\t\t");
Serial.print((float)currentRawPressure / 4096.0);
Serial.println(" mbar");

Serial.print("Current RPDS_L:\t\t");
Serial.print(rpds_low, BIN);
Serial.println(" binary");
Serial.print("Current RPDS_H:\t\t");
Serial.print(rpds_high, BIN);
Serial.println(" binary");

returnVal = (currentRawPressure - (int32_t)(my_local_qff_mbar * 4096.0));

return returnVal;

}

// Private Methods ///////////////////////////////////////////////////
Expand All @@ -206,7 +317,7 @@ bool LPS::detectDeviceAndAddress(deviceType device, sa0State sa0)
bool LPS::detectDevice(deviceType device)
{
int id = testWhoAmI(address);

if ((device == device_auto || device == device_25H) && id == LPS25H_WHO_ID)
{
_device = device_25H;
Expand All @@ -232,4 +343,4 @@ int LPS::testWhoAmI(byte address)
return Wire.read();
else
return TEST_REG_NACK;
}
}
65 changes: 46 additions & 19 deletions LPS.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,28 @@
class LPS
{
public:
enum deviceType { device_331AP, device_25H, device_auto };
enum deviceType { device_331AP, device_25H, device_25HB = device_25H, device_auto };
enum sa0State { sa0_low, sa0_high, sa0_auto };

/// Size of the hardware moving average depth, from 2 to 32 samples
enum fifoMeanModeSize {
SAMPLES_1 = 0b00001, // 2
SAMPLES_2 = 0b00011, // 4
SAMPLES_3 = 0b00111, // 8
SAMPLES_4 = 0b01111, // 16
SAMPLES_5 = 0b11111 // 32
};

enum fifoMode {
BYPASS,
FIFO,
STREAM,
STREAM2FIFO,
BYPASS2STREAM,
FIFOMEAN = 0b110,
BYPASS2FIFO
};

// register addresses
// Note: where register names differ between the register mapping table and
// the register descriptions in the datasheets, the names from the register
Expand All @@ -18,56 +37,56 @@ class LPS
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,
Expand All @@ -81,6 +100,9 @@ class LPS
byte getAddress(void) { return address; }

void enableDefault(void);
void enable1Hz(void);

void enableFifo(fifoMode mode, bool decimate = false);

void writeReg(int reg, byte value);
byte readReg(int reg);
Expand All @@ -94,11 +116,16 @@ class LPS

static float pressureToAltitudeMeters(float pressure_mbar, float altimeter_setting_mbar = 1013.25);
static float pressureToAltitudeFeet(float pressure_inHg, float altimeter_setting_inHg = 29.9213);
static float pressureToAltitude(float pressure, float altimeter_setting, bool metric = true);

float altitudeToQFF(float altitude_meters, float tempC = 15.0, bool please_return_mbars = true);

int32_t opcHelper(float my_local_qff_mbar, float my_local_altitude_meters);

private:
deviceType _device; // chip type (331AP or 25H)
byte address;

static const int dummy_reg_count = 4;
regAddr translated_regs[dummy_reg_count + 1]; // index 0 not used

Expand All @@ -107,4 +134,4 @@ class LPS
int testWhoAmI(byte address);
};

#endif
#endif
Loading