From d5e0be2f94211015da625e868a3711db092ad2c7 Mon Sep 17 00:00:00 2001 From: bzi Date: Thu, 21 Feb 2019 23:03:40 +0100 Subject: [PATCH] Prepare AVR and ESP FW for EnviSens --- envisens/atmega_fw/atmega_fw.ino | 31 ++- envisens/esp_sensor_firmware/.gitignore | 1 + .../configuration.h.example | 26 +++ .../esp_sensor_firmware.ino | 181 ++++++++++++++++++ 4 files changed, 238 insertions(+), 1 deletion(-) create mode 100644 envisens/esp_sensor_firmware/.gitignore create mode 100644 envisens/esp_sensor_firmware/configuration.h.example create mode 100644 envisens/esp_sensor_firmware/esp_sensor_firmware.ino diff --git a/envisens/atmega_fw/atmega_fw.ino b/envisens/atmega_fw/atmega_fw.ino index 07b81d6..37d1bfc 100644 --- a/envisens/atmega_fw/atmega_fw.ino +++ b/envisens/atmega_fw/atmega_fw.ino @@ -26,6 +26,13 @@ float hmid = 0; // humidity float temp = 0; // temperature float heat = 0; // heat index float airq = 0; // air quality / gas + +#define NUM_SENSORS 4 +float sensor_values[NUM_SENSORS]; +char sensor_names[NUM_SENSORS][5] = {"hmid", "temp", "heat", "airq"}; +int current_value_index = 0; + +volatile byte* float_ptr; void setup() { Serial.begin(SERIAL_BAUDRATE); @@ -38,7 +45,23 @@ void setup() { } void requestEvent() { - Wire.write("he1234"); + byte i2c_data[8]; + float_ptr = (byte*) &sensor_values[current_value_index]; + i2c_data[0] = byte(sensor_names[current_value_index][0]); + i2c_data[1] = byte(sensor_names[current_value_index][1]); + i2c_data[2] = byte(sensor_names[current_value_index][2]); + i2c_data[3] = byte(sensor_names[current_value_index][3]); + i2c_data[4] = float_ptr[0]; + i2c_data[5] = float_ptr[1]; + i2c_data[6] = float_ptr[2]; + i2c_data[7] = float_ptr[3]; + + Wire.write(i2c_data, 8); + if (current_value_index < NUM_SENSORS - 1) { + current_value_index ++; + } else { + current_value_index = 0; + } } void loop() { @@ -70,5 +93,11 @@ void loop() { Serial.print("AirQuality: "); Serial.print(airq); Serial.println(" PPM"); + + // set the sensor values for global access + sensor_values[0] = hmid; + sensor_values[1] = temp; + sensor_values[2] = heat; + sensor_values[3] = airq; } } diff --git a/envisens/esp_sensor_firmware/.gitignore b/envisens/esp_sensor_firmware/.gitignore new file mode 100644 index 0000000..32d5f83 --- /dev/null +++ b/envisens/esp_sensor_firmware/.gitignore @@ -0,0 +1 @@ +configuration.h diff --git a/envisens/esp_sensor_firmware/configuration.h.example b/envisens/esp_sensor_firmware/configuration.h.example new file mode 100644 index 0000000..73bb3ee --- /dev/null +++ b/envisens/esp_sensor_firmware/configuration.h.example @@ -0,0 +1,26 @@ +/* ESP8266 environmental sensor project + + This header provides the necessary credentials for the esp_sensor_firmware.ino file. + Before compilation, add your credentials and remove the .example postfix from the filename. + * ** WARNING ** DO NOT COMMIT YOUR configuration.h FILE CONTAINING YOUR ACTUAL CREDENTIALS. + + (C) 2019 Macrocell - Environmental sensing solutions + proudly presented by Macrocell - FPGA Innovators +*/ + +#define sensor_id "YOUR_SENSOR_ID" + +#define wifi_ssid "YOUR_SSID" +#define wifi_password "YOUR_WIFI_PW" + +#define mqtt_server "192.168.x.x" +#define mqtt_port 1883 +#define mqtt_user "YOUR_MQTT_USER" +#define mqtt_password "YOUR_MQTT_PW" +#define mqtt_client "ESP8266Client." sensor_id + +#define OPERATION_BLINK_EN true // blink continuously if in correct operation +#define OPERATION_PERIOD 5000 // sensor reading period in milliseconds +#define FORCE_PERIOD 12 // sensor reading publication force period in number of readings without publication + +#define SERIAL_BAUDRATE 115200 diff --git a/envisens/esp_sensor_firmware/esp_sensor_firmware.ino b/envisens/esp_sensor_firmware/esp_sensor_firmware.ino new file mode 100644 index 0000000..fa2e146 --- /dev/null +++ b/envisens/esp_sensor_firmware/esp_sensor_firmware.ino @@ -0,0 +1,181 @@ +/* Macrocell environmental sensor project EnviSens + * + * This firmware provides features to use the NodeMCU ESP12 unit as an environmental sensor broker. + * It currently collects all the sensor information via I2C from a connected ATMEGA. + * + * (C) 2019 Macrocell - Environmental sensing solutions + * proudly presented by Macrocell - FPGA Innovators + */ + +#include +#include +#include +#include "DHT.h" +#include "mqtt_credentials.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_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 2.5 // humidity doesn't change that much anyways +#define DIFF_HEAT 0.2 // this one's actually quite active +#define DIFF_AIRQ 5 + +float hmid = 0; // humidity +float hmid_r = 0; // 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 + +char data[8]; +char sensor_name[5]; +float sensor_value; + +WiFiClient espClient; +PubSubClient client(espClient); + +void setup() { + Serial.begin(SERIAL_BAUDRATE); + pinMode(LED_BUILTIN, OUTPUT); + digitalWrite(LED_BUILTIN, LOW); + setup_wifi(); + 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 checkBound(float newValue, float prevValue, float maxDiff) { + return !isnan(newValue) && + (newValue < prevValue - maxDiff || newValue > prevValue + maxDiff); +} + +long lastMsg = 0; +long lastSent = 0; +bool published = false; +bool forcePublish = false; + +bool publish (String desc, char *topic, float val, float &val_r, int diff, bool force){ + if (checkBound(val, val_r, 0.3) or force) { + val_r = val; + Serial.print("New " + desc + ": "); + Serial.println(String(val).c_str()); + client.publish(topic, String(val).c_str(), true); + return true; + } else { + return false; + } +} + +void loop() { + if (!client.connected()) { + reconnect(); + } + client.loop(); + digitalWrite(LED_BUILTIN, HIGH); + + long now = millis(); + if (now - lastMsg > OPERATION_PERIOD / 2) { + if (OPERATION_BLINK_EN) {digitalWrite(LED_BUILTIN, LOW);} + } + if (now - lastMsg > OPERATION_PERIOD) { + lastMsg = now; + if (OPERATION_BLINK_EN) {digitalWrite(LED_BUILTIN, HIGH);} + + Wire.requestFrom(8, 8); // request 6 bytes from slave device #8 + int i = 0; + while(Wire.available()) { // slave may send less than requested + char c = Wire.read(); // receive a byte as character + data[i] = byte(c); + i = i + 1; + } + + union sensor_tag {byte sensor_b[4]; float sensor_float;} sensor_union; //DRPS = Drum Revs per Second + sensor_name[0] = char(data[0]); + sensor_name[1] = char(data[1]); + sensor_name[2] = char(data[2]); + sensor_name[3] = char(data[3]); + sensor_name[4] = 0; + + sensor_union.sensor_b[0] = data[4]; + sensor_union.sensor_b[1] = data[5]; + sensor_union.sensor_b[2] = data[6]; + sensor_union.sensor_b[3] = data[7]; + sensor_value = sensor_union.sensor_float; + + Serial.print("Received: "); + Serial.print(sensor_name); + Serial.print(" - "); + Serial.println(sensor_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); + + if (published == false) { + lastSent = lastSent + 1; + } else { + lastSent = 0; + } + + forcePublish = false; + } +}