Current Monitoring with ESP8266 + Grafana
Here is how to setup a household power monitor using an ESP8266 module, some simple circuits and a few bits of software.
This is based off a guide from openenergymonitor.org.
https://learn.openenergymonitor.org/electricity-monitoring/ct-sensors/introduction
What you will need
- ESP8266 NodeMCU ESP-12F
- A passive Current Sensor YHDC SCT-013-000
- 2x 10 Ohm Resistors
- 2x 10K Ohm Resistors
- A 10uF capacitor
- A server/raspberry pi to host Grafana and Prometheus
The circuit diagram for this shows that we need a burden resistor to reduce the output voltage so it can be used with our module. In this case my module uses 3.3V logic levels, so using this burden calcuator the recommended Resistor size is 23 Ohms, however if you dont have the exact right one, go for a resistor smaller than the calculated one in order to prevent a higher voltage damaging your ESP module. In my case I used two 10 Ohm resistors in series to give me 20 Ohms.
We also need a voltage divider to reduce the voltage from the Current Sensor to a voltage safe for our ESP module. For this we use two 10K Ohm Resistors.
The positive lead from the current sensor does to our Analogue Input on the ESPModule, named A0 in my case.
Prototyping
I tested the circuit out in a breadboard and uploaded the code which I cobbled together attached at the end of this post.
The general idea is using the EmonLib package to pull the current sensor values and the ESP8266 example HTTP server I publish the current and power stats to the HTTP server in a format which Prometheus can scrape.
Prometheus is then configured to scrap the end point.
Grafana then integrates with Prometheus and gives us the ability to make awesome dashboards
After testing it out on the breadboard I moved the components to a protoboard.
Final Build
Code
For the below code update the SSID and PASSWORD so it can connect to your AP. There is some calibration values you can tweak if the output values don’t seem correct, please refer to OpenEnergyMonitor for more details.
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include "EmonLib.h" // Include Emon Library
#ifndef STASSID
#define STASSID "SSID"
#define STAPSK "PASSWORD"
#endif
EnergyMonitor emon1; // Create an instance
const char* ssid = STASSID;
const char* password = STAPSK;
double pwr;
double Irms;
ESP8266WebServer server(80);
void handleRoot() {
server.send(200, "text/plain", "Hello!");
}
void handleMetric() {
Irms = emon1.calcIrms(1480); // Calculate Irms only
pwr = Irms*230.0;
String powerMetric = "# HELP apparent_power The Apparent Power (VA)\napparent_power{device=\"mainspower\",location=\"home\"} " + String(pwr);
String currentMetric = "# HELP rms_current The RMS Current (A)\nrms_current{device=\"mainspower\",location=\"home\"} " + String(Irms);
Serial.println(powerMetric); // Apparent power
Serial.println(currentMetric); // Current
server.send(200, "text/plain", powerMetric + "\n"+ currentMetric);
}
void handleNotFound() {
String message = "File Not Found\n\n";
message += "URI: ";
message += server.uri();
message += "\nMethod: ";
message += (server.method() == HTTP_GET) ? "GET" : "POST";
message += "\nArguments: ";
message += server.args();
message += "\n";
for (uint8_t i = 0; i < server.args(); i++) {
message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
}
server.send(404, "text/plain", message);
}
void setup(void) {
Serial.begin(115200);
//pin 17 is A0
emon1.current(A0, 111.1); // Current: input pin, calibration.
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
if (MDNS.begin("esp8266")) {
Serial.println("MDNS responder started");
}
server.on("/", handleRoot);
server.on("/metrics", handleMetric);
server.on("/inline", []() {
server.send(200, "text/plain", "this works as well");
});
server.onNotFound(handleNotFound);
server.begin();
Serial.println("HTTP server started");
}
void loop(void) {
server.handleClient();
MDNS.update();
}