forked from adafruit/Adafruit_BMP085_Unified
Implemented error handling and performance improvements
This commit is contained in:
@@ -38,6 +38,14 @@
|
||||
#include <Wire.h>
|
||||
#endif
|
||||
|
||||
//#define DEBUG_OUTPUT
|
||||
#ifdef DEBUG_OUTPUT
|
||||
#include <esp_log.h>
|
||||
#define DBGPRNT(format, ...) ESP_LOGW("BMP085", format, ##__VA_ARGS__)
|
||||
#else
|
||||
#define DBGPRNT(format, ...)
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
|
||||
@@ -52,6 +60,14 @@ static uint8_t _bmp085Mode;
|
||||
#define BMP085_USE_DATASHEET_VALS \
|
||||
(0) //!< Set to 1 for sanity check, when true, will use values from datasheet
|
||||
|
||||
#if ARDUINO >= 100
|
||||
#define WIRE_WRITE Wire.write
|
||||
#define WIRE_READ Wire.read
|
||||
#else
|
||||
#define WIRE_WRITE Wire.send
|
||||
#define WIRE_READ Wire.receive
|
||||
#endif
|
||||
|
||||
/***************************************************************************
|
||||
PRIVATE FUNCTIONS
|
||||
***************************************************************************/
|
||||
@@ -61,16 +77,15 @@ static uint8_t _bmp085Mode;
|
||||
@brief Writes an 8 bit value over I2C
|
||||
*/
|
||||
/**************************************************************************/
|
||||
static void writeCommand(byte reg, byte value) {
|
||||
static bool writeCommand(byte reg, byte value) {
|
||||
bool succ{true};
|
||||
|
||||
Wire.beginTransmission((uint8_t)BMP085_ADDRESS);
|
||||
#if ARDUINO >= 100
|
||||
Wire.write((uint8_t)reg);
|
||||
Wire.write((uint8_t)value);
|
||||
#else
|
||||
Wire.send(reg);
|
||||
Wire.send(value);
|
||||
#endif
|
||||
Wire.endTransmission();
|
||||
if (WIRE_WRITE((uint8_t)reg) != 1) { DBGPRNT("fail"); succ = false; }
|
||||
if (WIRE_WRITE((uint8_t)value) != 1) { DBGPRNT("fail"); succ = false; }
|
||||
if (const auto result = Wire.endTransmission(); result != I2C_ERROR_OK) { DBGPRNT("fail %hhu", result); succ = false; }
|
||||
|
||||
return succ;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
@@ -78,21 +93,21 @@ static void writeCommand(byte reg, byte value) {
|
||||
@brief Reads an 8 bit value over I2C
|
||||
*/
|
||||
/**************************************************************************/
|
||||
static void read8(byte reg, uint8_t *value) {
|
||||
static bool read8(byte reg, uint8_t *value) {
|
||||
bool succ{true};
|
||||
|
||||
Wire.beginTransmission((uint8_t)BMP085_ADDRESS);
|
||||
#if ARDUINO >= 100
|
||||
Wire.write((uint8_t)reg);
|
||||
#else
|
||||
Wire.send(reg);
|
||||
#endif
|
||||
Wire.endTransmission();
|
||||
Wire.requestFrom((uint8_t)BMP085_ADDRESS, (byte)1);
|
||||
#if ARDUINO >= 100
|
||||
*value = Wire.read();
|
||||
#else
|
||||
*value = Wire.receive();
|
||||
#endif
|
||||
if (WIRE_WRITE((uint8_t)reg) != 1) { DBGPRNT("fail"); succ = false; }
|
||||
if (const auto result = Wire.endTransmission(); result != I2C_ERROR_OK) { DBGPRNT("fail %hhu", result); succ = false; }
|
||||
|
||||
if (const auto result = Wire.requestFrom((uint8_t)BMP085_ADDRESS, (byte)1); result != 1) { DBGPRNT("fail %hhu", result); succ = false; }
|
||||
if (const auto result = WIRE_READ(); result == -1) { DBGPRNT("fail %i", result); succ = false; }
|
||||
else *value = result;
|
||||
|
||||
//if (const auto result = Wire.endTransmission(); result != I2C_ERROR_OK) { DBGPRNT("fail %hhu", result); succ = false; }
|
||||
Wire.endTransmission();
|
||||
|
||||
return succ;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
@@ -100,21 +115,24 @@ static void read8(byte reg, uint8_t *value) {
|
||||
@brief Reads a 16 bit value over I2C
|
||||
*/
|
||||
/**************************************************************************/
|
||||
static void read16(byte reg, uint16_t *value) {
|
||||
static bool read16(byte reg, uint16_t *value) {
|
||||
bool succ{true};
|
||||
|
||||
Wire.beginTransmission((uint8_t)BMP085_ADDRESS);
|
||||
#if ARDUINO >= 100
|
||||
Wire.write((uint8_t)reg);
|
||||
#else
|
||||
Wire.send(reg);
|
||||
#endif
|
||||
Wire.endTransmission();
|
||||
Wire.requestFrom((uint8_t)BMP085_ADDRESS, (byte)2);
|
||||
#if ARDUINO >= 100
|
||||
*value = (Wire.read() << 8) | Wire.read();
|
||||
#else
|
||||
*value = (Wire.receive() << 8) | Wire.receive();
|
||||
#endif
|
||||
if (WIRE_WRITE((uint8_t)reg) != 1) { DBGPRNT("fail"); succ = false; }
|
||||
if (const auto result = Wire.endTransmission(); result != I2C_ERROR_OK) { DBGPRNT("fail %hhu", result); succ = false; }
|
||||
|
||||
if (const auto result = Wire.requestFrom((uint8_t)BMP085_ADDRESS, (byte)2); result != 2) { DBGPRNT("fail %hhu", result); succ = false; }
|
||||
const auto result0 = WIRE_READ();
|
||||
const auto result1 = WIRE_READ();
|
||||
if (result0 == -1) { DBGPRNT("fail %i", result0); succ = false; }
|
||||
else if (result1 == -1) { DBGPRNT("fail %i", result1); succ = false; }
|
||||
else { *value = (result0 << 8) | result1; }
|
||||
|
||||
//if (const auto result = Wire.endTransmission(); result != I2C_ERROR_OK) { DBGPRNT("fail %hhu", result); succ = false; }
|
||||
Wire.endTransmission();
|
||||
|
||||
return succ;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
@@ -122,10 +140,12 @@ static void read16(byte reg, uint16_t *value) {
|
||||
@brief Reads a signed 16 bit value over I2C
|
||||
*/
|
||||
/**************************************************************************/
|
||||
static void readS16(byte reg, int16_t *value) {
|
||||
static bool readS16(byte reg, int16_t *value) {
|
||||
bool succ{true};
|
||||
uint16_t i;
|
||||
read16(reg, &i);
|
||||
*value = (int16_t)i;
|
||||
if (!read16(reg, &i)) { DBGPRNT("fail"); succ = false; }
|
||||
else *value = (int16_t)i;
|
||||
return succ;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
@@ -133,7 +153,8 @@ static void readS16(byte reg, int16_t *value) {
|
||||
@brief Reads the factory-set coefficients
|
||||
*/
|
||||
/**************************************************************************/
|
||||
static void readCoefficients(void) {
|
||||
static bool readCoefficients(void) {
|
||||
bool succ{true};
|
||||
#if BMP085_USE_DATASHEET_VALS
|
||||
_bmp085_coeffs.ac1 = 408;
|
||||
_bmp085_coeffs.ac2 = -72;
|
||||
@@ -148,18 +169,19 @@ static void readCoefficients(void) {
|
||||
_bmp085_coeffs.md = 2868;
|
||||
_bmp085Mode = 0;
|
||||
#else
|
||||
readS16(BMP085_REGISTER_CAL_AC1, &_bmp085_coeffs.ac1);
|
||||
readS16(BMP085_REGISTER_CAL_AC2, &_bmp085_coeffs.ac2);
|
||||
readS16(BMP085_REGISTER_CAL_AC3, &_bmp085_coeffs.ac3);
|
||||
read16(BMP085_REGISTER_CAL_AC4, &_bmp085_coeffs.ac4);
|
||||
read16(BMP085_REGISTER_CAL_AC5, &_bmp085_coeffs.ac5);
|
||||
read16(BMP085_REGISTER_CAL_AC6, &_bmp085_coeffs.ac6);
|
||||
readS16(BMP085_REGISTER_CAL_B1, &_bmp085_coeffs.b1);
|
||||
readS16(BMP085_REGISTER_CAL_B2, &_bmp085_coeffs.b2);
|
||||
readS16(BMP085_REGISTER_CAL_MB, &_bmp085_coeffs.mb);
|
||||
readS16(BMP085_REGISTER_CAL_MC, &_bmp085_coeffs.mc);
|
||||
readS16(BMP085_REGISTER_CAL_MD, &_bmp085_coeffs.md);
|
||||
if (!readS16(BMP085_REGISTER_CAL_AC1, &_bmp085_coeffs.ac1)) { DBGPRNT("fail"); succ = false; }
|
||||
if (!readS16(BMP085_REGISTER_CAL_AC2, &_bmp085_coeffs.ac2)) { DBGPRNT("fail"); succ = false; }
|
||||
if (!readS16(BMP085_REGISTER_CAL_AC3, &_bmp085_coeffs.ac3)) { DBGPRNT("fail"); succ = false; }
|
||||
if (!read16(BMP085_REGISTER_CAL_AC4, &_bmp085_coeffs.ac4)) { DBGPRNT("fail"); succ = false; }
|
||||
if (!read16(BMP085_REGISTER_CAL_AC5, &_bmp085_coeffs.ac5)) { DBGPRNT("fail"); succ = false; }
|
||||
if (!read16(BMP085_REGISTER_CAL_AC6, &_bmp085_coeffs.ac6)) { DBGPRNT("fail"); succ = false; }
|
||||
if (!readS16(BMP085_REGISTER_CAL_B1, &_bmp085_coeffs.b1)) { DBGPRNT("fail"); succ = false; }
|
||||
if (!readS16(BMP085_REGISTER_CAL_B2, &_bmp085_coeffs.b2)) { DBGPRNT("fail"); succ = false; }
|
||||
if (!readS16(BMP085_REGISTER_CAL_MB, &_bmp085_coeffs.mb)) { DBGPRNT("fail"); succ = false; }
|
||||
if (!readS16(BMP085_REGISTER_CAL_MC, &_bmp085_coeffs.mc)) { DBGPRNT("fail"); succ = false; }
|
||||
if (!readS16(BMP085_REGISTER_CAL_MD, &_bmp085_coeffs.md)) { DBGPRNT("fail"); succ = false; }
|
||||
#endif
|
||||
return succ;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
@@ -167,15 +189,19 @@ static void readCoefficients(void) {
|
||||
|
||||
*/
|
||||
/**************************************************************************/
|
||||
static void readRawTemperature(int32_t *temperature) {
|
||||
static std::optional<int32_t> readRawTemperature() {
|
||||
#if BMP085_USE_DATASHEET_VALS
|
||||
*temperature = 27898;
|
||||
return 27898;
|
||||
#else
|
||||
uint16_t t;
|
||||
writeCommand(BMP085_REGISTER_CONTROL, BMP085_REGISTER_READTEMPCMD);
|
||||
bool succ{true};
|
||||
if (!writeCommand(BMP085_REGISTER_CONTROL, BMP085_REGISTER_READTEMPCMD)) { DBGPRNT("fail"); succ = false; }
|
||||
delay(5);
|
||||
read16(BMP085_REGISTER_TEMPDATA, &t);
|
||||
*temperature = t;
|
||||
uint16_t t;
|
||||
if (!read16(BMP085_REGISTER_TEMPDATA, &t)) { DBGPRNT("fail"); succ = false; }
|
||||
if (succ)
|
||||
return t;
|
||||
else
|
||||
return std::nullopt;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -184,16 +210,14 @@ static void readRawTemperature(int32_t *temperature) {
|
||||
|
||||
*/
|
||||
/**************************************************************************/
|
||||
static void readRawPressure(int32_t *pressure) {
|
||||
static std::optional<int32_t> readRawPressure() {
|
||||
#if BMP085_USE_DATASHEET_VALS
|
||||
*pressure = 23843;
|
||||
return 23843;
|
||||
#else
|
||||
uint8_t p8;
|
||||
uint16_t p16;
|
||||
int32_t p32;
|
||||
bool succ{true};
|
||||
|
||||
writeCommand(BMP085_REGISTER_CONTROL,
|
||||
BMP085_REGISTER_READPRESSURECMD + (_bmp085Mode << 6));
|
||||
if (!writeCommand(BMP085_REGISTER_CONTROL,
|
||||
BMP085_REGISTER_READPRESSURECMD + (_bmp085Mode << 6))) { DBGPRNT("fail"); succ = false; }
|
||||
switch (_bmp085Mode) {
|
||||
case BMP085_MODE_ULTRALOWPOWER:
|
||||
delay(5);
|
||||
@@ -210,13 +234,25 @@ static void readRawPressure(int32_t *pressure) {
|
||||
break;
|
||||
}
|
||||
|
||||
read16(BMP085_REGISTER_PRESSUREDATA, &p16);
|
||||
p32 = (uint32_t)p16 << 8;
|
||||
read8(BMP085_REGISTER_PRESSUREDATA + 2, &p8);
|
||||
p32 += p8;
|
||||
p32 >>= (8 - _bmp085Mode);
|
||||
int32_t p32{};
|
||||
|
||||
*pressure = p32;
|
||||
{
|
||||
uint16_t p16;
|
||||
if (!read16(BMP085_REGISTER_PRESSUREDATA, &p16)) { DBGPRNT("fail"); succ = false; }
|
||||
else if (succ) p32 += (uint32_t)p16 << 8;
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t p8;
|
||||
if (!read8(BMP085_REGISTER_PRESSUREDATA + 2, &p8)) { DBGPRNT("fail"); succ = false; }
|
||||
else if (succ) p32 += p8;
|
||||
}
|
||||
|
||||
if (succ) {
|
||||
p32 >>= (8 - _bmp085Mode);
|
||||
return p32;
|
||||
} else
|
||||
return std::nullopt;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -258,7 +294,8 @@ Adafruit_BMP085_Unified::Adafruit_BMP085_Unified(int32_t sensorID) {
|
||||
bool Adafruit_BMP085_Unified::begin(bool skipWireBegin, bmp085_mode_t mode) {
|
||||
// Enable I2C
|
||||
if (!skipWireBegin)
|
||||
Wire.begin();
|
||||
if (!Wire.begin())
|
||||
{ DBGPRNT("fail"); return false; }
|
||||
|
||||
/* Mode boundary check */
|
||||
if ((mode > BMP085_MODE_ULTRAHIGHRES) || (mode < 0)) {
|
||||
@@ -267,16 +304,14 @@ bool Adafruit_BMP085_Unified::begin(bool skipWireBegin, bmp085_mode_t mode) {
|
||||
|
||||
/* Make sure we have the right device */
|
||||
uint8_t id;
|
||||
read8(BMP085_REGISTER_CHIPID, &id);
|
||||
if (id != 0x55) {
|
||||
return false;
|
||||
}
|
||||
if (!read8(BMP085_REGISTER_CHIPID, &id)) { DBGPRNT("fail"); return false; }
|
||||
if (id != 0x55) { DBGPRNT("fail"); return false; }
|
||||
|
||||
/* Set the mode indicator */
|
||||
_bmp085Mode = mode;
|
||||
|
||||
/* Coefficients need to be read once */
|
||||
readCoefficients();
|
||||
if (!readCoefficients()) { DBGPRNT("fail"); return false; }
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -286,14 +321,33 @@ bool Adafruit_BMP085_Unified::begin(bool skipWireBegin, bmp085_mode_t mode) {
|
||||
@brief Gets the compensated pressure level in kPa
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void Adafruit_BMP085_Unified::getPressure(float *pressure) {
|
||||
int32_t ut = 0, up = 0, compp = 0;
|
||||
int32_t x1, x2, b5, b6, x3, b3, p;
|
||||
uint32_t b4, b7;
|
||||
std::optional<float> Adafruit_BMP085_Unified::getPressure() {
|
||||
int32_t ut;
|
||||
|
||||
/* Get the raw pressure and temperature values */
|
||||
readRawTemperature(&ut);
|
||||
readRawPressure(&up);
|
||||
if (const auto rawTemp = readRawTemperature())
|
||||
ut = *rawTemp;
|
||||
else
|
||||
{ DBGPRNT("fail"); return std::nullopt; }
|
||||
|
||||
int32_t up;
|
||||
|
||||
if (const auto rawPress = readRawPressure())
|
||||
up = *rawPress;
|
||||
else
|
||||
{ DBGPRNT("fail"); return std::nullopt; }
|
||||
|
||||
return getPressure(ut, up);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Gets the compensated pressure level in kPa
|
||||
*/
|
||||
/**************************************************************************/
|
||||
float Adafruit_BMP085_Unified::getPressure(int32_t ut, int32_t up) {
|
||||
int32_t x1, x2, b5, b6, x3, b3, p;
|
||||
uint32_t b4, b7;
|
||||
|
||||
/* Temperature compensation */
|
||||
b5 = computeB5(ut);
|
||||
@@ -319,10 +373,32 @@ void Adafruit_BMP085_Unified::getPressure(float *pressure) {
|
||||
x1 = (p >> 8) * (p >> 8);
|
||||
x1 = (x1 * 3038) >> 16;
|
||||
x2 = (-7357 * p) >> 16;
|
||||
compp = p + ((x1 + x2 + 3791) >> 4);
|
||||
float compp = p + ((x1 + x2 + 3791) >> 4);
|
||||
|
||||
/* Assign compensated pressure value */
|
||||
*pressure = compp;
|
||||
return compp / 100.f;
|
||||
}
|
||||
|
||||
std::optional<Adafruit_BMP085_Unified::TemperatureAndPressure> Adafruit_BMP085_Unified::getTemperatureAndPressure() {
|
||||
int32_t ut;
|
||||
|
||||
/* Get the raw pressure and temperature values */
|
||||
if (const auto rawTemp = readRawTemperature())
|
||||
ut = *rawTemp;
|
||||
else
|
||||
{ DBGPRNT("fail"); return std::nullopt; }
|
||||
|
||||
int32_t up;
|
||||
|
||||
if (const auto rawPress = readRawPressure())
|
||||
up = *rawPress;
|
||||
else
|
||||
{ DBGPRNT("fail"); return std::nullopt; }
|
||||
|
||||
return TemperatureAndPressure {
|
||||
.temperature = getTemperature(ut),
|
||||
.pressure = getPressure(ut, up)
|
||||
};
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
@@ -330,12 +406,7 @@ void Adafruit_BMP085_Unified::getPressure(float *pressure) {
|
||||
@brief Reads the temperatures in degrees Celsius
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void Adafruit_BMP085_Unified::getTemperature(float *temp) {
|
||||
int32_t UT, B5; // following ds convention
|
||||
float t;
|
||||
|
||||
readRawTemperature(&UT);
|
||||
|
||||
std::optional<float> Adafruit_BMP085_Unified::getTemperature() {
|
||||
#if BMP085_USE_DATASHEET_VALS
|
||||
// use datasheet numbers!
|
||||
UT = 27898;
|
||||
@@ -343,13 +414,31 @@ void Adafruit_BMP085_Unified::getTemperature(float *temp) {
|
||||
_bmp085_coeffs.ac5 = 32757;
|
||||
_bmp085_coeffs.mc = -8711;
|
||||
_bmp085_coeffs.md = 2868;
|
||||
#else
|
||||
int32_t UT;
|
||||
if (const auto rawTemp = readRawTemperature())
|
||||
UT = *rawTemp;
|
||||
else
|
||||
{ DBGPRNT("fail"); return std::nullopt; }
|
||||
#endif
|
||||
|
||||
return getTemperature(UT);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Reads the temperatures in degrees Celsius
|
||||
*/
|
||||
/**************************************************************************/
|
||||
float Adafruit_BMP085_Unified::getTemperature(int32_t UT) {
|
||||
int32_t B5; // following ds convention
|
||||
float t;
|
||||
|
||||
B5 = computeB5(UT);
|
||||
t = (B5 + 8) >> 4;
|
||||
t /= 10;
|
||||
|
||||
*temp = t;
|
||||
return t;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
@@ -466,18 +555,17 @@ sensor_t Adafruit_BMP085_Unified::getSensor() {
|
||||
*/
|
||||
/**************************************************************************/
|
||||
std::optional<sensors_event_t> Adafruit_BMP085_Unified::getEvent() {
|
||||
const auto pressure = getPressure();
|
||||
if (!pressure)
|
||||
return std::nullopt;
|
||||
|
||||
sensors_event_t event;
|
||||
|
||||
event.version = sizeof(sensors_event_t);
|
||||
event.sensor_id = _sensorID;
|
||||
event.type = SENSOR_TYPE_PRESSURE;
|
||||
event.timestamp = espchrono::millis_clock::now();
|
||||
|
||||
{
|
||||
float pressure_kPa;
|
||||
getPressure(&pressure_kPa);
|
||||
event.pressure = pressure_kPa / 100.0F;
|
||||
}
|
||||
event.pressure = *pressure;
|
||||
|
||||
return event;
|
||||
}
|
||||
|
@@ -99,13 +99,23 @@ public:
|
||||
* @param temp Temperature
|
||||
* @return Returns the temperature
|
||||
*/
|
||||
void getTemperature(float *temp);
|
||||
std::optional<float> getTemperature();
|
||||
|
||||
float getTemperature(int32_t UT);
|
||||
|
||||
/*!
|
||||
* @brief Gets the pressure over I2C from the BMP085
|
||||
* @param pressure Pressure
|
||||
* @return Returns the pressure
|
||||
*/
|
||||
void getPressure(float *pressure);
|
||||
std::optional<float> getPressure();
|
||||
|
||||
float getPressure(int32_t ut, int32_t up);
|
||||
|
||||
struct TemperatureAndPressure { float temperature, pressure; };
|
||||
|
||||
std::optional<TemperatureAndPressure> getTemperatureAndPressure();
|
||||
|
||||
/*!
|
||||
* @brief Calculates absolute pressure
|
||||
* @param seaLevel Pressure at sea level
|
||||
|
Reference in New Issue
Block a user