7typedef TinyWire TwoWire;
13#include "helper/mup_i2c_registers.h"
113 String BMP180_VERSION =
"0.1.0";
119 double temperatureValue, pressureValue, pressureNNValue;
120 unsigned long stateMachineClock;
121 int32_t rawTemperature;
122 double calibratedTemperature;
124 double calibratedPressure;
125 double baseRelativeNNPressure;
126 bool relativeAltitudeStarted;
127 bool captureRelative =
false;
128 unsigned long basePollRateUs = 500000L;
133 int16_t CD_AC1, CD_AC2, CD_AC3, CD_B1, CD_B2, CD_MB, CD_MC, CD_MD;
134 uint16_t CD_AC4, CD_AC5, CD_AC6;
137 enum BMPSensorState { UNAVAILABLE,
141 WAIT_NEXT_MEASUREMENT };
150 BMPSensorState sensorState;
151 unsigned long errs = 0;
152 unsigned long oks = 0;
153 uint16_t oversampleMode = 2;
154 enum FilterMode { FAST,
157#define MUP_BMP_INVALID_ALTITUDE -1000000.0
158 double referenceAltitudeMeters;
159 FilterMode filterMode;
161 ustd::sensorprocessor temperatureSensor = ustd::sensorprocessor(4, 600, 0.005);
162 ustd::sensorprocessor pressureSensor = ustd::sensorprocessor(4, 600, 0.005);
163 bool bActive =
false;
165 PressTempBMP180(String name, FilterMode filterMode = FilterMode::MEDIUM, uint8_t i2cAddress = 0x77)
166 : name(name), filterMode(filterMode), i2cAddress(i2cAddress) {
172 sensorState = BMPSensorState::UNAVAILABLE;
173 referenceAltitudeMeters = MUP_BMP_INVALID_ALTITUDE;
174 relativeAltitudeStarted =
false;
175 captureRelative =
false;
178 setFilterMode(filterMode,
true);
191 referenceAltitudeMeters = _referenceAltitudeMeters;
200 if (referenceAltitudeMeters != MUP_BMP_INVALID_ALTITUDE) {
201 captureRelative =
true;
209 return temperatureValue;
216 return pressureValue;
227 if (referenceAltitudeMeters != MUP_BMP_INVALID_ALTITUDE) {
228 double prNN = _pressure / pow((1.0 - (referenceAltitudeMeters / 44330.0)), 5.255);
235 oversampleMode = (uint16_t)_sampleMode;
238 bool initBmpSensorConstants() {
239 if (!pI2C->readRegisterWord(0xaa, (uint16_t *)&CD_AC1))
return false;
240 if (!pI2C->readRegisterWord(0xac, (uint16_t *)&CD_AC2))
return false;
241 if (!pI2C->readRegisterWord(0xae, (uint16_t *)&CD_AC3))
return false;
242 if (!pI2C->readRegisterWord(0xb0, (uint16_t *)&CD_AC4))
return false;
243 if (!pI2C->readRegisterWord(0xb2, (uint16_t *)&CD_AC5))
return false;
244 if (!pI2C->readRegisterWord(0xb4, (uint16_t *)&CD_AC6))
return false;
245 if (!pI2C->readRegisterWord(0xb6, (uint16_t *)&CD_B1))
return false;
246 if (!pI2C->readRegisterWord(0xb8, (uint16_t *)&CD_B2))
return false;
247 if (!pI2C->readRegisterWord(0xba, (uint16_t *)&CD_MB))
return false;
248 if (!pI2C->readRegisterWord(0xbc, (uint16_t *)&CD_MC))
return false;
249 if (!pI2C->readRegisterWord(0xbe, (uint16_t *)&CD_MD))
return false;
255 setSampleMode(_sampleMode);
257 pollRateMs = _pollRateMs;
260 auto ft = [=]() { this->loop(); };
261 tID = pSched->add(ft, name, basePollRateUs);
263 auto fnall = [=](String topic, String msg, String originator) {
264 this->subsMsg(topic, msg, originator);
266 pSched->subscribe(tID, name +
"/sensor/#", fnall);
268 pI2C =
new I2CRegisters(pWire, i2cAddress);
270 pI2C->lastError = pI2C->checkAddress(i2cAddress);
271 if (pI2C->lastError == I2CRegisters::I2CError::OK) {
272 if (!pI2C->readRegisterByte(0xd0, &data)) {
276 if (!initBmpSensorConstants()) {
277 pI2C->lastError = I2CRegisters::I2CError::I2C_HW_ERROR;
280 sensorState = BMPSensorState::IDLE;
285 pI2C->lastError = I2CRegisters::I2CError::I2C_WRONG_HARDWARE_AT_ADDRESS;
294 void setFilterMode(FilterMode mode,
bool silent =
false) {
298 temperatureSensor.update(1, 2, 0.05);
299 pressureSensor.update(1, 2, 0.1);
303 temperatureSensor.update(4, 30, 0.1);
304 pressureSensor.update(4, 30, 0.5);
308 filterMode = LONGTERM;
309 temperatureSensor.update(10, 600, 0.1);
310 pressureSensor.update(50, 600, 0.5);
318 void publishTemperature() {
320 sprintf(buf,
"%6.2f", temperatureValue);
321 pSched->publish(name +
"/sensor/temperature", buf);
324 void publishPressure() {
326 sprintf(buf,
"%7.2f", pressureValue);
327 pSched->publish(name +
"/sensor/pressure", buf);
328 if (referenceAltitudeMeters != MUP_BMP_INVALID_ALTITUDE) {
329 sprintf(buf,
"%7.2f", pressureNNValue);
330 pSched->publish(name +
"/sensor/pressureNN", buf);
334 void publishError(String errMsg) {
335 pSched->publish(name +
"/sensor/error", errMsg);
338 void publishFilterMode() {
339 switch (filterMode) {
340 case FilterMode::FAST:
341 pSched->publish(name +
"/sensor/mode",
"FAST");
343 case FilterMode::MEDIUM:
344 pSched->publish(name +
"/sensor/mode",
"MEDIUM");
346 case FilterMode::LONGTERM:
347 pSched->publish(name +
"/sensor/mode",
"LONGTERM");
352 void publishOversampling() {
355 pSched->publish(name +
"/sensor/oversampling",
"ULTRA_LOW_POWER");
358 pSched->publish(name +
"/sensor/oversampling",
"STANDARD");
361 pSched->publish(name +
"/sensor/oversampling",
"HIGH_RESOLUTION");
364 pSched->publish(name +
"/sensor/oversampling",
"ULTRA_HIGH_RESOLUTION");
367 pSched->publish(name +
"/sensor/oversampling",
"INVALID");
372 void publishCalibrationData() {
374 sprintf(msg,
"AC1=%d, AC2=%d, AC3=%d, AC4=%u, AC5=%u, AC6=%u, B1=%d, B2=%d, MB=%d, MC=%d, MD=%d", CD_AC1, CD_AC2, CD_AC3, CD_AC4, CD_AC5, CD_AC6, CD_B1, CD_B2, CD_MB, CD_MC, CD_MD);
375 pSched->publish(
"sensor/calibrationdata", msg);
378 void publishReferenceAltitude() {
379 if (referenceAltitudeMeters != MUP_BMP_INVALID_ALTITUDE) {
381 sprintf(buf,
"%7.2f", referenceAltitudeMeters);
382 pSched->publish(name +
"/sensor/referencealtitude", buf);
384 pSched->publish(name +
"/sensor/referencealtitude",
"unknown");
388 void publishRelativeAltitude() {
390 if (relativeAltitudeStarted) {
391 double ralt = 44330.0 * (1.0 - pow(pressureValue / baseRelativeNNPressure, 1. / 5.255));
392 sprintf(buf,
"%7.2f", ralt);
393 pSched->publish(name +
"/sensor/relativealtitude", buf);
394 double dalt = ralt - referenceAltitudeMeters;
395 sprintf(buf,
"%7.2f", dalt);
396 pSched->publish(name +
"/sensor/deltaaltitude", buf);
400 bool sensorStateMachine() {
401 bool newData =
false;
404 unsigned long convTimeOversampling[4] = {4500, 7500, 13500, 25500};
405 switch (sensorState) {
406 case BMPSensorState::UNAVAILABLE:
408 case BMPSensorState::IDLE:
409 if (!pI2C->writeRegisterByte(0xf4, 0x2e)) {
411 sensorState = BMPSensorState::WAIT_NEXT_MEASUREMENT;
412 stateMachineClock = micros();
415 sensorState = BMPSensorState::TEMPERATURE_WAIT;
416 stateMachineClock = micros();
419 case BMPSensorState::TEMPERATURE_WAIT:
420 if (timeDiff(stateMachineClock, micros()) > 4500) {
422 if (pI2C->readRegisterWord(0xf6, &rt)) {
424 uint8_t cmd = 0x34 | (oversampleMode << 6);
425 if (!pI2C->writeRegisterByte(0xf4, cmd)) {
427 sensorState = BMPSensorState::WAIT_NEXT_MEASUREMENT;
428 stateMachineClock = micros();
430 sensorState = BMPSensorState::PRESSURE_WAIT;
431 stateMachineClock = micros();
435 sensorState = BMPSensorState::WAIT_NEXT_MEASUREMENT;
436 stateMachineClock = micros();
440 case BMPSensorState::PRESSURE_WAIT:
441 if (timeDiff(stateMachineClock, micros()) > convTimeOversampling[oversampleMode]) {
443 if (pI2C->readRegisterTripple(0xf6, &rp)) {
444 rawPressure = rp >> (8 - oversampleMode);
447 sensorState = BMPSensorState::WAIT_NEXT_MEASUREMENT;
448 stateMachineClock = micros();
451 sensorState = BMPSensorState::WAIT_NEXT_MEASUREMENT;
452 stateMachineClock = micros();
456 case BMPSensorState::WAIT_NEXT_MEASUREMENT:
457 if (timeDiff(lastPollMs, millis()) > pollRateMs) {
458 sensorState = BMPSensorState::IDLE;
459 lastPollMs = millis();
466 bool calibrateRawData() {
468 int32_t x1 = (((uint32_t)rawTemperature - (uint32_t)CD_AC6) * (uint32_t)CD_AC5) >> 15;
469 int32_t x2 = ((int32_t)CD_MC << 11) / (x1 + (int32_t)CD_MD);
470 int32_t b5 = x1 + x2;
471 calibratedTemperature = ((double)b5 + 8.0) / 160.0;
473 int32_t b6 = b5 - (int32_t)4000;
474 x1 = ((int32_t)CD_B2 * ((b6 * b6) >> 12)) >> 11;
475 x2 = ((int32_t)CD_AC2 * b6) >> 11;
476 int32_t x3 = x1 + x2;
477 int32_t b3 = ((((int32_t)CD_AC1 * 4L + x3) << oversampleMode) + 2L) / 4;
483 x1 = ((int32_t)CD_AC3 * b6) >> 13;
484 x2 = ((int32_t)CD_B1 * ((b6 * b6) >> 12)) >> 16;
485 x3 = ((x1 + x2) + 2) >> 2;
486 uint32_t b4 = ((uint32_t)CD_AC4 * (uint32_t)(x3 + (uint32_t)32768)) >> 15;
487 uint32_t b7 = ((uint32_t)rawPressure - b3) * ((uint32_t)50000 >> oversampleMode);
493 if (b7 < (uint32_t)0x80000000) {
498 x1 = (p >> 8) * (p >> 8);
499 x1 = (x1 * (int32_t)3038) >> 16;
500 x2 = (((int32_t)-7357) * p) >> 16;
502 int32_t cp = p + ((x1 + x2 + (int32_t)3791) >> 4);
507 calibratedPressure = cp / 100.0;
512 double tempVal, pressVal;
514 if (!sensorStateMachine())
return;
516 tempVal = (double)calibratedTemperature;
517 pressVal = (double)calibratedPressure;
518 if (temperatureSensor.filter(&tempVal)) {
519 temperatureValue = tempVal;
520 publishTemperature();
522 if (pressureSensor.filter(&pressVal)) {
523 pressureValue = pressVal;
524 if (referenceAltitudeMeters != MUP_BMP_INVALID_ALTITUDE) {
526 if (captureRelative) {
527 baseRelativeNNPressure = pressureNNValue;
528 relativeAltitudeStarted =
true;
529 captureRelative =
false;
533 if (relativeAltitudeStarted) publishRelativeAltitude();
538 void subsMsg(String topic, String msg, String originator) {
539 if (topic == name +
"/sensor/temperature/get") {
540 publishTemperature();
541 }
else if (topic == name +
"/sensor/pressure/get") {
543 }
else if (topic == name +
"/sensor/mode/get") {
545 }
else if (topic == name +
"/sensor/calibrationdata/get") {
546 publishCalibrationData();
547 }
else if (topic == name +
"/sensor/referencealtitude/get") {
548 publishReferenceAltitude();
549 }
else if (topic == name +
"/sensor/relativealtitude/get") {
550 publishRelativeAltitude();
551 }
else if (topic == name +
"/sensor/relativealtitude/set") {
553 }
else if (topic == name +
"/sensor/oversampling/get") {
554 publishOversampling();
555 }
else if (topic == name +
"/sensor/referencealtitude/set") {
556 double alt = atof(msg.c_str());
558 }
else if (topic == name +
"/sensor/mode/set") {
559 if (msg ==
"fast" || msg ==
"FAST") {
560 setFilterMode(FilterMode::FAST);
562 if (msg ==
"medium" || msg ==
"MEDIUM") {
563 setFilterMode(FilterMode::MEDIUM);
565 setFilterMode(FilterMode::LONGTERM);
568 }
else if (topic == name +
"/sensor/oversampling/set") {
569 if (msg ==
"ULTRA_LOW_POWER") {
572 if (msg ==
"STANDARD") {
575 if (msg ==
"HIGH_RESOLUTION") {
mupplet-sensor temperature and pressure with Bosch BMP180
Definition: mup_presstemp_bmp180.h:111
double getTemperature()
Definition: mup_presstemp_bmp180.h:205
PressTempBMP180(String name, FilterMode filterMode=FilterMode::MEDIUM, uint8_t i2cAddress=0x77)
Definition: mup_presstemp_bmp180.h:165
double getPressure()
Definition: mup_presstemp_bmp180.h:212
void startRelativeAltitude()
Definition: mup_presstemp_bmp180.h:194
BMPSampleMode
Definition: mup_presstemp_bmp180.h:144
@ ULTRA_LOW_POWER
1 samples, 4.5ms conversion time, 3uA current at 1 sample/sec, 0.06 RMS noise typ....
Definition: mup_presstemp_bmp180.h:145
@ STANDARD
2 samples, 7.5ms conversion time, 5uA current at 1 sample/sec, 0.05 RMS noise typ....
Definition: mup_presstemp_bmp180.h:146
@ ULTRA_HIGH_RESOLUTION
8 samples, 25.5ms conversion time, 12uA current at 1 sample/sec, 0.03 RMS noise typ....
Definition: mup_presstemp_bmp180.h:148
@ HIGH_RESOLUTION
4 samples, 13.5ms conversion time, 7uA current at 1 sample/sec, 0.04 RMS noise typ....
Definition: mup_presstemp_bmp180.h:147
void setReferenceAltitude(double _referenceAltitudeMeters)
Definition: mup_presstemp_bmp180.h:187
double getPressureNN(double _pressure)
Definition: mup_presstemp_bmp180.h:219