small changes and many new sensors
This commit is contained in:
@@ -4,15 +4,29 @@
|
||||
#include "../../Platforms.h"
|
||||
#include "../../Debug.h"
|
||||
|
||||
// https://www.mouser.com/datasheet/2/783/BST-BME280-DS002-1509607.pdf
|
||||
|
||||
template <typename I2C> class BME280 {
|
||||
|
||||
I2C& i2c;
|
||||
|
||||
static constexpr const char* NAME = "BME280";
|
||||
|
||||
static constexpr uint8_t ADDR7 = 0b1110110;
|
||||
static constexpr uint8_t ADDR7_1 = 0b1110110; // 0x76
|
||||
static constexpr uint8_t ADDR7_2 = 0b1110111; // 0x77
|
||||
|
||||
static constexpr uint8_t MODE_SLEEP = 0b00;
|
||||
static constexpr uint8_t MODE_FORCED = 0b01; // manual sampling
|
||||
static constexpr uint8_t MODE_NORMAL = 0b11; // periodic background sampling
|
||||
|
||||
|
||||
|
||||
uint8_t ADDR7;
|
||||
|
||||
static constexpr uint8_t REG_CTRL1 = 0xF2; // humidity
|
||||
static constexpr uint8_t REG_CTRL2 = 0xF4; // temp, pressure, mode
|
||||
|
||||
static constexpr uint8_t REG_CONFIG = 0xF5;
|
||||
|
||||
static constexpr uint8_t REG_STATUS = 0xF3;
|
||||
static constexpr uint8_t REG_PRESSURE = 0xF7;
|
||||
static constexpr uint8_t REG_TEMPERATURE= 0xFA;
|
||||
@@ -22,9 +36,6 @@ template <typename I2C> class BME280 {
|
||||
static constexpr uint8_t REG_DIG_T2 = 0x8A;
|
||||
static constexpr uint8_t REG_DIG_T3 = 0x8C;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
bool started = false;
|
||||
|
||||
/** internal sensor calibration values */
|
||||
@@ -52,24 +63,141 @@ public:
|
||||
int8_t dig_H6 = 0;
|
||||
|
||||
} cal;
|
||||
|
||||
public:
|
||||
|
||||
struct Result {
|
||||
float temp;
|
||||
float humi;
|
||||
float pres;
|
||||
};
|
||||
|
||||
enum class Interval : uint8_t {
|
||||
INT_500_US = 0b000,
|
||||
INT_62_MS = 0b001,
|
||||
INT_125_MS = 0b010,
|
||||
INT_250_MS = 0b011,
|
||||
INT_500_MS = 0b100,
|
||||
INT_1000_MS = 0b101,
|
||||
INT_10_MS = 0b110,
|
||||
INT_20_MS = 0b111,
|
||||
};
|
||||
|
||||
enum class Oversample : uint8_t {
|
||||
X1 = 0b001,
|
||||
X2 = 0b010,
|
||||
X4 = 0b011,
|
||||
X8 = 0b100,
|
||||
X16 = 0b101,
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
struct Config {
|
||||
|
||||
Oversample temp = Oversample::X2;
|
||||
Oversample pres = Oversample::X16;
|
||||
Oversample humi = Oversample::X2;
|
||||
|
||||
uint8_t mode = MODE_NORMAL;
|
||||
Interval interval = Interval::INT_500_MS;
|
||||
uint8_t fir = 0b000; // fir filter disabled
|
||||
|
||||
} cfg;
|
||||
|
||||
public:
|
||||
|
||||
I2C& i2c;
|
||||
|
||||
BME280(I2C& i2c) : i2c(i2c) {
|
||||
BME280(I2C& i2c, uint8_t addrOffset = 0) : i2c(i2c), ADDR7(ADDR7_1 + addrOffset) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool isPresent() {
|
||||
return i2c.query(ADDR7);
|
||||
}
|
||||
|
||||
void init() {
|
||||
readCalib();
|
||||
}
|
||||
|
||||
void setSampling(Oversample temp, Oversample pres, Oversample humi) {
|
||||
cfg.temp = temp;
|
||||
cfg.pres = pres;
|
||||
cfg.humi = humi;
|
||||
}
|
||||
|
||||
uint8_t getStatus() {
|
||||
uint8_t res[1];
|
||||
i2c.readReg(ADDR7, REG_STATUS, 1, res);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** start periodic background measurement (tends to sensor-self-heating??) */
|
||||
void measurePeriodic(Interval ival) {
|
||||
cfg.mode = MODE_NORMAL;
|
||||
cfg.interval = ival;
|
||||
commitConfig();
|
||||
}
|
||||
|
||||
/** measure only once, takes some time before NEW results are present (seems more stable in terms of temperature) */
|
||||
void measureOnce() {
|
||||
cfg.mode = MODE_FORCED;
|
||||
commitConfig();
|
||||
}
|
||||
|
||||
/** get the most recent readings */
|
||||
Result getAll() {
|
||||
Result res;
|
||||
res.temp = getTemperature();
|
||||
res.humi = getHumidity();
|
||||
res.pres = getPressure();
|
||||
return res;
|
||||
}
|
||||
|
||||
/** get most recent pressure reading (hPa) */
|
||||
float getPressure() {
|
||||
uint8_t res[3];
|
||||
i2c.readReg(ADDR7, REG_PRESSURE, 3, res);
|
||||
//os_printf("res: %d - %d - %d \n", res[0], res[1], res[2]);
|
||||
const uint32_t tmp = ((res[0] << 16) | (res[1] << 8) | (res[2] << 0)) >> 4;
|
||||
const uint32_t pres = BME280_compensate_P_int64(tmp);
|
||||
const float presF = pres / 256.0f / 100.0f; // convert from Q24.8 to float and from Pa to hPa
|
||||
//const uint32_t p0 = pres / 256;
|
||||
//const uint32_t p1 = (uint32_t) presF;
|
||||
//const uint32_t p2 = (presF - p1) * 100000;
|
||||
//Log::addInfo((NAME, "[pres] ADC: %d -> %d Pa | %d.%d hPa", tmp, p0, p1,p2);
|
||||
return presF;
|
||||
}
|
||||
|
||||
/** get most recent temperature reading */
|
||||
float getTemperature() {
|
||||
uint8_t res[3];
|
||||
i2c.readReg(ADDR7, REG_TEMPERATURE, 3, res);
|
||||
const uint32_t tmp = ((res[0] << 16) | (res[1] << 8) | (res[2] << 0)) >> 4;
|
||||
const int32_t temp = BME280_compensate_T_int32(tmp);
|
||||
const float tempF = temp / 100.0f;
|
||||
return tempF;
|
||||
}
|
||||
|
||||
/** get the most recent humidity reading */
|
||||
float getHumidity() {
|
||||
uint8_t res[2];
|
||||
i2c.readReg(ADDR7, REG_HUMIDITY, 2, res);
|
||||
//os_printf("res: %d - %d \n", res[0], res[1]);
|
||||
const uint32_t tmp = (res[0] << 8) | (res[1] << 0);
|
||||
const int32_t humi = bme280_compensate_H_int32(tmp);
|
||||
const float humiF = humi / 1024.0f;
|
||||
//const uint16_t h0 = humi / 1024;
|
||||
//const uint16_t h1 = (uint16_t) humiF;
|
||||
//const uint16_t h2 = (humiF - humi) * 10000;
|
||||
//Log::addInfo((NAME, "[humi] ADC: %d -> %d -> %d.%d %%", tmp, h0, h1,h2);
|
||||
return humiF;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void readCalib() {
|
||||
|
||||
debugMod(NAME, "readCalib()");
|
||||
Log::addInfo(NAME, "readCalib()");
|
||||
|
||||
// read all 24 calibration bytes for temperature and pressure
|
||||
uint8_t b1[24];
|
||||
@@ -93,137 +221,33 @@ private:
|
||||
i2c.readReg(ADDR7, 0xA1, 1, &cal.dig_H1);
|
||||
i2c.readReg(ADDR7, 0xE1, 7, b1);
|
||||
cal.dig_H2 = (b1[1] << 8) | b1[0];
|
||||
cal.dig_H3 = b1[3];
|
||||
cal.dig_H4 = (b1[3] << 4) | (b1[4] & 0b000001111);
|
||||
cal.dig_H5 = (b1[5] << 4) | ((b1[4] & 0b111100000) >> 4);
|
||||
cal.dig_H3 = b1[2];
|
||||
cal.dig_H4 = (b1[3] << 4) | (b1[4] & 0b00001111);
|
||||
cal.dig_H5 = (b1[5] << 4) | ((b1[4] & 0b11110000) >> 4);
|
||||
cal.dig_H6 = (b1[6]);
|
||||
|
||||
//os_printf("calib temp: %d %d %d\n", cal.dig_T1, cal.dig_T2, cal.dig_T3);
|
||||
//os_printf("calib pres: %d %d %d %d %d %d %d %d %d\n", cal.dig_P1, cal.dig_P2, cal.dig_P3, cal.dig_P4, cal.dig_P5, cal.dig_P6, cal.dig_P7, cal.dig_P8, cal.dig_P9);
|
||||
//os_printf("calib humi: %d %d %d %d %d %d\n", cal.dig_H1, cal.dig_H2, cal.dig_H3, cal.dig_H4, cal.dig_H5, cal.dig_H6);
|
||||
//debugMod3(NAME, "calTemp: %d %d %d", cal.dig_T1, cal.dig_T2, cal.dig_T3);
|
||||
//debugMod9(NAME, "calPres: %d %d %d %d %d %d %d %d %d", cal.dig_P1, cal.dig_P2, cal.dig_P3, cal.dig_P4, cal.dig_P5, cal.dig_P6, cal.dig_P7, cal.dig_P8, cal.dig_P9);
|
||||
//debugMod6(NAME, "calHumi: %d %d %d %d %d %d", cal.dig_H1, cal.dig_H2, cal.dig_H3, cal.dig_H4, cal.dig_H5, cal.dig_H6);
|
||||
Log::addInfo(NAME, "calTemp: %d %d %d", cal.dig_T1, cal.dig_T2, cal.dig_T3);
|
||||
Log::addInfo(NAME, "calPres: %d %d %d %d %d %d %d %d %d", cal.dig_P1, cal.dig_P2, cal.dig_P3, cal.dig_P4, cal.dig_P5, cal.dig_P6, cal.dig_P7, cal.dig_P8, cal.dig_P9);
|
||||
Log::addInfo(NAME, "calHumi: %d %d %d %d %d %d", cal.dig_H1, cal.dig_H2, cal.dig_H3, cal.dig_H4, cal.dig_H5, cal.dig_H6);
|
||||
|
||||
}
|
||||
|
||||
void start() {
|
||||
debugMod(NAME, "start()");
|
||||
const uint8_t cfgHumi = 0b101; // 16x oversampling
|
||||
const uint8_t cfgPres = 0b101; // 16x oversampling
|
||||
const uint8_t cfgTemp = 0b101; // 16x oversampling
|
||||
const uint8_t cfgMode = 0b11;
|
||||
const uint8_t cfg1 = (cfgHumi << 1);
|
||||
const uint8_t cfg2 = (cfgTemp << 5) | (cfgPres << 2) | (cfgMode << 0);
|
||||
i2c.writeReg(ADDR7, REG_CTRL1, 1, &cfg1);
|
||||
i2c.writeReg(ADDR7, REG_CTRL2, 1, &cfg2);
|
||||
|
||||
void commitConfig() {
|
||||
|
||||
const uint8_t ctrl1 = (uint8_t(cfg.humi) << 0);
|
||||
const uint8_t ctrl2 = (uint8_t(cfg.temp) << 5) | (uint8_t(cfg.pres) << 2) | (uint8_t(cfg.mode) << 0);
|
||||
const uint8_t conf = (uint8_t(cfg.interval) << 5) | (cfg.fir << 2);
|
||||
|
||||
i2c.writeReg8(ADDR7, REG_CTRL1, MODE_SLEEP);
|
||||
i2c.writeReg8(ADDR7, REG_CTRL1, ctrl1);
|
||||
i2c.writeReg8(ADDR7, REG_CTRL2, ctrl2);
|
||||
i2c.writeReg8(ADDR7, REG_CONFIG, conf);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public:
|
||||
|
||||
void startOnce() {
|
||||
if (started) {return;}
|
||||
debugMod(NAME, "startOnce()");
|
||||
readCalib();
|
||||
start();
|
||||
started = true;
|
||||
}
|
||||
|
||||
uint8_t getStatus() {
|
||||
uint8_t res[1];
|
||||
i2c.readReg(ADDR7, REG_STATUS, 1, res);
|
||||
//os_printf("Status: %d \n", res[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** get current pressure in hPa */
|
||||
float getPressure() {
|
||||
uint8_t res[3];
|
||||
i2c.readReg(ADDR7, REG_PRESSURE, 3, res);
|
||||
//os_printf("res: %d - %d - %d \n", res[0], res[1], res[2]);
|
||||
const uint32_t tmp = ((res[0] << 16) | (res[1] << 8) | (res[2] << 0)) >> 4;
|
||||
const uint32_t pres = BME280_compensate_P_int64(tmp);
|
||||
const float presF = pres / 256.0f / 100.0f; // convert from Q24.8 to float and from Pa to hPa
|
||||
//const uint32_t p0 = pres / 256;
|
||||
//const uint32_t p1 = (uint32_t) presF;
|
||||
//const uint32_t p2 = (presF - p1) * 100000;
|
||||
//debugMod4(NAME, "[pres] ADC: %d -> %d Pa | %d.%d hPa", tmp, p0, p1,p2);
|
||||
return presF;
|
||||
}
|
||||
|
||||
float getTemperature() {
|
||||
uint8_t res[3];
|
||||
i2c.readReg(ADDR7, REG_TEMPERATURE, 3, res);
|
||||
//os_printf("res: %d - %d - %d \n", res[0], res[1], res[2]);
|
||||
const uint32_t tmp = ((res[0] << 16) | (res[1] << 8) | (res[2] << 0)) >> 4;
|
||||
const int32_t temp = BME280_compensate_T_int32(tmp);
|
||||
const float tempF = temp / 100.0f;
|
||||
//debugMod2(NAME, "[temp] ADC: %d -> %d", tmp, temp);
|
||||
return tempF;
|
||||
}
|
||||
|
||||
float getHumidity() {
|
||||
uint8_t res[2];
|
||||
i2c.readReg(ADDR7, REG_HUMIDITY, 2, res);
|
||||
//os_printf("res: %d - %d \n", res[0], res[1]);
|
||||
const uint32_t tmp = (res[0] << 8) | (res[1] << 0);
|
||||
const int32_t humi = bme280_compensate_H_int32(tmp);
|
||||
const float humiF = humi / 1024.0f;
|
||||
//const uint16_t h0 = humi / 1024;
|
||||
//const uint16_t h1 = (uint16_t) humiF;
|
||||
//const uint16_t h2 = (humiF - humi) * 10000;
|
||||
//debugMod4(NAME, "[humi] ADC: %d -> %d -> %d.%d %%", tmp, h0, h1,h2);
|
||||
return humiF;
|
||||
}
|
||||
|
||||
/*
|
||||
bool readRegister(const uint8_t addr, uint8_t* dst, const uint8_t len) {
|
||||
|
||||
bool ok;
|
||||
|
||||
// address the slave in write mode and select the first register to read
|
||||
ok = i2c.startWrite(ADDR7);
|
||||
if (!ok) {printf("failed start write\n"); return false;}
|
||||
ok = i2c.writeByteAndCheck(addr);
|
||||
if (!ok) {printf("failed to select register %d\n", addr); return false;}
|
||||
|
||||
//i2c::stop();
|
||||
|
||||
// address the slave in read mode and read [len] registers
|
||||
ok = i2c.startRead(ADDR7);
|
||||
if (!ok) {printf("failed start read\n"); return 0;}
|
||||
i2c.readBytes(dst, len);
|
||||
|
||||
// done
|
||||
i2c.stop();
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool writeRegister(const uint8_t addr, const uint8_t* src, const uint8_t len) {
|
||||
|
||||
bool ok;
|
||||
|
||||
// address the slave in write mode and select the first register to read
|
||||
ok = i2c.startWrite(ADDR7);
|
||||
if (!ok) {printf("failed start write\n"); return false;}
|
||||
ok = i2c.writeByteAndCheck(addr);
|
||||
if (!ok) {printf("failed to select register %d\n", addr); return false;}
|
||||
ok = i2c.writeBytesAndCheck(src, len);
|
||||
if (!ok) {printf("failed to write register contents \n"); return false;}
|
||||
|
||||
// done
|
||||
i2c.stop();
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
private:
|
||||
|
||||
/** conversions from ADC values to real-world values. from Bosch BMP280 manual! */
|
||||
|
||||
using BME280_S32_t = int32_t;
|
||||
@@ -251,7 +275,7 @@ private:
|
||||
var2 = var2 + ((var1*(BME280_S64_t)cal.dig_P5)<<17);
|
||||
var2 = var2 + (((BME280_S64_t)cal.dig_P4)<<35);
|
||||
var1 = ((var1 * var1 * (BME280_S64_t)cal.dig_P3)>>8) + ((var1 * (BME280_S64_t)cal.dig_P2)<<12);
|
||||
var1 = (((((BME280_S64_t)1)<<47)+var1))*((BME280_S64_t)cal.dig_P1)>>33;
|
||||
var1 = (((((BME280_S64_t)1l)<<47)+var1))*((BME280_S64_t)cal.dig_P1)>>33;
|
||||
if (var1 == 0) {return 0;} // avoid exception caused by division by zero
|
||||
p = 1048576-adc_P;
|
||||
p = (((p<<31)-var2)*3125)/var1;
|
||||
|
||||
Reference in New Issue
Block a user