Remove compile-time variables and revamp readme.md

This commit is contained in:
albarlow 2022-07-20 13:06:27 +01:00
parent 866296fefd
commit 22ac12dc36
2 changed files with 149 additions and 101 deletions

View File

@ -1,42 +1,66 @@
Hello! I have written a v2 usermod for the BME280/BMP280 sensor based on the [existing v1 usermod](https://github.com/Aircoookie/WLED/blob/master/usermods/Wemos_D1_mini%2BWemos32_mini_shield/usermod_bme280.cpp). It is not just a refactor, there are many changes which I made to fit my use case, and I hope they will fit the use cases of others as well! Most notably, this usermod is *just* for the BME280 and does not control a display like in the v1 usermod designed for the WeMos shield. # Usermod BME280
This Usermod is designed to read a `BME280` or `BMP280` sensor and output the following:
- Temperature
- Humidity (`BME280` only)
- Pressure
- Heat Index (`BME280` only)
- Dew Point (`BME280` only)
- Requires libraries `BME280@~3.0.0` (by [finitespace](https://github.com/finitespace/BME280)) and `Wire`. Please add these under `lib_deps` in your `platform.ini` (or `platform_override.ini`). Configuration is all completed via the Usermod menu. There are no settings to set in code! The following settings can be configured in the Usermod Menu (remember to reboot for any changes made here to take effect):
- Data is published over MQTT so make sure you've enabled the MQTT sync interface. - Temperature Decimals (number of decimal places to output)
- Humidity Decimals
- Pressure Decimals
- Temperature Interval (how many seconds between reads of temperature and humidity)
- Pressure Interval
- Publish Always (turn off to only publish changes, on to publish whether or not value changed)
- Use Celsius (turn off to use Farenheit)
- Home Assistant Discovery (turn on to sent MQTT Discovery entries for Home Assistant)
- SDA/SCL GPIO Pins
Dependencies
- Libraries
- `BME280@~3.0.0` (by [finitespace](https://github.com/finitespace/BME280))
- `Wire`
- These must be added under `lib_deps` in your `platform.ini` (or `platform_override.ini`).
- Data is published over MQTT - make sure you've enabled the MQTT sync interface.
- This usermod also writes to serial (GPIO1 on ESP8266). Please make sure nothing else listening on the serial TX pin of your board will get confused by log messages! - This usermod also writes to serial (GPIO1 on ESP8266). Please make sure nothing else listening on the serial TX pin of your board will get confused by log messages!
To enable, compile with `USERMOD_BME280` defined (i.e. `platformio_override.ini`) In addition to outputting via MQTT, you can read the values from the Info Screen on the dashboard page of the device's web interface.
Methods also exist to read the read/calculated values from other WLED modules through code.
- `getTemperatureC()`
- `getTemperatureF()`
- `getHumidity()`
- `getPressure()`
- `getDewPointC()`
- `getDewPointF()`
- `getHeatIndexC()`
- `getHeatIndexF()`
# Complilation
To enable, compile with `USERMOD_BME280` defined (e.g. in `platformio_override.ini`)
```ini ```ini
[env:usermod_bme280_d1_mini]
extends = env:d1_mini
build_flags = build_flags =
${common.build_flags_esp8266} ${common.build_flags_esp8266}
-D USERMOD_BME280 -D USERMOD_BME280
``` lib_deps =
or define `USERMOD_BME280` in `my_config.h` ${esp8266.lib_deps}
```c++ BME280@~3.0.0
#define USERMOD_BME280 Wire
``` ```
If you are using Home Assistant, there is an option to create a discoverable device with sensors for Pressure, Humidity, Temperature, Dew Point and Heat Index. This can be disabled if required.
Changes include: # MQTT
- Adjustable measure intervals MQTT topics are as follows (`<deviceTopic>` is set in MQTT section of Sync Setup menu):
- Temperature and pressure have separate intervals due to pressure not frequently changing at any constant altitude
- Adjustment of number of decimal places in published sensor values
- Separate adjustment for temperature, humidity and pressure values
- Values are rounded to the specified number of decimal places
- Pressure measured in units of hPa instead of Pa
- Calculation of heat index (apparent temperature) and dew point
- These, along with humidity measurements, are disabled if the sensor is a BMP280
- 16x oversampling of sensor during measurement
- Values are only published if they are different from the previous value
- Values are published on startup (continually until the MQTT broker acknowledges a successful publication)
Adjustments are made through preprocessor definitions at the start of the class definition.
MQTT topics are as follows:
Measurement type | MQTT topic Measurement type | MQTT topic
--- | --- --- | ---
Temperature | `<deviceTopic>/temperature` Temperature | `<deviceTopic>/temperature`
Humidity | `<deviceTopic>/humidity` Humidity | `<deviceTopic>/humidity`
Pressure | `<deviceTopic>/pressure` Pressure | `<deviceTopic>/pressure`
Heat index | `<deviceTopic>/heat_index` Heat index | `<deviceTopic>/heat_index`
Dew point | `<deviceTopic>/dew_point` Dew point | `<deviceTopic>/dew_point`
If you are using Home Assistant, and `Home Assistant Discovery` is turned on, Home Assistant should automatically detect a new device, provided you have the MQTT integration installed. The device is seperate from the main WLED device and will contain sensors for Pressure, Humidity, Temperature, Dew Point and Heat Index.

View File

@ -12,24 +12,28 @@
class UsermodBME280 : public Usermod class UsermodBME280 : public Usermod
{ {
private: private:
// User-defined configuration
#define Celsius // Show temperature mesaurement in Celcius. Comment out for Fahrenheit // NOTE: Do not implement any compile-time variables, anything the user needs to configure
unsigned long TemperatureDecimals = 0; // Number of decimal places in published temperaure values // should be configurable from the Usermod menu using the methods below
unsigned long HumidityDecimals = 0; // Number of decimal places in published humidity values // key settings set via usermod menu
unsigned long PressureDecimals = 0; // Number of decimal places in published pressure values unsigned long TemperatureDecimals = 0; // Number of decimal places in published temperaure values
unsigned long TemperatureInterval = 5; // Interval to measure temperature (and humidity, dew point if available) in seconds unsigned long HumidityDecimals = 0; // Number of decimal places in published humidity values
unsigned long PressureInterval = 300; // Interval to measure pressure in seconds unsigned long PressureDecimals = 0; // Number of decimal places in published pressure values
bool PublishAlways = false; // Publish values even when they have not changed unsigned long TemperatureInterval = 5; // Interval to measure temperature (and humidity, dew point if available) in seconds
bool HomeAssistantDiscovery = false; // Publish Home Assistant Device Information unsigned long PressureInterval = 300; // Interval to measure pressure in seconds
bool PublishAlways = false; // Publish values even when they have not changed
bool UseCelsius = true; // Use Celsius for Reporting
bool HomeAssistantDiscovery = false; // Publish Home Assistant Device Information
#ifdef ARDUINO_ARCH_ESP32 // ESP32 boards // set the default pins based on the architecture, these get overridden by Usermod menu settings
uint8_t SCL_PIN = 22; #ifdef ARDUINO_ARCH_ESP32 // ESP32 boards
uint8_t SDA_PIN = 21; uint8_t SCL_PIN = 22;
#else // ESP8266 boards uint8_t SDA_PIN = 21;
uint8_t SCL_PIN = 5; #else // ESP8266 boards
uint8_t SDA_PIN = 4; uint8_t SCL_PIN = 5;
//uint8_t RST_PIN = 16; // Uncoment for Heltec WiFi-Kit-8 uint8_t SDA_PIN = 4;
#endif //uint8_t RST_PIN = 16; // Uncoment for Heltec WiFi-Kit-8
#endif
// BME280 sensor settings // BME280 sensor settings
BME280I2C::Settings settings{ BME280I2C::Settings settings{
@ -59,6 +63,7 @@ bool HomeAssistantDiscovery = false; // Publish Home Assistant Device Inform
float sensorHeatIndex; float sensorHeatIndex;
float sensorDewPoint; float sensorDewPoint;
float sensorPressure; float sensorPressure;
String tempScale;
// Track previous sensor values // Track previous sensor values
float lastTemperature; float lastTemperature;
float lastHumidity; float lastHumidity;
@ -78,31 +83,47 @@ bool HomeAssistantDiscovery = false; // Publish Home Assistant Device Inform
uint16_t mqttTemperaturePub = 0; uint16_t mqttTemperaturePub = 0;
uint16_t mqttPressurePub = 0; uint16_t mqttPressurePub = 0;
// Read the BME280/BMP280 Sensor (which one runs depends on whether Celsius or Farenheit being set in Usermod Menu)
void UpdateBME280Data(int SensorType) void UpdateBME280Data(int SensorType)
{ {
float _temperature, _humidity, _pressure; float _temperature, _humidity, _pressure;
#ifdef Celsius
if (UseCelsius) {
BME280::TempUnit tempUnit(BME280::TempUnit_Celsius); BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
EnvironmentCalculations::TempUnit envTempUnit(EnvironmentCalculations::TempUnit_Celsius); EnvironmentCalculations::TempUnit envTempUnit(EnvironmentCalculations::TempUnit_Celsius);
#else BME280::PresUnit presUnit(BME280::PresUnit_hPa);
bme.read(_pressure, _temperature, _humidity, tempUnit, presUnit);
sensorTemperature = _temperature;
sensorHumidity = _humidity;
sensorPressure = _pressure;
tempScale = "°C";
if (sensorType == 1)
{
sensorHeatIndex = EnvironmentCalculations::HeatIndex(_temperature, _humidity, envTempUnit);
sensorDewPoint = EnvironmentCalculations::DewPoint(_temperature, _humidity, envTempUnit);
}
} else {
BME280::TempUnit tempUnit(BME280::TempUnit_Fahrenheit); BME280::TempUnit tempUnit(BME280::TempUnit_Fahrenheit);
EnvironmentCalculations::TempUnit envTempUnit(EnvironmentCalculations::TempUnit_Fahrenheit); EnvironmentCalculations::TempUnit envTempUnit(EnvironmentCalculations::TempUnit_Fahrenheit);
#endif BME280::PresUnit presUnit(BME280::PresUnit_hPa);
BME280::PresUnit presUnit(BME280::PresUnit_hPa);
bme.read(_pressure, _temperature, _humidity, tempUnit, presUnit); bme.read(_pressure, _temperature, _humidity, tempUnit, presUnit);
sensorTemperature = _temperature; sensorTemperature = _temperature;
sensorHumidity = _humidity; sensorHumidity = _humidity;
sensorPressure = _pressure; sensorPressure = _pressure;
if (sensorType == 1) tempScale = "°F";
{ if (sensorType == 1)
sensorHeatIndex = EnvironmentCalculations::HeatIndex(_temperature, _humidity, envTempUnit); {
sensorDewPoint = EnvironmentCalculations::DewPoint(_temperature, _humidity, envTempUnit); sensorHeatIndex = EnvironmentCalculations::HeatIndex(_temperature, _humidity, envTempUnit);
sensorDewPoint = EnvironmentCalculations::DewPoint(_temperature, _humidity, envTempUnit);
}
} }
} }
// Procedure to define all MQTT Topics // Procedure to define all MQTT discovery Topics
void _mqttInitialize() void _mqttInitialize()
{ {
mqttTemperatureTopic = String(mqttDeviceTopic) + "/temperature"; mqttTemperatureTopic = String(mqttDeviceTopic) + "/temperature";
@ -111,25 +132,15 @@ bool HomeAssistantDiscovery = false; // Publish Home Assistant Device Inform
mqttHeatIndexTopic = String(mqttDeviceTopic) + "/heat_index"; mqttHeatIndexTopic = String(mqttDeviceTopic) + "/heat_index";
mqttDewPointTopic = String(mqttDeviceTopic) + "/dew_point"; mqttDewPointTopic = String(mqttDeviceTopic) + "/dew_point";
String t = String("homeassistant/sensor/") + mqttClientID + "/temperature/config"; if (HomeAssistantDiscovery) {
String t = String("homeassistant/sensor/") + mqttClientID + "/temperature/config";
#ifdef Celsius _createMqttSensor("Temperature", mqttTemperatureTopic, "temperature", tempScale);
_createMqttSensor("Temperature", mqttTemperatureTopic, "temperature", "°C"); _createMqttSensor("Pressure", mqttPressureTopic, "pressure", "hPa");
#else _createMqttSensor("Humidity", mqttHumidityTopic, "humidity", "%");
_createMqttSensor("Temperature", mqttTemperatureTopic, "temperature", "°F"); _createMqttSensor("HeatIndex", mqttHeatIndexTopic, "temperature", tempScale);
#endif _createMqttSensor("DewPoint", mqttDewPointTopic, "temperature", tempScale);
_createMqttSensor("Pressure", mqttPressureTopic, "pressure", "hPa"); }
_createMqttSensor("Humidity", mqttHumidityTopic, "humidity", "%");
#ifdef Celsius
_createMqttSensor("HeatIndex", mqttHeatIndexTopic, "temperature", "°C");
#else
_createMqttSensor("HeatIndex", mqttHeatIndexTopic, "temperature", "°F");
#endif
#ifdef Celsius
_createMqttSensor("DewPoint", mqttDewPointTopic, "temperature", "°C");
#else
_createMqttSensor("DewPoint", mqttDewPointTopic, "temperature", "°F");
#endif
} }
// Create an MQTT Sensor for Home Assistant Discovery purposes, this includes a pointer to the topic that is published to in the Loop. // Create an MQTT Sensor for Home Assistant Discovery purposes, this includes a pointer to the topic that is published to in the Loop.
@ -210,7 +221,7 @@ public:
float temperature = roundf(sensorTemperature * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals); float temperature = roundf(sensorTemperature * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals);
float humidity, heatIndex, dewPoint; float humidity, heatIndex, dewPoint;
if (WLED_MQTT_CONNECTED && !mqttInitialized && HomeAssistantDiscovery) if (WLED_MQTT_CONNECTED && !mqttInitialized)
{ {
_mqttInitialize(); _mqttInitialize();
mqttInitialized = true; mqttInitialized = true;
@ -277,19 +288,19 @@ public:
* API calls te enable data exchange between WLED modules * API calls te enable data exchange between WLED modules
*/ */
inline float getTemperatureC() { inline float getTemperatureC() {
#ifdef Celsius if (UseCelsius) {
return (float)roundf(sensorTemperature * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals); return (float)roundf(sensorTemperature * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals);
#else } else {
return (float)roundf(sensorTemperature * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals) * 1.8f + 32; return (float)roundf(sensorTemperature * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals) * 1.8f + 32;
#endif }
} }
inline float getTemperatureF() { inline float getTemperatureF() {
#ifdef Celsius if (UseCelsius) {
return ((float)roundf(sensorTemperature * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals) -32) * 0.56f; return ((float)roundf(sensorTemperature * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals) -32) * 0.56f;
#else } else {
return (float)roundf(sensorTemperature * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals); return (float)roundf(sensorTemperature * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals);
#endif }
} }
inline float getHumidity() { inline float getHumidity() {
return (float)roundf(sensorHumidity * pow(10, HumidityDecimals)); return (float)roundf(sensorHumidity * pow(10, HumidityDecimals));
@ -297,11 +308,32 @@ public:
inline float getPressure() { inline float getPressure() {
return (float)roundf(sensorPressure * pow(10, PressureDecimals)); return (float)roundf(sensorPressure * pow(10, PressureDecimals));
} }
inline float getDewPoint() { inline float getDewPointC() {
return (float)roundf(sensorDewPoint * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals); if (UseCelsius) {
return (float)roundf(sensorDewPoint * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals);
} else {
return (float)roundf(sensorDewPoint * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals) * 1.8f + 32;
}
} }
inline float getHeatIndex() { inline float getDewPointF() {
return (float)roundf(sensorHeatIndex * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals); if (UseCelsius) {
return ((float)roundf(sensorDewPoint * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals) -32) * 0.56f;
} else {
return (float)roundf(sensorDewPoint * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals);
}
}
inline float getHeatIndexC() {
if (UseCelsius) {
return (float)roundf(sensorHeatIndex * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals);
} else {
return (float)roundf(sensorHeatIndex * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals) * 1.8f + 32;
}
}inline float getHeatIndexF() {
if (UseCelsius) {
return ((float)roundf(sensorHeatIndex * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals) -32) * 0.56f;
} else {
return (float)roundf(sensorHeatIndex * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals);
}
} }
// Publish Sensor Information to Info Page // Publish Sensor Information to Info Page
@ -322,7 +354,7 @@ public:
JsonArray temperature_json = user.createNestedArray("Temperature"); JsonArray temperature_json = user.createNestedArray("Temperature");
JsonArray pressure_json = user.createNestedArray("Pressure"); JsonArray pressure_json = user.createNestedArray("Pressure");
temperature_json.add(roundf(sensorTemperature * pow(10, TemperatureDecimals))); temperature_json.add(roundf(sensorTemperature * pow(10, TemperatureDecimals)));
temperature_json.add(F("°C")); temperature_json.add(tempScale);
pressure_json.add(roundf(sensorPressure * pow(10, PressureDecimals))); pressure_json.add(roundf(sensorPressure * pow(10, PressureDecimals)));
pressure_json.add(F("hPa")); pressure_json.add(F("hPa"));
} }
@ -334,27 +366,15 @@ public:
JsonArray heatindex_json = user.createNestedArray("Heat Index"); JsonArray heatindex_json = user.createNestedArray("Heat Index");
JsonArray dewpoint_json = user.createNestedArray("Dew Point"); JsonArray dewpoint_json = user.createNestedArray("Dew Point");
temperature_json.add(roundf(sensorTemperature * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals)); temperature_json.add(roundf(sensorTemperature * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals));
#ifdef Celsius temperature_json.add(tempScale);
temperature_json.add(F("°C"));
#else
temperature_json.add(F("°F"));
#endif
humidity_json.add(roundf(sensorHumidity * pow(10, HumidityDecimals))); humidity_json.add(roundf(sensorHumidity * pow(10, HumidityDecimals)));
humidity_json.add(F("%")); humidity_json.add(F("%"));
pressure_json.add(roundf(sensorPressure * pow(10, PressureDecimals))); pressure_json.add(roundf(sensorPressure * pow(10, PressureDecimals)));
pressure_json.add(F("hPa")); pressure_json.add(F("hPa"));
heatindex_json.add(roundf(sensorHeatIndex * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals)); heatindex_json.add(roundf(sensorHeatIndex * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals));
#ifdef Celsius heatindex_json.add(tempScale);
heatindex_json.add(F("°C"));
#else
heatindex_json.add(F("°F"));
#endif
dewpoint_json.add(roundf(sensorDewPoint * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals)); dewpoint_json.add(roundf(sensorDewPoint * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals));
#ifdef Celsius dewpoint_json.add(tempScale);
dewpoint_json.add(F("°C"));
#else
dewpoint_json.add(F("°F"));
#endif
} }
return; return;
} }
@ -367,7 +387,9 @@ public:
top["HumidityDecimals"] = HumidityDecimals; top["HumidityDecimals"] = HumidityDecimals;
top["PressureDecimals"] = PressureDecimals; top["PressureDecimals"] = PressureDecimals;
top["TemperatureInterval"] = TemperatureInterval; top["TemperatureInterval"] = TemperatureInterval;
top["PressureInterval"] = PressureInterval;
top["PublishAlways"] = PublishAlways; top["PublishAlways"] = PublishAlways;
top["UseCelsius"] = UseCelsius;
top["HomeAssistantDiscovery"] = HomeAssistantDiscovery; top["HomeAssistantDiscovery"] = HomeAssistantDiscovery;
JsonArray pinArray = top.createNestedArray("pin-sda-scl"); JsonArray pinArray = top.createNestedArray("pin-sda-scl");
pinArray.add(SDA_PIN); pinArray.add(SDA_PIN);
@ -389,7 +411,9 @@ public:
configComplete &= getJsonValue(top["HumidityDecimals"], HumidityDecimals, 0); configComplete &= getJsonValue(top["HumidityDecimals"], HumidityDecimals, 0);
configComplete &= getJsonValue(top["PressureDecimals"], PressureDecimals, 0); configComplete &= getJsonValue(top["PressureDecimals"], PressureDecimals, 0);
configComplete &= getJsonValue(top["TemperatureInterval"], TemperatureInterval, 30); configComplete &= getJsonValue(top["TemperatureInterval"], TemperatureInterval, 30);
configComplete &= getJsonValue(top["PressureInterval"], PressureInterval, 30);
configComplete &= getJsonValue(top["PublishAlways"], PublishAlways, false); configComplete &= getJsonValue(top["PublishAlways"], PublishAlways, false);
configComplete &= getJsonValue(top["UseCelsius"], UseCelsius, true);
configComplete &= getJsonValue(top["HomeAssistantDiscovery"], HomeAssistantDiscovery, false); configComplete &= getJsonValue(top["HomeAssistantDiscovery"], HomeAssistantDiscovery, false);
configComplete &= getJsonValue(top["pin-sda-scl"][0], SDA_PIN, 21); //SDA configComplete &= getJsonValue(top["pin-sda-scl"][0], SDA_PIN, 21); //SDA
configComplete &= getJsonValue(top["pin-sda-scl"][1], SCL_PIN, 22); //SCL configComplete &= getJsonValue(top["pin-sda-scl"][1], SCL_PIN, 22); //SCL