diff --git a/code/.astylerc b/code/.astylerc new file mode 100644 index 0000000..d158bc6 --- /dev/null +++ b/code/.astylerc @@ -0,0 +1,42 @@ +# Don't create backup files, let git handle it +suffix=none + +# K&R style +style=google + +# 4 spaces, convert tabs to spaces +indent=spaces=4 +convert-tabs + +# Indent +indent-switches +indent-classes +indent-preproc-block +indent-preproc-define + +# Brackets +add-brackets + +# Remove spaces in and around parentheses +unpad-paren + +# Insert a space after if, while, for, and around operators +pad-header +pad-oper + +# Pointer/reference operators go next to the name (on the right) +align-pointer=name +align-reference=name + +# Attach { for classes and namespaces +attach-namespaces +attach-classes + +# Extend longer lines, define maximum 120 value. This results in aligned code, +# otherwise the lines are broken and not consistent +max-continuation-indent=120 +max-code-length=120 + +# Breaks +break-after-logical +break-blocks=all diff --git a/code/WemosWeatherStation/const.h b/code/WemosWeatherStation/const.h index c79758f..d970925 100644 --- a/code/WemosWeatherStation/const.h +++ b/code/WemosWeatherStation/const.h @@ -1,5 +1,5 @@ #define DEVICE_NAME "meteo" // used for MQTT, OTA, AP -#define FW_VERSION "1.0.1" +#define FW_VERSION "2.0.0" #define CONFIG_PATH "/config.json" #define CONFIG_AP_SSID DEVICE_NAME "_config" diff --git a/code/WemosWeatherStation/load.h b/code/WemosWeatherStation/load.h index 1f96dbb..5a297f8 100644 --- a/code/WemosWeatherStation/load.h +++ b/code/WemosWeatherStation/load.h @@ -1,5 +1,5 @@ // wifi.h -#include +#include "LittleFS.h" #include #include #include @@ -13,9 +13,10 @@ WiFiEventHandler wifiDisconnectHandler; class IntParameter : public WiFiManagerParameter { public: - IntParameter(const char *id, const char *placeholder, int32_t value, const uint8_t length = 10, const char *custom = NULL) + IntParameter(const char *id, const char *placeholder, int32_t value, const uint8_t length = 10, + const char *custom = NULL) : WiFiManagerParameter("") { - const char * type_number = "type=\"number\" "; + const char *type_number = "type=\"number\" "; uint16_t custom_len = 0; if (custom) { @@ -81,14 +82,15 @@ IntParameter custom_mqtt_port("mqtt_port", "MQTT port", mqtt_port, 4, "required" WiFiManagerParameter custom_mqtt_user("mqtt_user", "MQTT user", mqtt_user, sizeof(mqtt_user), "placeholder=\"Leave blank if not aplicable\""); WiFiManagerParameter custom_mqtt_password("mqtt_password", "MQTT password", mqtt_password, sizeof(mqtt_password), - "placeholder=\"Leave blank if not aplicable\" type=\"password\""); + "placeholder=\"Leave blank if not aplicable\" type=\"password\""); // ota.h #if defined(NOFUSS_OTA) - #include "NoFUSSClient.h" - char nofuss_server[40]; - WiFiManagerParameter custom_nofuss_server("nofuss_server", "NoFUSS server", nofuss_server, sizeof(nofuss_server), "required"); +#include "NoFUSSClient.h" +char nofuss_server[40]; +WiFiManagerParameter custom_nofuss_server("nofuss_server", "NoFUSS server", nofuss_server, sizeof(nofuss_server), + "required"); #endif #if defined(HTTP_OTA) @@ -96,7 +98,7 @@ WiFiManagerParameter custom_mqtt_password("mqtt_password", "MQTT password", mqtt bool do_http_update = false; char http_ota_url[100]; - void httpUpdate(const char* url); + void httpUpdate(const char *url); #endif #if defined(ARDUINO_OTA) @@ -113,7 +115,29 @@ bool ota_in_progess = false; MeteoFunctions meteoFunctions; +struct sensorData { + float humidity[2] = {NAN, NAN}; // rel, abs + float temp[3] = {NAN, NAN, NAN}; // from baro, temp, humidity + float pressure[2] = {NAN, NAN}; // rel, abs +}; + #if defined(SENSOR_BMP280) || defined(SENSOR_BME280) || defined(SENSOR_LPS35HW) + #define HAS_BARO +#endif + +#if defined(SENSOR_MCP9808) + #define HAS_TEMP +#endif + +#if defined(SENSOR_HTU21D) || defined(SENSOR_SHT31) + #define HAS_HUMIDITY +#endif + +float round2(float value) { + return round(value * 100.0) / 100.0; +} + +#if defined(HAS_BARO) MovingAverageFloat baro_filter[2]; // rel pressure, abs pressure MovingAverageFloat baro_temp_filter; @@ -122,12 +146,12 @@ MeteoFunctions meteoFunctions; IntParameter custom_height_above_sea("height_above_sea", "Height above sea (m)", height_above_sea, 4, "required"); #endif -#if defined(SENSOR_BME280) || defined(SENSOR_HTU21D) || defined(SENSOR_SHT31) +#if defined(SENSOR_BME280) || defined(HAS_HUMIDITY) MovingAverageFloat humidity_filter[2]; // rel humidity, abs humidity MovingAverageFloat humidity_temp_filter; #endif -#if defined(SENSOR_MCP9808) +#if defined(HAS_TEMP) MovingAverageFloat temp_filter; #endif diff --git a/code/WemosWeatherStation/meters.h b/code/WemosWeatherStation/meters.h index 91b027d..639e96f 100644 --- a/code/WemosWeatherStation/meters.h +++ b/code/WemosWeatherStation/meters.h @@ -95,20 +95,20 @@ void metersLoop() { float temp = NAN; float humidity = NAN; -#if defined(SENSOR_HTU21D) || defined(SENSOR_SHT31) +#if defined(HAS_HUMIDITY) if (sensor_state & 0b100) { temp = humidity_temp_filter.get(); humidity = humidity_filter[0].get(); } -#elif defined(SENSOR_MCP9808) +#elif defined(HAS_TEMP) if (sensor_state & 0b010) { temp = temp_filter.get(); } -#elif defined(SENSOR_BMP280) || defined(SENSOR_BME280) || defined(SENSOR_LPS35HW) +#elif defined(HAS_BARO) if (sensor_state & 0b001) { temp = baro_temp_filter.get(); diff --git a/code/WemosWeatherStation/mqtt.h b/code/WemosWeatherStation/mqtt.h index b0197a7..f15c2e9 100644 --- a/code/WemosWeatherStation/mqtt.h +++ b/code/WemosWeatherStation/mqtt.h @@ -35,7 +35,7 @@ void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties #endif if (strcmp(topic, MQTT_HEIGHT_UPDATE_TOPIC) == 0 && len > 0) { -#if defined(SENSOR_BMP280) || defined(SENSOR_BME280) || defined(SENSOR_LPS35HW) +#if defined(HAS_BARO) if (atoi(payload) > 0) { height_above_sea = atoi(payload); diff --git a/code/WemosWeatherStation/ota.h b/code/WemosWeatherStation/ota.h index d8be249..e2079e9 100644 --- a/code/WemosWeatherStation/ota.h +++ b/code/WemosWeatherStation/ota.h @@ -154,14 +154,13 @@ void httpUpdate() { WiFiClient client; ESPhttpUpdate.rebootOnUpdate(false); - ESPhttpUpdate.followRedirects(true); #if defined(DEBUG) Serial.print("[OTA] Starting HTTP update from: "); Serial.println(http_ota_url); #endif - t_httpUpdate_return ret = ESPhttpUpdate.update(client, http_ota_url, FW_VERSION); + t_httpUpdate_return ret = ESPhttpUpdate.update(client, http_ota_url); switch (ret) { case HTTP_UPDATE_FAILED: diff --git a/code/WemosWeatherStation/sensors.h b/code/WemosWeatherStation/sensors.h index f771a26..63432d7 100644 --- a/code/WemosWeatherStation/sensors.h +++ b/code/WemosWeatherStation/sensors.h @@ -1,142 +1,33 @@ #if defined(SENSOR_MCP9808) - #include "Adafruit_MCP9808.h" - Adafruit_MCP9808 mcp; + #include "sensors/mcp9808.h" #endif #if defined(SENSOR_BMP280) || defined(SENSOR_BME280) -#include "BME280I2C.h" -BME280I2C::Settings settings( - BME280::OSR_X1, - BME280::OSR_X1, - BME280::OSR_X1, - BME280::Mode_Forced, - BME280::StandbyTime_1000ms, - BME280::Filter_8, - BME280::SpiEnable_False, - BMP280_ADDR -); - -BME280I2C bmp(settings); + #include "sensors/bmp280.h" #elif defined(SENSOR_LPS35HW) -#include "LPS35HW.h" -LPS35HW lps; + #include "sensors/lps35hw.h" #endif #if defined(SENSOR_HTU21D) - #include "HTU21D.h" - HTU21D htu(HTU21D_RES_RH12_TEMP14); + #include "sensors/htu21d.h" #elif defined(SENSOR_SHT31) - #include "ClosedCube_SHT31D.h" - ClosedCube_SHT31D sht31; + #include "sensors/sht31d.h" #endif -float round2(float value) { - return round(value * 100.0) / 100.0; -} - -bool setupBaro() { -#if defined(SENSOR_BMP280) || defined(SENSOR_BME280) - return bmp.begin(); -#elif defined(SENSOR_LPS35HW) - - if (lps.begin(&Wire)) { - lps.setLowPassFilter(LPS35HW::LowPassFilter_ODR9); - return true; - } - -#endif - return false; -} - -bool setupMCP9808() { -#if defined(SENSOR_MCP9808) - - if (mcp.begin(MCP9808_ADDR, &Wire)) { - sensor_state |= (1 << 1); - mcp.setResolution(3); - mcp.shutdown_wake(0); - return true; - } - -#endif - return false; -} - -bool setupHumidity() { -#if defined(SENSOR_HTU21D) - - if (htu.begin(SDA, SCL)) { - return true; - } - -#elif defined(SENSOR_SHT31) - - if (sht31.begin(SHT31D_ADDR) == SHT3XD_NO_ERROR) { - if (sht31.periodicStart(SHT3XD_REPEATABILITY_HIGH, SHT3XD_FREQUENCY_10HZ) == SHT3XD_NO_ERROR) { - return true; - } - } - -#endif - return false; -} - void sensorsSetup() { Wire.begin(SDA, SCL); Wire.setClock(I2C_SPEED); -#if defined(SENSOR_BMP280) || defined(SENSOR_LPS35HW) - - if (setupBaro()) { - sensor_state |= (1 << 0); - - } else { - sensor_state &= ~(1 << 0); - -#if defined(DEBUG) - Serial.println("[SENSOR] Barometer did not respond. Please check wiring."); +#if defined(HAS_BARO) + setupBaro(); #endif - } -#else - sensor_state &= ~(1 << 0); +#if defined(HAS_TEMP) + setupTemp(); #endif - -#if defined(SENSOR_MCP9808) - - if (mcp.begin(MCP9808_ADDR, &Wire)) { - sensor_state |= (1 << 1); - mcp.setResolution(3); - mcp.shutdown_wake(0); - - } else { - sensor_state &= ~(1 << 1); - -#if defined(DEBUG) - Serial.println("[SENSOR] MCP9808 did not respond. Please check wiring."); -#endif - } - -#else - sensor_state &= ~(1 << 1); -#endif - -#if defined(SENSOR_HTU21D) || defined(SENSOR_SHT31) - - if (setupHumidity()) { - sensor_state |= (1 << 2); - - } else { - sensor_state &= ~(1 << 2); - -#if defined(DEBUG) - Serial.println("[SENSOR] Humidity sensor did not respond. Please check wiring."); -#endif - } - -#else - sensor_state &= ~(1 << 2); +#if defined(HAS_HUMIDITY) + setupHumidity(); #endif } @@ -150,224 +41,81 @@ void sensorsLoop() { last_check = millis(); -#if defined(SENSOR_BME280) || defined(SENSOR_HTU21D) || defined(SENSOR_SHT31) - float abs_humidity = NAN; - float rel_humidity = NAN; - float temp_hum = NAN; -#endif + sensorData data; -#if defined(SENSOR_HTU21D) || defined(SENSOR_SHT31) -#if defined(SENSOR_HTU21D) - temp_hum = htu.readTemperature(); - rel_humidity = htu.readHumidity(); + data.humidity[0] = NAN; + data.humidity[1] = NAN; + data.temp[0] = NAN; + data.temp[1] = NAN; + data.temp[2] = NAN; + data.pressure[0] = NAN; + data.pressure[1] = NAN; - if (temp_hum >= 255.0) { - temp_hum = NAN; - } +#if defined(HAS_BARO) - if (rel_humidity > 100.0 || rel_humidity < 0.0) { - rel_humidity = NAN; + if ((sensor_state & 0b1) == 0) { + setupBaro(); } -#elif defined(SENSOR_SHT31) - SHT31D result = sht31.periodicFetchData(); - - if (result.error == SHT3XD_NO_ERROR) { - temp_hum = result.t; - rel_humidity = result.rh; + if (sensor_state & 0b1) { + readBaro(&data); } #endif - if (!isnan(temp_hum)) { - if ((sensor_state & 0b100) == 0) { - if (setupHumidity()) { - sensor_state |= (1 << 2); - - humidity_filter[0].reset(); // rel - humidity_filter[1].reset(); // abs - humidity_temp_filter.reset(); - -#if defined(DEBUG) - Serial.println("[SENSOR] HTU21D is back on."); -#endif - - } else { - sensor_state &= ~(1 << 2); -#if defined(DEBUG) - Serial.println("[SENSOR] Humidity sensor could not init again."); -#endif - } - } - - if (sensor_state & 0b100) { - abs_humidity = round2(humidity_filter[1].add(meteoFunctions.absoluteHumidity_c(temp_hum, rel_humidity))); - rel_humidity = round2(humidity_filter[0].add(rel_humidity)); - temp_hum = round2(humidity_temp_filter.add(temp_hum)); - } +#if defined(HAS_TEMP) - } else { - if (sensor_state & 0b100) { - sensor_state &= ~(1 << 2); // Humidity not available - -#if defined(DEBUG) - Serial.println("[SENSOR] Humidity sensor stopped responding. Please check wiring."); -#endif - } - - abs_humidity = NAN; - rel_humidity = NAN; - temp_hum = NAN; + if ((sensor_state & 0b10) == 0) { + setupTemp(); } -#endif - -#if defined(SENSOR_MCP9808) - float temp_mcp = mcp.readTempC(); - - if (!isnan(temp_mcp)) { - if ((sensor_state & 0b10) == 0) { - if (setupMCP9808()) { - sensor_state |= (1 << 1); - - temp_filter.reset(); - -#if defined(DEBUG) - Serial.println("[SENSOR] MCP9808 is back on."); -#endif - - } else { - sensor_state &= ~(1 << 1); -#if defined(DEBUG) - Serial.println("[SENSOR] MCP9808 could not init again."); -#endif - } - } - - if (sensor_state & 0b10) { - temp_mcp = round2(temp_filter.add(temp_mcp)); - } - - } else { - if (sensor_state & 0b10) { - sensor_state &= ~(1 << 1); // MCP not available - -#if defined(DEBUG) - Serial.println("[SENSOR] MCP9808 stopped responding. Please check wiring."); -#endif - } - - temp_mcp = NAN; + if (sensor_state & 0b10) { + readTemp(&data); } #endif -#if defined(SENSOR_BMP280) || defined(SENSOR_BME280) || defined(SENSOR_LPS35HW) - float temp_baro = NAN; - float abs_pressure = NAN; - float rel_pressure = NAN; - -#if defined(SENSOR_BMP280) - float none = NAN; - bmp.read(abs_pressure, temp_baro, none); -#elif defined(SENSOR_BME280) - bmp.read(abs_pressure, temp_baro, rel_humidity); -#elif defined(SENSOR_LPS35HW) - abs_pressure = lps.readPressure(); - temp_baro = lps.readTemp(); -#endif - - if (!isnan(temp_baro) && !isnan(abs_pressure)) { - if ((sensor_state & 0b1) == 0) { - if (setupBaro()) { - sensor_state |= (1 << 0); - - baro_filter[0].reset(); // rel - baro_filter[1].reset(); // abs - baro_temp_filter.reset(); - -#if defined(SENSOR_BME280) - humidity_filter[0].reset(); // rel - humidity_filter[1].reset(); // abs -#endif - +#if defined(HAS_HUMIDITY) -#if defined(DEBUG) - Serial.println("[SENSOR] Barometer is back on."); -#endif - - } else { - sensor_state &= ~(1 << 0); - -#if defined(DEBUG) - Serial.println("[SENSOR] Barometer could not init."); -#endif - } - } - - if (sensor_state & 0b1) { - rel_pressure = round2(baro_filter[0].add(meteoFunctions.relativePressure_c(abs_pressure, height_above_sea, temp_baro))); - abs_pressure = round2(baro_filter[1].add(abs_pressure)); - temp_baro = round2(baro_temp_filter.add(temp_baro)); - -#if defined(SENSOR_BME280) - abs_humidity = round2(humidity_filter[1].add(meteoFunctions.absoluteHumidity_c(temp_baro, rel_humidity))); - rel_humidity = round2(humidity_filter[0].add(rel_humidity)); - temp_hum = temp_baro; -#endif - } - - } else { - if (sensor_state & 0b1) { - sensor_state &= ~(1 << 0); // Baro not available - -#if defined(DEBUG) - Serial.println("[SENSOR] Barometer stopped responding again. Please check wiring."); -#endif - } - - rel_pressure = NAN; - abs_pressure = NAN; - temp_baro = NAN; + if ((sensor_state & 0b100) == 0) { + setupHumidity(); + } -#if defined(SENSOR_BME280) - rel_humidity = NAN; - abs_humidity = NAN; - temp_hum = NAN; -#endif + if (sensor_state & 0b100) { + readHumidity(&data); } #endif #if defined(DEBUG) -#if defined(SENSOR_BMP280) || defined(SENSOR_BME280) || defined(SENSOR_LPS35HW) +#if defined(HAS_BARO) Serial.print("[SENSOR] Pressure: "); - Serial.print(abs_pressure, 2); - Serial.print(" hPa, "); - Serial.print(rel_pressure, 2); - Serial.println(" hPa"); + Serial.print(data.pressure[1], 2); + Serial.print("hPa (abs), "); + Serial.print(data.pressure[0], 2); + Serial.println("hPa (rel)"); Serial.print("[SENSOR] Pressure temp: "); - Serial.print(temp_baro); + Serial.print(data.temp[0]); Serial.println(" C"); #endif -#if defined(SENSOR_MCP9808) - Serial.print("[SENSOR] Temp MCP: "); - Serial.print(temp_mcp, 2); +#if defined(HAS_TEMP) + Serial.print("[SENSOR] Temp: "); + Serial.print(data.temp[1], 2); Serial.println(" C"); #endif -#if defined(SENSOR_BME280) || defined(SENSOR_HTU21D) || defined(SENSOR_SHT31) +#if defined(SENSOR_BME280) || defined(HAS_HUMIDITY) Serial.print("[SENSOR] Humidity: "); - Serial.print(abs_humidity, 2); + Serial.print(data.humidity[1], 2); Serial.print(" g/m3, "); - Serial.print(rel_humidity, 2); + Serial.print(data.humidity[0], 2); Serial.println(" %"); #endif -#if defined(SENSOR_HTU21D) || defined(SENSOR_SHT31) +#if defined(HAS_HUMIDITY) Serial.print("[SENSOR] Humidity temp: "); - Serial.print(temp_hum, 2); + Serial.print(data.temp[2], 2); Serial.println(" C"); #endif @@ -379,80 +127,76 @@ void sensorsLoop() { if (counter > READ_SAMPLES) { // time to send data counter = 0; - if (mqtt.connected()) { - StaticJsonDocument < (JSON_OBJECT_SIZE(9) + JSON_ARRAY_SIZE(3)) > json; + if (!mqtt.connected()) { + return; + } + + StaticJsonDocument < (JSON_OBJECT_SIZE(9) + JSON_ARRAY_SIZE(3)) > json; -#if defined(SENSOR_BMP280) || defined(SENSOR_BME280) || defined(SENSOR_LPS35HW) +#if defined(HAS_BARO) - if (!isnan(rel_pressure)) { - json["pressure_rel"] = rel_pressure; - } + if (!isnan(data.pressure[0])) { + json["pressure_rel"] = data.pressure[0]; + } - if (!isnan(abs_pressure)) { - json["pressure_abs"] = abs_pressure; - } + if (!isnan(data.pressure[1])) { + json["pressure_abs"] = data.pressure[1]; + } #endif -#if defined(SENSOR_BMP280) || defined(SENSOR_BME280) || defined(SENSOR_MCP9808) || defined(SENSOR_HTU21D) || defined(SENSOR_SHT31) +#if defined(HAS_BARO) || defined(HAS_TEMP) || defined(HAS_HUMIDITY) - if (sensor_state > 0) { - JsonArray temperatures = json.createNestedArray("temp"); -#if defined(SENSOR_BMP280) || defined(SENSOR_BME280) || defined(SENSOR_LPS35HW) - temperatures.add(temp_baro); + if (sensor_state > 0) { + JsonArray temperatures = json.createNestedArray("temp"); +#if defined(HAS_BARO) + temperatures.add(data.temp[0]); #endif -#if defined(SENSOR_MCP9808) - temperatures.add(temp_mcp); +#if defined(HAS_TEMP) + temperatures.add(data.temp[1]); #endif -#if defined(SENSOR_HTU21D) || defined(SENSOR_SHT31) - temperatures.add(temp_hum); +#if defined(HAS_HUMIDITY) + temperatures.add(data.temp[2]); #endif - } + } #endif -#if defined(SENSOR_BME280) || defined(SENSOR_HTU21D) || defined(SENSOR_SHT31) - - if (!isnan(rel_humidity)) { - json["humidity_rel"] = rel_humidity; - } +#if defined(SENSOR_BME280) || defined(HAS_HUMIDITY) - if (!isnan(abs_humidity)) { - json["humidity_abs"] = abs_humidity; - } + if (!isnan(data.humidity[0])) { + json["humidity_rel"] = data.humidity[0]; + } - if (!isnan(temp_hum) && !isnan(rel_humidity)) { - json["dew"] = round2(meteoFunctions.dewPoint_c(temp_hum, rel_humidity)); - json["humidex"] = round2(meteoFunctions.humidex_c(temp_hum, rel_humidity)); - json["heat"] = round2(meteoFunctions.heatIndex_c(temp_hum, rel_humidity)); - json["cloud"] = round2(meteoFunctions.cloudBase_m(temp_hum, rel_humidity)); - } + if (!isnan(data.humidity[1])) { + json["humidity_abs"] = data.humidity[1]; + } + if (!isnan(data.temp[2]) && !isnan(data.humidity[0])) { + json["dew"] = round2(meteoFunctions.dewPoint_c(data.temp[2], data.humidity[0])); + json["humidex"] = round2(meteoFunctions.humidex_c(data.temp[2], data.humidity[0])); + json["heat"] = round2(meteoFunctions.heatIndex_c(data.temp[2], data.humidity[0])); + json["cloud"] = round2(meteoFunctions.cloudBase_m(data.temp[2], data.humidity[0])); + } #endif - if (json.size() > 0) { + if (json.size() > 0) { #if defined(DEBUG) - Serial.println("[MQTT] Sending sensor data:"); - serializeJsonPretty(json, Serial); - Serial.println(); + Serial.println("[MQTT] Sending sensor data:"); + serializeJsonPretty(json, Serial); + Serial.println(); #endif - char message[350]; - uint32_t len = serializeJson(json, message, sizeof(message)); - mqtt.publish(MQTT_SENSORS_TOPIC, MQTT_QOS, MQTT_RETAIN, message, len); - - } else { -#if defined(DEBUG) - Serial.println("[MQTT] No valid data to send"); -#endif - } + char message[350]; + uint32_t len = serializeJson(json, message, sizeof(message)); + mqtt.publish(MQTT_SENSORS_TOPIC, MQTT_QOS, MQTT_RETAIN, message, len); } else { #if defined(DEBUG) - // Serial.println("[MQTT] Could not send sensors data"); + Serial.println("[MQTT] No valid data to send"); #endif } } diff --git a/code/WemosWeatherStation/sensors/bmp280.h b/code/WemosWeatherStation/sensors/bmp280.h new file mode 100644 index 0000000..71a36f5 --- /dev/null +++ b/code/WemosWeatherStation/sensors/bmp280.h @@ -0,0 +1,71 @@ +#include +BME280I2C::Settings settings( + BME280::OSR_X1, + BME280::OSR_X1, + BME280::OSR_X1, + BME280::Mode_Forced, + BME280::StandbyTime_1000ms, + BME280::Filter_8, + BME280::SpiEnable_False, + BMP280_ADDR +); + +BME280I2C bmp(settings); + +bool setupBaro() { + if (bmp.begin()) { + sensor_state |= (1 << 0); + + return true; + } + +#if defined(DEBUG) + + if (sensor_state & 0b1) { + Serial.println("[SENSOR] BMP280 did not respond. Please check wiring."); + } + +#endif + + sensor_state &= ~(1 << 0); + + return false; +} + +void readBaro(sensorData *data) { +#if defined(SENSOR_BMP280) + float none = NAN; + bmp.read(data->pressure[1], data->temp[0], none); +#elif defined(SENSOR_BME280) + bmp.read(data->pressure[1], data->temp[0], data->humidity[0]); +#endif + + if (!isnan(data->temp[0]) && !isnan(data->pressure[1])) { + data->pressure[0] = round2(baro_filter[0].add( + meteoFunctions.relativePressure_c( + data->pressure[1], height_above_sea, data->temp[0]))); + data->pressure[1] = round2(baro_filter[1].add(data->pressure[1])); + data->temp[0] = round2(baro_temp_filter.add(data->temp[0])); + +#if defined(SENSOR_BME280) + abs_humidity = round2(humidity_filter[1].add(meteoFunctions.absoluteHumidity_c(data->temp[0], data->humidity[0]))); + data->humidity[0] = round2(humidity_filter[0].add(data->humidity[0])); + data->temp[2] = data->temp[0]; +#endif + + } else { + sensor_state &= ~(1 << 0); + baro_filter[0].reset(); // rel + baro_filter[1].reset(); // abs + baro_temp_filter.reset(); + +#if defined(SENSOR_BME280) + humidity_filter[0].reset(); // rel + humidity_filter[1].reset(); // abs +#endif + +#if defined(DEBUG) + Serial.println("[SENSOR] Baro stopped responding."); +#endif + } +} diff --git a/code/WemosWeatherStation/sensors/htu21d.h b/code/WemosWeatherStation/sensors/htu21d.h new file mode 100644 index 0000000..3dd5805 --- /dev/null +++ b/code/WemosWeatherStation/sensors/htu21d.h @@ -0,0 +1,55 @@ +#include +HTU21D htu(HTU21D_RES_RH12_TEMP14); + +bool setupHumidity() { + if (htu.begin(SDA, SCL)) { + sensor_state |= (1 << 2); + + return true; + } + +#if defined(DEBUG) + + if (sensor_state & 0b100) { + Serial.println("[SENSOR] HTU21D did not respond. Please check wiring."); + } + +#endif + + sensor_state &= ~(1 << 2); + + return false; +} + +void readHumidity(sensorData *data) { + bool ok = true; + + data->temp[2] = htu.readTemperature(); + data->humidity[0] = htu.readHumidity(); + + if (data->temp[2] >= 255.0) { + data->temp[2] = NAN; + ok = false; + } + + if (data->humidity[0] > 100.0 || data->humidity[0] < 0.0) { + data->humidity[0] = NAN; + ok = false; + } + + if (ok) { + data->humidity[1] = round2(humidity_filter[1].add(meteoFunctions.absoluteHumidity_c(data->temp[2], data->humidity[0]))); + data->humidity[0] = round2(humidity_filter[0].add(data->humidity[0])); + data->temp[2] = round2(humidity_temp_filter.add(data->temp[2])); + + } else { + sensor_state &= ~(1 << 2); + humidity_filter[0].reset(); // rel + humidity_filter[1].reset(); // abs + humidity_temp_filter.reset(); + +#if defined(DEBUG) + Serial.println("[SENSOR] HTU21D stopped responding."); +#endif + } +} diff --git a/code/WemosWeatherStation/sensors/lps35hw.h b/code/WemosWeatherStation/sensors/lps35hw.h new file mode 100644 index 0000000..4a819ff --- /dev/null +++ b/code/WemosWeatherStation/sensors/lps35hw.h @@ -0,0 +1,46 @@ +#include +LPS35HW lps; + +bool setupBaro() { + if (lps.begin(&Wire)) { + lps.setLowPassFilter(LPS35HW::LowPassFilter_ODR9); + sensor_state |= (1 << 0); + + return true; + } + +#if defined(DEBUG) + + if (sensor_state & 0b1) { + Serial.println("[SENSOR] LPS35HW did not respond. Please check wiring."); + } + +#endif + + sensor_state &= ~(1 << 0); + + return false; +} + +void readBaro(sensorData *data) { + data->pressure[1] = lps.readPressure(); // abs + data->temp[0] = lps.readTemp(); + + if (!isnan(data->temp[0]) && !isnan(data->pressure[1])) { + data->pressure[0] = round2(baro_filter[0].add( + meteoFunctions.relativePressure_c( + data->pressure[1], height_above_sea, data->temp[0]))); + data->pressure[1] = round2(baro_filter[1].add(data->pressure[1])); + data->temp[0] = round2(baro_temp_filter.add(data->temp[0])); + + } else { + sensor_state &= ~(1 << 0); + baro_filter[0].reset(); // rel + baro_filter[1].reset(); // abs + baro_temp_filter.reset(); + +#if defined(DEBUG) + Serial.println("[SENSOR] LPS35HW stopped responding."); +#endif + } +} diff --git a/code/WemosWeatherStation/sensors/mcp9808.h b/code/WemosWeatherStation/sensors/mcp9808.h new file mode 100644 index 0000000..e6131b4 --- /dev/null +++ b/code/WemosWeatherStation/sensors/mcp9808.h @@ -0,0 +1,40 @@ +#include +Adafruit_MCP9808 mcp; + +bool setupTemp() { + if (mcp.begin(MCP9808_ADDR, &Wire)) { + sensor_state |= (1 << 1); + mcp.setResolution(3); + mcp.shutdown_wake(0); + + return true; + } + +#if defined(DEBUG) + + if (sensor_state & 0b10) { + Serial.println("[SENSOR] MCP9808 did not respond. Please check wiring."); + } + +#endif + + sensor_state &= ~(1 << 1); + + return false; +} + +void readTemp(sensorData *data) { + data->temp[1] = mcp.readTempC(); + + if (!isnan(data->temp[1])) { + data->temp[1] = round2(temp_filter.add(data->temp[1])); + + } else { + sensor_state &= ~(1 << 1); + temp_filter.reset(); + +#if defined(DEBUG) + Serial.println("[SENSOR] MCP9808 stopped responding."); +#endif + } +} diff --git a/code/WemosWeatherStation/sensors/sht31d.h b/code/WemosWeatherStation/sensors/sht31d.h new file mode 100644 index 0000000..234465f --- /dev/null +++ b/code/WemosWeatherStation/sensors/sht31d.h @@ -0,0 +1,44 @@ +#include +ClosedCube_SHT31D sht31; + +bool setupHumidity() { + if (sht31.begin(SHT31D_ADDR) == SHT3XD_NO_ERROR) { + if (sht31.periodicStart(SHT3XD_REPEATABILITY_HIGH, SHT3XD_FREQUENCY_10HZ) == SHT3XD_NO_ERROR) { + sensor_state |= (1 << 2); + + return true; + } + } + +#if defined(DEBUG) + + if (sensor_state & 0b100) { + Serial.println("[SENSOR] SHT31D did not respond. Please check wiring."); + } + +#endif + + sensor_state &= ~(1 << 2); + + return false; +} + +void readHumidity(sensorData *data) { + SHT31D result = sht31.periodicFetchData(); + + if (result.error == SHT3XD_NO_ERROR) { + data->humidity[1] = round2(humidity_filter[1].add(meteoFunctions.absoluteHumidity_c(result.t, result.rh))); + data->humidity[0] = round2(humidity_filter[0].add(result.rh)); + data->temp[2] = round2(humidity_temp_filter.add(result.t)); + + } else { + sensor_state &= ~(1 << 2); + humidity_filter[0].reset(); // rel + humidity_filter[1].reset(); // abs + humidity_temp_filter.reset(); + +#if defined(DEBUG) + Serial.println("[SENSOR] SHT31D stopped responding."); +#endif + } +} diff --git a/code/WemosWeatherStation/wifi.h b/code/WemosWeatherStation/wifi.h index 1575e4f..fee679b 100644 --- a/code/WemosWeatherStation/wifi.h +++ b/code/WemosWeatherStation/wifi.h @@ -26,7 +26,7 @@ void saveConfig() { strncpy(mqtt_user, custom_mqtt_user.getValue(), sizeof(mqtt_user)); strncpy(mqtt_password, custom_mqtt_password.getValue(), sizeof(mqtt_password)); -#if defined(SENSOR_BMP280) || defined(SENSOR_BME280) || defined(SENSOR_LPS35HW) +#if defined(HAS_BARO) height_above_sea = custom_height_above_sea.getValue(); #endif @@ -40,7 +40,7 @@ void saveConfig() { json["mqtt_user"] = mqtt_user; json["mqtt_password"] = mqtt_password; -#if defined(SENSOR_BMP280) || defined(SENSOR_BME280) || defined(SENSOR_LPS35HW) +#if defined(HAS_BARO) json["height_above_sea"] = height_above_sea; #endif @@ -48,7 +48,7 @@ void saveConfig() { json["nofuss_server"] = nofuss_server; #endif - File configFile = SPIFFS.open(CONFIG_PATH, "w"); + File configFile = LittleFS.open(CONFIG_PATH, "w"); if (!configFile) { #if defined(DEBUG) @@ -99,7 +99,7 @@ bool loadDefaultConfig() { Serial.println("[FS] mounting..."); #endif - if (SPIFFS.begin()) { + if (LittleFS.begin()) { #if defined(DEBUG) Serial.println("[FS] mounted"); #endif @@ -107,12 +107,12 @@ bool loadDefaultConfig() { DynamicJsonDocument json(JSON_OBJECT_SIZE(5) + 130); File configFile; - if (SPIFFS.exists(CONFIG_PATH)) { + if (LittleFS.exists(CONFIG_PATH)) { #if defined(DEBUG) Serial.println("[FS] Reading config file..."); #endif - configFile = SPIFFS.open(CONFIG_PATH, "r"); + configFile = LittleFS.open(CONFIG_PATH, "r"); if (configFile) { #if defined(DEBUG) @@ -164,7 +164,7 @@ bool loadDefaultConfig() { strncpy(mqtt_password, json["mqtt_password"], sizeof(mqtt_password)); } -#if defined(SENSOR_BMP280) || defined(SENSOR_BME280) || defined(SENSOR_LPS35HW) +#if defined(HAS_BARO) height_above_sea = json["height_above_sea"]; @@ -191,8 +191,8 @@ bool loadDefaultConfig() { #if defined(DEBUG) Serial.println("[FS] Formatting"); #endif - SPIFFS.format(); - configFile = SPIFFS.open(CONFIG_PATH, "w"); + LittleFS.format(); + configFile = LittleFS.open(CONFIG_PATH, "w"); if (!configFile) { Serial.println("Failed to create file"); @@ -204,7 +204,7 @@ bool loadDefaultConfig() { json["mqtt_user"] = ""; json["mqtt_password"] = ""; -#if defined(SENSOR_BMP280) || defined(SENSOR_BME280) || defined(SENSOR_LPS35HW) +#if defined(HAS_BARO) json["height_above_sea"] = DEFAULT_HEIGHT_ABOVE_SEA; #endif @@ -267,7 +267,7 @@ void wifiSetup() { wifiManager.addParameter(&custom_mqtt_user); wifiManager.addParameter(&custom_mqtt_password); -#if defined(SENSOR_BMP280) || defined(SENSOR_BME280) || defined(SENSOR_LPS35HW) +#if defined(HAS_BARO) custom_height_above_sea.setValue(height_above_sea, 4); wifiManager.addParameter(&custom_height_above_sea); #endif diff --git a/code/platformio.ini b/code/platformio.ini index d987963..3c9bae9 100644 --- a/code/platformio.ini +++ b/code/platformio.ini @@ -12,8 +12,8 @@ build_flags = lib_deps = Wire SPI - bblanchon/ArduinoJson @ ^6.17.2 - https://github.com/tzapu/WiFiManager.git#4873c7c6326fcbfb069731035b1ed79ebd11746a + bblanchon/ArduinoJson @ ^6.18.0 + https://github.com/tzapu/WiFiManager.git marvinroger/AsyncMqttClient jchristensen/JC_Button pilotak/MovingAverageFloat