2021-09-01 15:46:20 +02:00

156 lines
3.9 KiB
C++

#include <Arduino.h>
#include "EmonLib.h"
#include "WiFi.h"
#include <driver/adc.h>
#include <PubSubClient.h>
// This is the device name as defined on AWS IOT
#define DEVICE_NAME "xd-home-energy-monitor-1"
// The GPIO pin were the CT sensor is connected to (should be an ADC input)
#define ADC_INPUT 34
// The voltage in our apartment. Usually this is 230V for Europe, 110V for US.
// Ours is higher because the building has its own high voltage cabin.
#define HOME_VOLTAGE 110.0
// Force EmonLib to use 10bit ADC resolution
#define ADC_BITS 10
#define ADC_COUNTS (1<<ADC_BITS)
// Create instances
EnergyMonitor emon1;
// Wifi credentials
const char *WIFI_SSID = "Xiaomi_Router";
const char *WIFI_PASSWORD = "UYQQMTHF";
const char* mqtt_server = "m21.cloudmqtt.com";
WiFiClient lolinClient;
PubSubClient client(lolinClient);
char message_buff[100];
// Array to store 30 readings (and then transmit in one-go to AWS)
short measurements[30];
short measureIndex = 0;
unsigned long lastMeasurement = 0;
unsigned long timeFinishedSetup = 0;
void setup()
{
Serial.begin(115200);
adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_DB_11);
analogReadResolution(10);
connectToWiFi();
// Initialize emon library (30 = calibration number)
emon1.current(ADC_INPUT, 30);
timeFinishedSetup = millis();
client.setServer(mqtt_server, 18932);
}
void connectToWiFi() {
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
// Only try 15 times to connect to the WiFi
int retries = 0;
while (WiFi.status() != WL_CONNECTED && retries < 15) {
delay(500);
Serial.print(".");
retries++;
}
// If we still couldn't connect to the WiFi, go to deep sleep for a
// minute and try again.
if (WiFi.status() != WL_CONNECTED) {
esp_sleep_enable_timer_wakeup(1 * 60L * 1000000L);
esp_deep_sleep_start();
}
// If we get here, print the IP address on the LCD
Serial.println(WiFi.localIP());
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect("LolinClient-EnergyMonitor", "oilkfgjy", "lEyZb90q49Rf")) {
Serial.println("connected");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
unsigned long currentMillis = millis();
// If it's been longer then 1000ms since we took a measurement, take one now!
if (currentMillis - lastMeasurement > 1000) {
double amps = emon1.calcIrms(1480); // Calculate Irms only
double watt = amps * HOME_VOLTAGE;
if(watt > 45) {
Serial.print("watt optimized: ");
Serial.println(watt*1.35);
}
// Update the display
Serial.print("watt: ");
Serial.println(watt);
Serial.print("amps: ");
Serial.println(amps);
String toSend = "WO: " + String(watt*1.35) + ", W: " + String(watt) + ", A: " + String(amps);
toSend.toCharArray(message_buff, toSend.length()+1);
client.publish("Energy", message_buff);
lastMeasurement = millis();
// Readings are unstable the first 5 seconds when the device powers on
// so ignore them until they stabilise.
if (millis() - timeFinishedSetup < 10000) {
Serial.println("Startup mode ");
} else {
Serial.println(WiFi.localIP());
measurements[measureIndex] = watt;
measureIndex++;
}
}
// When we have 30 measurements, send them to AWS!
if (measureIndex == 30) {
Serial.println("we have 30 measurements ");
// Construct the JSON to send to AWS
String msg = "{\"readings\": [";
for (short i = 0; i <= 28; i++) {
msg += measurements[i];
msg += ",";
}
msg += measurements[29];
msg += "]}";
Serial.println("Message is ready : " + msg);
measureIndex = 0;
}
}