Last active
February 20, 2023 14:56
-
-
Save ItKindaWorks/ab4d85bc1ea77c1ff20a46b5dc2a2746 to your computer and use it in GitHub Desktop.
A simple arduino and ESP8266 program to read and average 2 current transformers and a voltage transformer for monitoring whole house power usage.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
powerMonitorArd.ino | |
Copyright (c) 2017 ItKindaWorks All right reserved. | |
github.com/ItKindaWorks | |
powerMonitorArd.ino is free software: you can redistribute it and/or modify | |
it under the terms of the GNU General Public License as published by | |
the Free Software Foundation, either version 3 of the License, or | |
(at your option) any later version. | |
powerMonitorArd.ino is distributed in the hope that it will be useful, | |
but WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
GNU General Public License for more details. | |
You should have received a copy of the GNU General Public License | |
along with powerMonitorArd.ino. If not, see <http://www.gnu.org/licenses/>. | |
*/ | |
#include "EmonLib.h" | |
#define SAMPLE_COUNT 5 | |
#define VOLT_CAL 148.7 //voltage calibration | |
#define CURRENT_CAL1 62.6 //sensor 1 calibration | |
#define CURRENT_CAL2 62.8 //sensor 2 calibration | |
//create 2 instances of the energy monitor lib | |
EnergyMonitor emon1; | |
EnergyMonitor emon2; | |
//arrays to hold the sample data | |
double volts1[SAMPLE_COUNT]; | |
double amps1[SAMPLE_COUNT]; | |
double watts1[SAMPLE_COUNT]; | |
double volts2[SAMPLE_COUNT]; | |
double amps2[SAMPLE_COUNT]; | |
double watts2[SAMPLE_COUNT]; | |
const int currentPin1 = 2; | |
const int currentPin2 = 1; | |
const int voltagePin = 3; | |
//counter to keep track of the current sample location | |
int counter = 0; | |
void setup() | |
{ | |
Serial.begin(115200); | |
Serial1.begin(115200); | |
emon1.voltage(voltagePin, VOLT_CAL, 1.7); // Voltage: input pin, calibration, phase_shift | |
emon1.current(currentPin1, CURRENT_CAL1); // Current: input pin, calibration. | |
emon2.voltage(voltagePin, VOLT_CAL, 1.7); // Voltage: input pin, calibration, phase_shift | |
emon2.current(currentPin2, CURRENT_CAL2); // Current: input pin, calibration. | |
} | |
void loop() | |
{ | |
//reset the var that keeps track of the number of samples taken | |
//(loop back around to 0 on the array for our running total) | |
if(counter >= SAMPLE_COUNT){ | |
counter = 0; | |
} | |
//calculate the most recent readings | |
emon1.calcVI(20,5000); | |
emon2.calcVI(20,5000); | |
//save the voltage, current, watts to the array for later averaging | |
amps1[counter] = emon1.Irms; | |
volts1[counter] = emon1.Vrms; | |
watts1[counter] = emon1.Vrms * emon1.Irms; | |
amps2[counter] = emon2.Irms; | |
volts2[counter] = emon2.Vrms; | |
watts2[counter] = emon2.Vrms * emon2.Irms; | |
counter++; | |
//setup the vars to be averaged | |
double wattAvg1 = 0; | |
double voltAvg1 = 0; | |
double ampAvg1 = 0; | |
double wattAvg2 = 0; | |
double voltAvg2 = 0; | |
double ampAvg2 = 0; | |
//add em up for averaging | |
for(int i = 0; i < SAMPLE_COUNT; i++){ | |
wattAvg1 += watts1[i]; | |
voltAvg1 += volts1[i]; | |
ampAvg1 += amps1[i]; | |
wattAvg2 += watts2[i]; | |
voltAvg2 += volts2[i]; | |
ampAvg2 += amps2[i]; | |
} | |
//get the final average by dividing by the # of samples | |
wattAvg1 /= SAMPLE_COUNT; | |
ampAvg1 /= SAMPLE_COUNT; | |
voltAvg1 /= SAMPLE_COUNT; | |
wattAvg2 /= SAMPLE_COUNT; | |
ampAvg2 /= SAMPLE_COUNT; | |
voltAvg2 /= SAMPLE_COUNT; | |
//calculate the total amps and watts | |
double totalAmp = ampAvg1 + ampAvg2; | |
double totalWatt = wattAvg1 + wattAvg2; | |
//send the power info to the ESP module through Serial1 | |
sendPowerInfo (voltAvg1, totalAmp, totalWatt); | |
} | |
//send the power info to the ESP module through Serial1 (comma separated and starting with *) | |
void sendPowerInfo(double Volts, double Amps, double Watts){ | |
Serial1.print("*"); | |
Serial1.print(Volts); | |
Serial1.print(","); | |
Serial1.print(Amps); | |
Serial1.print(","); | |
Serial1.println(Watts); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
powerMonitorESP.ino | |
Copyright (c) 2017 ItKindaWorks All right reserved. | |
github.com/ItKindaWorks | |
powerMonitorESP.ino is free software: you can redistribute it and/or modify | |
it under the terms of the GNU General Public License as published by | |
the Free Software Foundation, either version 3 of the License, or | |
(at your option) any later version. | |
powerMonitorESP.ino is distributed in the hope that it will be useful, | |
but WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
GNU General Public License for more details. | |
You should have received a copy of the GNU General Public License | |
along with powerMonitorESP.ino. If not, see <http://www.gnu.org/licenses/>. | |
*/ | |
#include "ESPHelper.h" | |
#include <Metro.h> | |
#define AVG_COUNT 50 | |
const char* voltTopic = "/yourTopic/volt"; | |
const char* ampTopic = "/yourTopic/amp"; | |
const char* wattTopic = "/yourTopic/watt"; | |
const char* hostnameStr = "PWR-Node"; | |
const char* otaPass = "Your OTA Password"; | |
netInfo homeNet = { .mqttHost = "YOUR MQTT-IP", //can be blank if not using MQTT | |
.mqttUser = "YOUR MQTT USERNAME", //can be blank | |
.mqttPass = "YOUR MQTT PASSWORD", //can be blank | |
.mqttPort = 1883, //default port for MQTT is 1883 - only chance if needed. | |
.ssid = "YOUR SSID", | |
.pass = "YOUR NETWORK PASS"}; | |
ESPHelper myESP(&homeNet); | |
Metro powerMetro = Metro(30000); | |
void setup() { | |
Serial.begin(115200); | |
myESP.OTA_enable(); | |
myESP.OTA_setPassword(otaPass); | |
myESP.OTA_setHostnameWithVersion(hostnameStr); | |
myESP.setHopping(false); | |
myESP.begin(); | |
} | |
void loop(){ | |
int count = 0; | |
//where to store the data to be averaged | |
double watts[AVG_COUNT]; | |
double volts[AVG_COUNT]; | |
double amps[AVG_COUNT]; | |
//vars to maintain averages for all data points | |
double wattAvg = 0; | |
double voltAvg = 0; | |
double ampAvg = 0; | |
//the serial buffer of 64 bytes | |
char serialBuf[64]; | |
while(1){ | |
//reset the count when we hit the max. The average acts and a rolling average | |
if(count >= AVG_COUNT){ | |
count = 0; | |
} | |
//get data from serial line | |
while(Serial.available()){ | |
// '*' marks the beginning of a transmission | |
bool start = Serial.find('*'); | |
//parse out the floats | |
if(start){ | |
volts[count] = Serial.parseFloat(); | |
amps[count] = Serial.parseFloat(); | |
watts[count++] = Serial.parseFloat(); | |
break; | |
} | |
delay(1); | |
} | |
//calculate averages | |
wattAvg = 0; | |
ampAvg = 0; | |
voltAvg = 0; | |
for(int i = 0; i < AVG_COUNT; i++){ | |
wattAvg += watts[i]; | |
voltAvg += volts[i]; | |
ampAvg += amps[i]; | |
} | |
wattAvg /= AVG_COUNT; | |
ampAvg /= AVG_COUNT; | |
voltAvg /= AVG_COUNT; | |
//only send the data every so often (set by the metro timer) and only when connected to WiFi and MQTT | |
if(myESP.loop() == FULL_CONNECTION && powerMetro.check()){ | |
//post just watts | |
char wattStr[10]; | |
dtostrf(wattAvg,4,1,wattStr); | |
myESP.publish(wattTopic,wattStr, true); | |
delay(5); | |
//post just volts | |
char voltStr[10]; | |
dtostrf(voltAvg,4,1,voltStr); | |
myESP.publish(voltTopic,voltStr, true); | |
delay(5); | |
//post just amps | |
char ampStr[10]; | |
dtostrf(ampAvg,4,1,ampStr); | |
myESP.publish(ampTopic,ampStr, true); | |
delay(5); | |
} | |
yield(); | |
} | |
} | |
void callback(char* topic, uint8_t* payload, unsigned int length) { | |
} | |
Hey Guys, I am unable to use ESPHelper.h and Metro.h libraries for my esp32 and esp8266, please can you help me to figure out this problem...
I have one esp32 (Wroom-32) and esp8266MOD (Powered by Model vendor).
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I have made some changes to the code.... Please check it out.
The data which I send had to be converted to a JSON and sent.
Check the whole code, the bottom part