diff --git a/envisens/envisens_esp_fw/envisens_esp_fw.ino b/envisens/envisens_esp_fw/envisens_esp_fw.ino index a746692..0b40524 100644 --- a/envisens/envisens_esp_fw/envisens_esp_fw.ino +++ b/envisens/envisens_esp_fw/envisens_esp_fw.ino @@ -10,129 +10,36 @@ #include #include #include -#include "DHT.h" + #include "configuration.h" - -#define TOPIC_BASE "sensor/" sensor_id "/" -#define TOPIC_TEMP TOPIC_BASE "temperature" -#define TOPIC_HMID TOPIC_BASE "humidity" -#define TOPIC_HEAT TOPIC_BASE "heat_index" -#define TOPIC_ABHU TOPIC_BASE "abs_humidity" -#define TOPIC_AIRQ TOPIC_BASE "air_gas" - -#define DIFF_TEMP 0.5 // sensor has only 0.5°C accuracy, triggering on less is ludicrous -#define DIFF_HMID 2.5 // humidity doesn't change that much anyways -#define DIFF_HEAT 0.5 // this one's actually quite active -#define DIFF_ABHU 0.5 // small changes mean quite something -#define DIFF_AIRQ 5 // this one changes in integers - -float hmid = 0; // humidity -float hmid_r = 0; // humidity -float abhu = 0; // absolute humidity -float abhu_r = 0; // absolute humidity -float temp = 0; // temperature -float temp_r = 0; // temperature -float heat = 0; // heat index -float heat_r = 0; // heat index -float airq = 0; // air quality / gas -float airq_r = 0; // air quality / gas +#include "sensing.h" char data[8]; char sensor_name[5]; float sensor_value; +long lastMsg = 0; WiFiClient espClient; PubSubClient client(espClient); +Sensor temp = {"temperature (°C)", TOPIC_TEMP, DIFF_TEMP, 0.0, 0.0, -1}; // temperature +Sensor hmid = {"humidity (%)", TOPIC_HMID, DIFF_HMID, 0.0, 0.0, -1}; // humidity +Sensor abhu = {"absolute humidity (gr/m³)", TOPIC_ABHU, DIFF_ABHU, 0.0, 0.0, -1}; // absolute humidity +Sensor heat = {"heat index (°C)", TOPIC_HEAT, DIFF_HEAT, 0.0, 0.0, -1}; // heat index +Sensor airq = {"air quality (ppm)", TOPIC_AIRQ, DIFF_AIRQ, 0.0, 0.0, -1}; // air quality + void setup() { Serial.begin(SERIAL_BAUDRATE); pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, LOW); setup_wifi(); - client.setServer(mqtt_server, mqtt_port); + client.setServer(MQTT_SERVER, MQTT_PORT); Wire.begin(); // join i2c bus as master } -void setup_wifi() { - delay(10); - // Connect to a WiFi network - Serial.println(); - Serial.print("Connecting to "); - Serial.println(wifi_ssid); - - WiFi.begin(wifi_ssid, wifi_password); - WiFi.mode(WIFI_STA); - - // blink LED fast until WiFi is connected - while (WiFi.status() != WL_CONNECTED) { - delay(200); - digitalWrite(LED_BUILTIN, HIGH); - Serial.print("."); - delay(200); - digitalWrite(LED_BUILTIN, LOW); - } - - // WiFi connected - Serial.println(""); - Serial.println("WiFi connected"); - Serial.println("IP address: "); - Serial.println(WiFi.localIP()); -} - -void reconnect() { - // Loop until reconnected - while (!client.connected()) { - Serial.print("Attempting MQTT connection..."); - // Attempt to connect - if (client.connect(mqtt_client, mqtt_user, mqtt_password)) { - Serial.println("connected"); - } else { - Serial.print("failed, rc="); - Serial.print(client.state()); - Serial.println(" try again in 5 seconds"); - digitalWrite(LED_BUILTIN, HIGH); - // Wait 5 seconds before retrying - delay(4000); - digitalWrite(LED_BUILTIN, LOW); - delay(1000); - } - } -} - -bool checkVariation(float newValue, float prevValue, float maxDiff) { - return !isnan(newValue) && - (newValue < prevValue - maxDiff || newValue > prevValue + maxDiff); -} - -bool checkPlausibility(float newValue, float prevValue, float maxDiff) { - return (newValue < prevValue + (maxDiff * 10) || newValue > prevValue - (maxDiff * 10) || prevValue == 0.0); -} - -long lastMsg = 0; -long lastSent = 0; -bool published = false; -bool forcePublish = false; - -bool publish (String desc, char *topic, float val, float &lastVal, float diff, bool force){ - bool ret = false; - Serial.println("Sample " + desc + ": " + String(val).c_str() + " vs. last " + String(lastVal).c_str()); - if (checkVariation(val, lastVal, diff) or force) { - Serial.println("Sufficient variation on " + desc + ": " + String(val).c_str()); - if (checkPlausibility(val, lastVal, diff) or force) { - Serial.println("Value " + desc + " averaged and published : " + String(val).c_str()); - client.publish(topic, String(val).c_str(), true); - ret = true; - } else { - Serial.println("** ERROR: Value " + desc + " out of bounds, not published. Last : " + String(lastVal).c_str()); - } - lastVal = val; - } - return ret; -} - void loop() { if (!client.connected()) { - reconnect(); + reconnect(client); } client.loop(); digitalWrite(LED_BUILTIN, HIGH); @@ -172,40 +79,25 @@ void loop() { Serial.println(sensor_value); if (strcmp(sensor_name, "hmid") == 0){ - hmid = sensor_value; + hmid.value = sensor_value; } else if (strcmp(sensor_name, "temp") == 0){ - temp = sensor_value; + temp.value = sensor_value; } else if (strcmp(sensor_name, "heat") == 0){ - heat = sensor_value; + heat.value = sensor_value; } else if (strcmp(sensor_name, "airq") == 0){ - airq = sensor_value; + airq.value = sensor_value; } else{ Serial.println("ERR: Sensor could not be identified"); } - if (!isnan(hmid) && !isnan(temp) && hmid != 0.0 && temp != 0.0){ - abhu = (6.112 * ( pow(2.71828, ((17.67 * temp) / (temp + 243.5))) * hmid * 2.1674)) / (273.15 + temp); + if (!isnan(hmid.value) && !isnan(temp.value) && hmid.value != 0.0 && temp.value != 0.0){ + abhu.value = (6.112 * ( pow(2.71828, ((17.67 * temp.value) / (temp.value + 243.5))) * hmid.value * 2.1674)) / (273.15 + temp.value); } - published = false; - if (lastSent > FORCE_PERIOD) { - Serial.println(F("Forcing a publish of all values")); - forcePublish = true; - lastSent = 0; - } - - published += publish("temperature", TOPIC_TEMP, temp, temp_r, DIFF_TEMP, forcePublish); - published += publish("humidity", TOPIC_HMID, hmid, hmid_r, DIFF_HMID, forcePublish); - published += publish("heat index", TOPIC_HEAT, heat, heat_r, DIFF_HEAT, forcePublish); - published += publish("air quality", TOPIC_AIRQ, airq, airq_r, DIFF_AIRQ, forcePublish); - published += publish("absolute humidity", TOPIC_ABHU, abhu, abhu_r, DIFF_ABHU, forcePublish); - - if (published == false) { - lastSent = lastSent + 1; - } else { - lastSent = 0; - } - - forcePublish = false; + publishSensor(client, temp); + publishSensor(client, hmid); + publishSensor(client, heat); + publishSensor(client, abhu); + publishSensor(client, airq); } } diff --git a/envisens/envisens_esp_fw/sensing.cpp b/envisens/envisens_esp_fw/sensing.cpp new file mode 100644 index 0000000..066c926 --- /dev/null +++ b/envisens/envisens_esp_fw/sensing.cpp @@ -0,0 +1,110 @@ +/* ESP8266 environmental sensor project + + This file provides functions for all the sensor publication used in espsens and envisens. + + (C) 2019 Macrocell - Environmental sensing solutions + proudly presented by Macrocell - FPGA Innovators +*/ + +#include +#include "Arduino.h" +#include +#include + +#include "configuration.h" +#include "sensing.h" + +void setup_wifi() { + delay(10); + // Connect to a WiFi network + Serial.println(); + Serial.print("Connecting to "); + Serial.println(WIFI_SSID); + + WiFi.begin(WIFI_SSID, WIFI_PW); + WiFi.mode(WIFI_STA); + + // blink LED fast until WiFi is connected + while (WiFi.status() != WL_CONNECTED) { + delay(200); + digitalWrite(LED_BUILTIN, HIGH); + Serial.print("."); + delay(200); + digitalWrite(LED_BUILTIN, LOW); + } + + // WiFi connected + Serial.println(""); + Serial.println("WiFi connected"); + Serial.println("IP address: "); + Serial.println(WiFi.localIP()); +} + +void reconnect(PubSubClient client) { + // Loop until reconnected + while (!client.connected()) { + Serial.print("Attempting MQTT connection..."); + // Attempt to connect + if (client.connect(MQTT_CLIENT, MQTT_USER, MQTT_PW)) { + Serial.println("connected"); + } else { + Serial.print("failed, rc="); + Serial.print(client.state()); + Serial.println(" try again in 5 seconds"); + digitalWrite(LED_BUILTIN, HIGH); + // Wait 5 seconds before retrying + delay(4000); + digitalWrite(LED_BUILTIN, LOW); + delay(1000); + } + } +} + +bool checkVariation(float newValue, float prevValue, float maxDiff) { + return !isnan(newValue) && + (newValue < prevValue - maxDiff || newValue > prevValue + maxDiff); +} + +bool checkPlausibility(float newValue, float prevValue, float maxDiff) { + return (newValue < prevValue + (maxDiff * 10) || newValue > prevValue - (maxDiff * 10)); +} + +void publishSensor (PubSubClient &client, Sensor &sensor){ + bool force = false; + Serial.print("Sample " + sensor.desc + " : "); + Serial.print(String(sensor.value).c_str()); + Serial.print(" last : "); + Serial.print(String(sensor.lastValue).c_str()); + Serial.print(" samples since last update : "); + Serial.println(String(sensor.lastUpdate).c_str()); + + // check if first sample, set lastValue and return + if (sensor.lastUpdate == -1){ + sensor.lastValue = sensor.value; + sensor.lastUpdate = 0; + return; + } + + // force an update if the number of samples without update is exceeded + force = sensor.lastUpdate >= FORCE_PERIOD; + if (force) { + Serial.println(" * Forcing publication if sensor value is plausible"); + } + + // update the sample counter, will be reset if sample is published + sensor.lastUpdate += 1; + + // check if there was sufficient variation on the signal and if the value is plausible + if (checkVariation(sensor.value, sensor.lastValue, sensor.diff) or force) { + Serial.println(" Sufficient variation on " + sensor.desc + ": " + String(sensor.value).c_str()); + if (checkPlausibility(sensor.value, sensor.lastValue, sensor.diff)) { + Serial.println(" Value published"); + client.publish(sensor.topic, String(sensor.value).c_str(), true); + sensor.lastUpdate = 0; + } else { + Serial.print(" ** ERROR: Value out of bounds, not published. Last value :"); + Serial.println(String(sensor.lastValue).c_str()); + } + sensor.lastValue = sensor.value; + } +} diff --git a/envisens/envisens_esp_fw/sensing.h b/envisens/envisens_esp_fw/sensing.h new file mode 100644 index 0000000..6c9df54 --- /dev/null +++ b/envisens/envisens_esp_fw/sensing.h @@ -0,0 +1,35 @@ +/* ESP8266 environmental sensor project + + This file provides functions for all the sensor publication used in espsens and envisens. + + (C) 2019 Macrocell - Environmental sensing solutions + proudly presented by Macrocell - FPGA Innovators +*/ +#define TOPIC_BASE "sensor/" SENSOR_ID "/" +#define TOPIC_TEMP TOPIC_BASE "temperature" +#define TOPIC_HMID TOPIC_BASE "humidity" +#define TOPIC_ABHU TOPIC_BASE "abs_humidity" +#define TOPIC_HEAT TOPIC_BASE "heat_index" +#define TOPIC_AIRQ TOPIC_BASE "air_gas" + +#define DIFF_TEMP 0.3 // sensor has only 0.5°C accuracy, triggering on less is ludicrous +#define DIFF_HMID 1.5 // humidity doesn't change that much anyways +#define DIFF_ABHU 0.4 // small changes mean quite something +#define DIFF_HEAT 0.4 // this one's actually quite active +#define DIFF_AIRQ 5 // this one changes in integers + +#define DHTPIN 4 // Digital pin connected to the DHT sensor +#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 + +struct Sensor { + String desc; // sensor description + char* topic; // sensor topic + float diff; // value difference for an update + float value; // current values + float lastValue; // value at last update + int lastUpdate; // number of samples since last update +}; + +void setup_wifi(); +void reconnect(PubSubClient client); +void publishSensor (PubSubClient &client, Sensor &sensor);