diff --git a/environments.ini b/environments.ini
index a849a34397..bc545ba0c8 100644
--- a/environments.ini
+++ b/environments.ini
@@ -5,6 +5,51 @@
;List of environments that can be build ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+[env:tinypico-bmp390-usb]
+platform = espressif32
+board = tinypico
+framework = arduino
+
+monitor_speed = 115200
+;upload_speed = 921600
+
+;board_build.partitions = huge_app.csv
+board_build.partitions = partitions/min_spiffs.csv
+
+build_flags =
+ -DGateway_Name=\"OMG_TinyPICO_BMP390\"
+ -DZsensorBMP390=\"BMP390\"
+ -DDEFAULT_I2C_SDA=21
+ -DDEFAULT_I2C_SCL=22
+ -DLOG_LEVEL=LOG_LEVEL_NOTICE
+ -DENV_NAME=\"tinypico-bmp390-usb\"
+ -DZwebUI=\"WebUI\"
+ -DZwebServer=true
+ -DZmqttDiscovery=\"HADiscovery\"
+ -DvalueAsATopic=true
+ -UZgatewayBT
+ -UZgatewayBLE
+ -UZgatewayBLEConnect
+ -UZgatewayIR
+ -UZgatewayLORA
+ -UZgatewayRF
+ -UZgatewayRTL_433
+ -UZgatewayPilight
+ -UZgatewaySERIAL
+
+lib_deps =
+ ${env.lib_deps}
+ ${com-esp32.lib_deps}
+ ${libraries.ble}
+ ${libraries.decoder}
+ adafruit/Adafruit BMP3XX Library
+ adafruit/Adafruit Unified Sensor
+
+lib_ignore =
+ NimBLE-Arduino
+ TheengsDecoder
+
+
[env:rfbridge]
platform = ${com.esp8266_platform}
board = esp8285
@@ -232,6 +277,7 @@ build_flags =
'-DZsensorADC="ADC"'
'-DZsensorBH1750="BH1750"'
'-DZsensorBME280="BME280"'
+ '-DZsensorBMP390="BMP390"'
'-DBME280Correction=-3.4'
'-DZsensorHTU21="HTU21"'
'-DZsensorAHTx0="AHTx0"'
diff --git a/main/User_config.h b/main/User_config.h
index 31a8351004..1ee47b79df 100644
--- a/main/User_config.h
+++ b/main/User_config.h
@@ -356,6 +356,7 @@ extern ss_cnt_parameters cnt_parameters_array[];
//#define ZsensorTEMT6000 "TEMT6000" //ESP8266
//#define ZsensorTSL2561 "TSL2561" //ESP8266, Arduino, ESP32
//#define ZsensorBME280 "BME280" //ESP8266, Arduino, ESP32
+//#define ZsensorBMP390 "BMP390" //ESP8266, Arduino, ESP32
//#define ZsensorHTU21 "HTU21" //ESP8266, Arduino, ESP32
//#define ZsensorLM75 "LM75" //ESP8266, Arduino, ESP32
//#define ZsensorDHT "DHT" //ESP8266, Arduino, ESP32, Sonoff RF Bridge
diff --git a/main/config_BMP390.h b/main/config_BMP390.h
new file mode 100644
index 0000000000..1c37dca63a
--- /dev/null
+++ b/main/config_BMP390.h
@@ -0,0 +1,105 @@
+/*
+ Theengs OpenMQTTGateway - We Unite Sensors in One Open-Source Interface
+
+ Act as a gateway between your 433mhz, infrared IR, BLE, LoRa signal and one interface like an MQTT broker
+ Send and receiving command by MQTT
+
+ This files enables you to set parameters for the BMP390 sensor.
+
+ Copyright: (c) Hans-Juergen Dinges
+
+ This file is part of OpenMQTTGateway.
+
+ OpenMQTTGateway is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ OpenMQTTGateway is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+ Connection Schemata:
+ --------------------
+
+ BMP390 ------> ESP8266
+ ==============================
+ Vcc ----------------> 5V/3.3V (5V or 3.3V depends on the BMP390 board variant)
+ GND ----------------> GND
+ SCL ----------------> D1
+ SDA ----------------> D2
+
+*/
+#ifndef config_BMP390_h
+#define config_BMP390_h
+
+extern void setupZsensorBMP390();
+extern void MeasureTempAndPressureBMP390();
+
+#ifndef bmp390_always
+# define bmp390_always true // if false when the current value of the parameter is the same as previous one don't send it by MQTT
+#endif
+#ifndef TimeBetweenReadingbmp390
+# define TimeBetweenReadingbmp390 30000
+#endif
+
+/*----------------------------USER PARAMETERS-----------------------------*/
+/*-------------DEFINE YOUR MQTT PARAMETERS BELOW----------------*/
+#ifndef BMP390TOPIC
+# define BMP390TOPIC "/CLIMAtoMQTT/bmp390"
+#endif
+
+// I2C address options for BMP390 boards (commonly 0x76 or 0x77)
+#ifndef BMP390_I2C_ADDR1
+# define BMP390_I2C_ADDR1 0x77
+#endif
+#ifndef BMP390_I2C_ADDR2
+# define BMP390_I2C_ADDR2 0x76
+#endif
+
+// Only supported for ESP
+#ifndef BMP390_PIN_SDA
+# define BMP390_PIN_SDA SDA
+#endif
+#ifndef BMP390_PIN_SCL
+# define BMP390_PIN_SCL SCL
+#endif
+
+// Oversampling for BMP390 devices
+
+#ifndef BMP390TemperatureOversample
+// BMP390TemperatureOversample - Values:
+// ------------------------
+// 0, skipped
+// 1 through 5, oversampling *2, *4, *8, *16, *32 respectively (BMP3XX does not expose 1x)
+# define BMP390TemperatureOversample 1
+#endif
+
+#ifndef BMP390PressureOversample
+// BMP390PressureOversample - Values:
+// -------------------------
+// 0, skipped
+// 1 through 5, oversampling *2, *4, *8, *16, *32 respectively (BMP3XX does not expose 1x)
+# define BMP390PressureOversample 1
+#endif
+
+// Temperature correction for BMP390 devices
+
+#ifndef BMP390Correction
+// BMP390Correction - Correction in Celsius of temperature reported by BMP390 sensor. Both Celsius and Fahrenheit temperatures are adjusted.
+// -------------------------
+// Value is a float
+// ie Compiler Directive '-DBMP390Correction=-3.4'
+# define BMP390Correction 0
+#endif
+
+// Sea-level pressure reference in hPa (used to compute altitude)
+#ifndef BMP390_SEALEVEL_HPA
+# define BMP390_SEALEVEL_HPA 1013.25f
+#endif
+
+#endif
diff --git a/main/main.cpp b/main/main.cpp
index 7452920d80..38c6f8911c 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -164,6 +164,9 @@ Preferences preferences;
#ifdef ZsensorBME280
# include "config_BME280.h"
#endif
+#ifdef ZsensorBMP390
+# include "config_BMP390.h"
+#endif
#ifdef ZsensorHTU21
# include "config_HTU21.h"
#endif
@@ -1484,6 +1487,10 @@ void setup() {
setupZsensorBME280();
modules.add(ZsensorBME280);
#endif
+#ifdef ZsensorBMP390
+ setupZsensorBMP390();
+ modules.add(ZsensorBMP390);
+#endif
#ifdef ZsensorHTU21
setupZsensorHTU21();
modules.add(ZsensorHTU21);
@@ -2623,6 +2630,9 @@ void loop() {
#ifdef ZsensorBME280
MeasureTempHumAndPressure(); //Addon to measure Temperature, Humidity, Pressure and Altitude with a Bosch BME280/BMP280
#endif
+#ifdef ZsensorBMP390
+ MeasureTempAndPressureBMP390(); //Addon to measure Temperature and Pressure with a Bosch BMP390
+#endif
#ifdef ZsensorHTU21
MeasureTempHum(); //Addon to measure Temperature, Humidity, of a HTU21 sensor
#endif
diff --git a/main/mqttDiscovery.cpp b/main/mqttDiscovery.cpp
index 6a249e9db7..ad1222ea43 100644
--- a/main/mqttDiscovery.cpp
+++ b/main/mqttDiscovery.cpp
@@ -820,6 +820,19 @@ void pubMqttDiscovery() {
true, BMETOPIC, will_Topic, nullptr);
# endif
+# ifdef ZsensorBMP390
+# include "config_BMP390.h"
+ const char* BMP390sensor[][13] = {
+ {HASS_TYPE_SENSOR, "BMP390: Temp", "bmp390-temp", HASS_CLASS_TEMPERATURE, jsonTempc, "", "", HASS_UNIT_CELSIUS, stateClassMeasurement, nullptr, nullptr, nullptr, nullptr},
+ {HASS_TYPE_SENSOR, "BMP390: Pressure", "bmp390-pressure", HASS_CLASS_PRESSURE, jsonPa, "", "", HASS_UNIT_HPA, stateClassMeasurement, nullptr, nullptr, nullptr, nullptr},
+ {HASS_TYPE_SENSOR, "BMP390: Altitude", "bmp390-altim", "", jsonAltim, "", "", HASS_UNIT_METER, stateClassMeasurement, nullptr, nullptr, nullptr, nullptr},
+ {HASS_TYPE_SENSOR, "BMP390: Altitude (ft)", "bmp390-altift", "", jsonAltif, "", "", HASS_UNIT_FT, stateClassMeasurement, nullptr, nullptr, nullptr, nullptr}};
+
+ THEENGS_LOG_TRACE(F("bmp390Discovery" CR));
+ createDiscoveryFromList(nullptr, BMP390sensor, 4, nullptr, nullptr, nullptr,
+ true, BMP390TOPIC, will_Topic, nullptr);
+# endif
+
# ifdef ZsensorHTU21
# include "config_HTU21.h"
const char* HTUsensor[][13] = {
@@ -1152,4 +1165,4 @@ void pubMqttDiscovery() {
}
#else
void pubMqttDiscovery() {}
-#endif
\ No newline at end of file
+#endif
diff --git a/main/sensorBMP390.cpp b/main/sensorBMP390.cpp
new file mode 100644
index 0000000000..a3da3564be
--- /dev/null
+++ b/main/sensorBMP390.cpp
@@ -0,0 +1,203 @@
+/*
+ OpenMQTTGateway Addon - ESP8266 or Arduino program for home automation
+
+ Act as a gateway between your 433mhz, infrared IR, BLE, LoRa signal and one interface like an MQTT broker
+ Send and receiving command by MQTT
+
+ This is the Climate Addon:
+ - Measures Temperature and Pressure
+ - Generates Values for: Temperature in degrees C and F, Pressure in Pa, Altitude in Meter and Feet
+ - Required Hardware Module: Bosch BMP390
+ - Required Library: Adafruit BMP3XX
+
+ Connection Schemata:
+ --------------------
+
+ BMP390 ------> ESP8266
+ =====================================================
+ Vcc ----------------> 5V/3.3V (5V or 3.3V depends on the BMP390 board variant)
+ GND ----------------> GND
+ SCL ----------------> D1
+ SDA ----------------> D2
+
+ Copyright: (c) Hans-Juergen Dinges
+
+ This file is part of OpenMQTTGateway.
+
+ OpenMQTTGateway is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ OpenMQTTGateway is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+#include "User_config.h"
+
+#ifdef ZsensorBMP390
+# include
+
+# include "Adafruit_BMP3XX.h"
+# include "TheengsCommon.h"
+# include "Wire.h" // Library for communication with I2C / TWI devices
+# include "config_BMP390.h"
+
+//Time used to wait for an interval before resending measured values
+static unsigned long timebmp390 = 0;
+static uint8_t BMP390_i2c_addr = BMP390_I2C_ADDR1; // Default I2C address for BMP390 is 0x77, alternate is 0x76
+static Adafruit_BMP3XX bmp;
+
+static inline uint8_t mapOversample(int v) {
+ // Values:
+ // -------------------------
+ // 0, skipped
+ // 1 through 5, oversampling *2, *4, *8, *16, *32 respectively (BMP3XX does not expose 1x)
+ switch (v) {
+ case 0: return BMP3_NO_OVERSAMPLING;
+ case 1: return BMP3_OVERSAMPLING_2X;
+ case 2: return BMP3_OVERSAMPLING_4X;
+ case 3: return BMP3_OVERSAMPLING_8X;
+ case 4: return BMP3_OVERSAMPLING_16X;
+ case 5: return BMP3_OVERSAMPLING_32X;
+ default: return BMP3_OVERSAMPLING_4X;
+ }
+}
+
+void setupZsensorBMP390() {
+ // Allow custom pins on ESP Platforms
+ Wire.begin(BMP390_PIN_SDA, BMP390_PIN_SCL);
+
+ THEENGS_LOG_NOTICE(F("Setup BMP390 on address: %X" CR), BMP390_i2c_addr);
+
+ delay(10); // Gives the Sensor enough time to turn on (The BMP390 requires 2ms to start up)
+
+ bool ok = bmp.begin_I2C(BMP390_I2C_ADDR1);
+ if (ok) {
+ BMP390_i2c_addr = BMP390_I2C_ADDR1;
+ } else {
+ ok = bmp.begin_I2C(BMP390_I2C_ADDR2);
+ if (ok) {
+ BMP390_i2c_addr = BMP390_I2C_ADDR2;
+ }
+ }
+
+ if (!ok) {
+ THEENGS_LOG_NOTICE(F("Bosch BMP390 failed (not found at 0x76/0x77)" CR));
+ return;
+ }
+
+ //***Operation settings*****************************//
+
+ // tempOverSample - Values:
+ // ------------------------
+ // 0, skipped
+ // 1 through 5, oversampling *1, *2, *4, *8, *16 respectively
+ bmp.setTemperatureOversampling(mapOversample(BMP390TemperatureOversample));
+
+ // pressOverSample - Values:
+ // -------------------------
+ // 0, skipped
+ // 1 through 5, oversampling *1, *2, *4, *8, *16 respectively
+ bmp.setPressureOversampling(mapOversample(BMP390PressureOversample));
+
+ // Filter can be off or number of FIR coefficients - Values:
+ // ---------------------------------------------------------
+ // 0, filter off
+ // 1, coefficients = 2
+ // 2, coefficients = 4
+ // 3, coefficients = 8
+ // 4, coefficients = 16
+ bmp.setIIRFilterCoeff(BMP3_IIR_FILTER_COEFF_3);
+
+ // Output Data Rate - Values:
+ // --------------------------
+ // BMP3_ODR_xx_HZ (see Adafruit_BMP3XX.h)
+ bmp.setOutputDataRate(BMP3_ODR_50_HZ);
+
+ THEENGS_LOG_NOTICE(F("Bosch BMP390 successfully initialized: %X" CR), BMP390_i2c_addr);
+}
+
+void MeasureTempAndPressureBMP390() {
+ if (millis() > (timebmp390 + TimeBetweenReadingbmp390)) {
+ timebmp390 = millis();
+ static float persisted_bmp_tempc;
+ static float persisted_bmp_tempf;
+ static float persisted_bmp_pa;
+ static float persisted_bmp_altim;
+ static float persisted_bmp_altift;
+
+ bool read_ok = bmp.performReading();
+ float BmpTempC = NAN;
+ float BmpTempF = NAN;
+ float BmpPa = NAN;
+ float BmpAltiM = NAN;
+ float BmpAltiFt = NAN;
+
+ if (read_ok) {
+ BmpTempC = bmp.temperature + (float)BMP390Correction;
+ BmpTempF = (BmpTempC * 9.0f / 5.0f) + 32.0f;
+ BmpPa = bmp.pressure;
+ BmpAltiM = bmp.readAltitude((float)BMP390_SEALEVEL_HPA);
+ BmpAltiFt = BmpAltiM * 3.280839895f;
+ }
+
+ // Check if reads failed and exit early (to try again).
+ if (!read_ok || isnan(BmpTempC) || isnan(BmpTempF) || isnan(BmpPa) || isnan(BmpAltiM) || isnan(BmpAltiFt)) {
+ THEENGS_LOG_ERROR(F("Failed to read from BMP390!" CR));
+ } else {
+ THEENGS_LOG_TRACE(F("Creating BMP390 buffer" CR));
+ StaticJsonDocument BMP390dataBuffer;
+ JsonObject BMP390data = BMP390dataBuffer.to();
+ // Generate Temperature in degrees C
+ if (BmpTempC != persisted_bmp_tempc || bmp390_always) {
+ BMP390data["tempc"] = (float)BmpTempC;
+ } else {
+ THEENGS_LOG_TRACE(F("Same Degrees C don't send it" CR));
+ }
+
+ // Generate Temperature in degrees F
+ if (BmpTempF != persisted_bmp_tempf || bmp390_always) {
+ BMP390data["tempf"] = (float)BmpTempF;
+ } else {
+ THEENGS_LOG_TRACE(F("Same Degrees F don't send it" CR));
+ }
+
+ // Generate Pressure in Pa
+ if (BmpPa != persisted_bmp_pa || bmp390_always) {
+ BMP390data["pa"] = (float)BmpPa;
+ } else {
+ THEENGS_LOG_TRACE(F("Same Pressure don't send it" CR));
+ }
+
+ // Generate Altitude in Meter
+ if (BmpAltiM != persisted_bmp_altim || bmp390_always) {
+ THEENGS_LOG_TRACE(F("Sending Altitude Meter to MQTT" CR));
+ BMP390data["altim"] = (float)BmpAltiM;
+ } else {
+ THEENGS_LOG_TRACE(F("Same Altitude Meter don't send it" CR));
+ }
+
+ // Generate Altitude in Feet
+ if (BmpAltiFt != persisted_bmp_altift || bmp390_always) {
+ BMP390data["altift"] = (float)BmpAltiFt;
+ } else {
+ THEENGS_LOG_TRACE(F("Same Altitude Feet don't send it" CR));
+ }
+ BMP390data["origin"] = BMP390TOPIC;
+ enqueueJsonObject(BMP390data);
+ }
+
+ persisted_bmp_tempc = BmpTempC;
+ persisted_bmp_tempf = BmpTempF;
+ persisted_bmp_pa = BmpPa;
+ persisted_bmp_altim = BmpAltiM;
+ persisted_bmp_altift = BmpAltiFt;
+ }
+}
+
+#endif
diff --git a/main/sensorBMP390.h b/main/sensorBMP390.h
new file mode 100644
index 0000000000..854e45017c
--- /dev/null
+++ b/main/sensorBMP390.h
@@ -0,0 +1,5 @@
+#pragma once
+#include
+
+bool setupBMP390();
+bool readBMP390(float &tempC, float &pressurePa, float &altM);
diff --git a/main/webUI.cpp b/main/webUI.cpp
index b3011169d1..ad50608663 100644
--- a/main/webUI.cpp
+++ b/main/webUI.cpp
@@ -2073,13 +2073,15 @@ void webUIPubPrint(const char* topicori, JsonObject& data) {
break;
}
# endif
-# ifdef ZsensorBME280
+# if defined(ZsensorBME280) || defined(ZsensorBMP390)
case webUIHash("CLIMAtoMQTT"): {
// {"tempc":17.06,"tempf":62.708,"hum":50.0752,"pa":98876.14,"altim":205.8725,"altift":675.4348}
// Line 1
- strlcpy(message->line1, "bme280", WEBUI_TEXT_WIDTH);
+ const String origin = data["origin"] | "";
+ const bool isBmp390 = (origin.indexOf("bmp390") >= 0);
+ strlcpy(message->line1, isBmp390 ? "bmp390" : "bme280", WEBUI_TEXT_WIDTH);
// Line 2
@@ -2101,11 +2103,24 @@ void webUIPubPrint(const char* topicori, JsonObject& data) {
// Line 3
String line3 = "";
- float humidity = data["hum"];
- if (data.containsKey("hum") && humidity <= 100 && humidity >= 0) {
- char hum[5];
- dtostrf(humidity, 3, 1, hum);
- line3 += "hum: " + (String)hum + "% ";
+ if (isBmp390) {
+ if (data.containsKey("altim") && data.containsKey("altift")) {
+ char altitude[7];
+ if (displayMetric) {
+ dtostrf((float)data["altim"], 4, 1, altitude);
+ line3 = "alt: " + (String)altitude + " m";
+ } else {
+ dtostrf((float)data["altift"], 4, 1, altitude);
+ line3 = "alt: " + (String)altitude + " ft";
+ }
+ }
+ } else {
+ float humidity = data["hum"];
+ if (data.containsKey("hum") && humidity <= 100 && humidity >= 0) {
+ char hum[5];
+ dtostrf(humidity, 3, 1, hum);
+ line3 += "hum: " + (String)hum + "% ";
+ }
}
line3.toCharArray(message->line3, WEBUI_TEXT_WIDTH);
@@ -2604,18 +2619,21 @@ void SerialWeb::begin() {
Dummy virtual functions carried over from Serial
*/
int SerialWeb::available(void) {
+ return 0;
}
/*
Dummy virtual functions carried over from Serial
*/
int SerialWeb::peek(void) {
+ return -1;
}
/*
Dummy virtual functions carried over from Serial
*/
int SerialWeb::read(void) {
+ return -1;
}
/*
diff --git a/platformio.ini b/platformio.ini
index 92da37f09d..b6d843cb17 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -28,7 +28,7 @@ extra_configs =
; into a separate file called prod_env.ini, it will be automatically read by pio ;
; an example (prod_env.ini.example) is available into the same folder as this file. ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
+default_envs = tinypico-bmp390-usb
;default_envs = rfbridge
;default_envs = rfbridge-direct
;default_envs = esp32dev-all-test