This commit is contained in:
Patrick Haßel 2025-02-14 11:55:43 +01:00
parent 0660bb1726
commit d03369e7ef
7 changed files with 122 additions and 22 deletions

View File

@ -4,6 +4,7 @@ board = esp12e
framework = arduino
lib_deps = https://github.com/adafruit/Adafruit_TSL2561
https://github.com/knolleary/pubsubclient
https://github.com/adafruit/Adafruit_BME680
build_flags = -DHOSTNAME=\"Greenhouse\"
monitor_speed = 115200
upload_protocol = espota

75
src/bme680.h Normal file
View File

@ -0,0 +1,75 @@
#ifndef BME680_H
#define BME680_H
#include <Adafruit_BME680.h>
#include <mqtt.h>
class BME680 {
Adafruit_BME680 bme; // NOLINT(*-interfaces-global-init)
public:
const char *name;
unsigned long intervalMs;
explicit BME680(const char *name, const unsigned long interval_ms = 5000) : name(name), intervalMs(interval_ms) {
//
}
void setup() {
if (bme.begin()) {
Log.printf("BME680: Initialized.\n");
} else {
Log.printf("BME680: Failed to initialize.\n");
}
bme.setTemperatureOversampling(BME680_OS_8X);
bme.setHumidityOversampling(BME680_OS_2X);
bme.setPressureOversampling(BME680_OS_4X);
bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
bme.setGasHeater(320, 150);
}
void loop() {
const auto now = max(1UL, millis());
static auto last = 0UL;
if (last == 0 || now - last >= intervalMs) {
if (bme.beginReading() == 0) {
Log.print("BME680: Failed to request reading.\n");
setup();
}
last = now;
}
if (bme.remainingReadingMillis() == 0) {
if (bme.endReading()) {
const auto humidityAbsolute = calculateHumidityAbsolute(bme.temperature, bme.humidity);
mqttPublish("garden/temperature", bme.temperature, "\xB0""C");
mqttPublish("garden/pressure", bme.pressure / 100.0, "hPa");
mqttPublish("garden/humidity/relative", bme.humidity, "%");
mqttPublish("garden/humidity/absolute", humidityAbsolute, "mg/L");
mqttPublish("garden/gas", bme.gas_resistance / 1000.0, "KOhms");
mqttPublish("garden/altitude", bme.readAltitude(1013.25), "m");
} else {
Log.printf("Failed to complete reading\n");
setup();
}
}
}
static double calculateHumidityAbsolute(const double temperature, const double humidityRelative) {
constexpr auto A = 6.112;
constexpr auto m = 17.67;
constexpr auto Tn = 243.5;
constexpr auto Mw = 18.01534;
constexpr auto R = 8.314462618;
const auto Tk = temperature + 273.15;
const auto P_sat = A * exp((m * temperature) / (temperature + Tn));
const auto P_act = P_sat * (humidityRelative / 100.0);
return (P_act * Mw) / (R * Tk);
}
};
#endif

View File

@ -1,16 +1,25 @@
#include <bme680.h>
#include "mqtt.h"
#include "tsl2561.h"
#include "wifi.h"
BME680 garden("garden");
BME680 greenhouse("greenhouse");
void setup() {
delay(500);
Log.printf("\n\n\nStartup\n");
wifiConnect();
sensorSetup();
tsl2561Setup();
garden.setup();
greenhouse.setup();
}
void loop() {
wifiLoop();
sensorLoop();
mqttLoop();
}
tsl2561Loop();
garden.loop();
greenhouse.loop();
}

View File

@ -65,30 +65,37 @@ void mqttLoop() {
}
void mqttPublish(const char *topic, const int32_t value, const char *unit) {
if (!isTimeSet()) {
return;
}
char buffer[200];
snprintf(buffer, sizeof buffer, R"({"timestamp": %lld, "value": %d, "unit": "%s"})", time(nullptr), value, unit);
mqttPublish(topic, buffer);
mqttPublish(topic, String(value), unit);
}
void mqttPublish(const char *topic, const int64_t value, const char *unit) {
mqttPublish(topic, String(value), unit);
}
void mqttPublish(const char *topic, const uint32_t value, const char *unit) {
if (!isTimeSet()) {
return;
}
char buffer[200];
snprintf(buffer, sizeof buffer, R"({"timestamp": %lld, "value": %d, "unit": "%s"})", time(nullptr), value, unit);
mqttPublish(topic, buffer);
mqttPublish(topic, String(value), unit);
}
void mqttPublish(const char *topic, const uint64_t value, const char *unit) {
mqttPublish(topic, String(value), unit);
}
void mqttPublish(const char *topic, const float value, const char *unit) {
mqttPublish(topic, String(value), unit);
}
void mqttPublish(const char *topic, const double value, const char *unit) {
mqttPublish(topic, String(value), unit);
}
bool mqttPublish(const char *topic, const String& value, const char *unit) {
if (!isTimeSet()) {
return;
return true;
}
char buffer[200];
snprintf(buffer, sizeof buffer, R"({"timestamp": %lld, "value": %s, "unit": "%s"})", time(nullptr), isnan(value) ? "null" : String(value).c_str(), unit);
snprintf(buffer, sizeof buffer, R"({"timestamp": %lld, "value": %s, "unit": "%s"})", time(nullptr), value.c_str(), unit);
mqttPublish(topic, buffer);
return false;
}
void mqttPublish(const char *topic, const char *payload) {

View File

@ -13,10 +13,18 @@ void mqttLoop();
void mqttPublish(const char *topic, int32_t value, const char *unit);
void mqttPublish(const char *topic, int64_t value, const char *unit);
void mqttPublish(const char *topic, uint32_t value, const char *unit);
void mqttPublish(const char *topic, uint64_t value, const char *unit);
void mqttPublish(const char *topic, float value, const char *unit);
void mqttPublish(const char *topic, double value, const char *unit);
bool mqttPublish(const char *topic, const String& value, const char *unit);
void mqttPublish(const char *topic, const char *payload);
class LogClass final : public Stream {

View File

@ -9,7 +9,7 @@
auto tsl = Adafruit_TSL2561_Unified(TSL2561_ADDR_FLOAT);
void sensorSetup() {
void tsl2561Setup() {
if (tsl.begin()) {
Log.printf("TSL2561: Initialized.\n");
} else {
@ -26,13 +26,13 @@ void sensorRead() {
const auto illuminance = tsl.calculateLux(broadband, ir);
if (illuminance == 65536) {
Log.printf("TSL2561: Failed to read.\n");
sensorSetup();
tsl2561Setup();
} else {
mqttPublish("garden/illuminance", illuminance, "lux");
}
}
void sensorLoop() {
void tsl2561Loop() {
const auto now = millis();
static unsigned long last = 0;
if (last == 0 || now - last >= TSL2561_INTERVAL_MS) {

View File

@ -1,8 +1,8 @@
#ifndef TSL2561_H
#define TSL2561_H
void sensorSetup();
void tsl2561Setup();
void sensorLoop();
void tsl2561Loop();
#endif