Hello All,
This is my first post here and am looking for some help with a three phase energy meter/calculator I am working on. I have the project sort of working and visually its fine, however I need some help with how to do the calculations. what I am trying to do is take a reading of amps with a current transformer. I want to take a reading say 20 times and then calculate the average for those readings this is where I am stuck. then with those readings I want to convert it into KWH.PerKG which is not a problem. Next problem would be is it possible for me to have a permanent calculation running so I can keep updating kWh per kg without refreshing the unit? so like a live reading of Amps being converted and then the screen constantly updating with the new values? any ideas or pointers would be amazing
#if 1
#include <Adafruit_GFX.h>
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;
#include <Fonts/FreeSans9pt7b.h>
#include <Fonts/FreeSans12pt7b.h>
#include <Fonts/FreeSerif12pt7b.h>
#include <FreeDefaultFonts.h>
#include <TouchScreen.h>
#define MINPRESSURE 200
#define MAXPRESSURE 1000
const int XP=8,XM=A2,YP=A3,YM=9; //240x320 ID=0x9341
const int TS_LEFT=902,TS_RT=142,TS_TOP=93,TS_BOT=885; // done
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
Adafruit_GFX_Button on_btn, off_btn;
int pixel_x, pixel_y; //Touch_getXY() updates global vars
bool Touch_getXY(void)
{
TSPoint p = ts.getPoint();
pinMode(YP, OUTPUT); //restore shared pins
pinMode(XM, OUTPUT); //because TFT control pins
bool pressed = (p.z > MINPRESSURE && p.z < MAXPRESSURE);
if (pressed) {
pixel_x = map(p.x, TS_LEFT, TS_RT, 0, tft.width()); //.kbv makes sense to me
pixel_y = map(p.y, TS_TOP, TS_BOT, 0, tft.height());
}
return pressed;
}
#define BLACK 0x0000
#define BLUE 0x001F
#define WHITE 0xFFFF
#define NAVY 0x000F
int currentPins[3] = {10,11,12}; //Assign phase CT inputs to analog pins
double calib[3] = {11.8337,11.8234,12.0325};
double kilos[3];
unsigned long startMillis[3];
unsigned long endMillis[3];
double RMSCurrent[3];
int RMSPower[3];
int peakPower[3];
double RMSAverage;
double KWH;
double ShotWeight;
double CycleTime;
double MaterialThroughPerHr;
double KWHPerKg;
int CountAmps;
int AmpsAverage25;
int RMSAverage25;
// end of added code
void setup(void)
{
#if defined(__arm__) || defined(ESP32) //default to 12-bit ADC
analogReadResolution(10); //Adafruit TouchScreen.h expects 10-bit
#endif
Serial.begin(9600);
uint16_t ID = tft.readID();
Serial.print("TFT ID = 0x");
Serial.println(ID, HEX);
Serial.println("Calibrate for your Touch Panel");
if (ID == 0xD3D3) ID = 0x9486; // write-only shield
tft.begin(ID);
tft.setRotation(0); //PORTRAIT
tft.fillScreen(BLUE);
on_btn.initButton(&tft, 60, 290, 100, 40, WHITE, NAVY, WHITE, "KWH/KG", 2);
off_btn.initButton(&tft, 180, 290, 100, 40, WHITE, NAVY, WHITE, "AMPS", 2);
on_btn.drawButton(false);
off_btn.drawButton(false);
tft.fillRect(10, 10, 220, 240, NAVY);
showmsgXY(20,40,2.8,NULL, "H");
showmsgXY(20,65,2.8,NULL, "L");
showmsgXY(20,89,2.8,NULL, "ENERGY MONITOR");
}
void readPhase () //Method to read information from CTs
{
for(int i=0;i<=2;i++)
{
int current = 0;
int maxCurrent = 0;
int minCurrent = 1000;
for (int j=0 ; j<=200 ; j++) //Monitors and logs the current input for 200 cycles to determine max and min current
{
current = analogRead(currentPins[i]); //Reads current input and records maximum and minimum current
if(current >= maxCurrent)
maxCurrent = current;
else if(current <= minCurrent)
minCurrent = current;
}
if (maxCurrent <= 517)
{
maxCurrent = 516;
}
RMSCurrent[i] = ((maxCurrent - 516)*0.707)/calib[i]; //Calculates RMS current based on maximum value and scales according to calibration
RMSPower[i] = 220*RMSCurrent[i]; //Calculates RMS Power Assuming Voltage 220VAC, change to 110VAC accordingly
if (RMSPower[i] > peakPower[i])
{
peakPower[i] = RMSPower[i];
}
endMillis[i]= millis();
unsigned long time = (endMillis[i] - startMillis[i]);
kilos[i] = kilos[i] + (RMSPower[i] * (time/60/60/1000000)); //Calculate kilowatt hours used
startMillis[i]= millis();
RMSAverage = (RMSCurrent[0] + RMSCurrent[1] + RMSCurrent[2] /3); //calculate average of amps
KWH = (415 * RMSAverage * 0.9 * 1.732 /1000);
ShotWeight = 0.100;
CycleTime = 22;
MaterialThroughPerHr = (3600 / CycleTime * ShotWeight);
KWHPerKg = (KWH / MaterialThroughPerHr);
AmpsAverage25 = (RMSAverage25 /25);
}
}
void loop(void)
{
/*
void readPhase () //Method to read information from CTs
{
for(int i=0;i<=2;i++)
{
int current = 0;
int maxCurrent = 0;
int minCurrent = 1000;
for (int j=0 ; j<=200 ; j++) //Monitors and logs the current input for 200 cycles to determine max and min current
{
current = analogRead(currentPins[i]); //Reads current input and records maximum and minimum current
if(current >= maxCurrent)
maxCurrent = current;
else if(current <= minCurrent)
minCurrent = current;
}
if (maxCurrent <= 517)
{
maxCurrent = 516;
}
RMSCurrent[i] = ((maxCurrent - 516)*0.707)/calib[i]; //Calculates RMS current based on maximum value and scales according to calibration
RMSPower[i] = 220*RMSCurrent[i]; //Calculates RMS Power Assuming Voltage 220VAC, change to 110VAC accordingly
if (RMSPower[i] > peakPower[i])
{
peakPower[i] = RMSPower[i];
}
endMillis[i]= millis();
unsigned long time = (endMillis[i] - startMillis[i]);
kilos[i] = kilos[i] + (RMSPower[i] * (time/60/60/1000000)); //Calculate kilowatt hours used
startMillis[i]= millis();
RMSAverage = (RMSCurrent[2] + RMSCurrent[1] + RMSCurrent[2] /3); //calculate average of amps
KWH = (415 * RMSAverage * 0.9 * 1.732 /1000);
ShotWeight = 0.100;
CycleTime = 22;
MaterialThroughPerHr = (3600 / CycleTime * ShotWeight);
KWHPerKg = (KWH / MaterialThroughPerHr);
}
} */
//////
bool down = Touch_getXY();
on_btn.press(down && on_btn.contains(pixel_x, pixel_y));
off_btn.press(down && off_btn.contains(pixel_x, pixel_y));
if (on_btn.justReleased())
on_btn.drawButton();
if (off_btn.justReleased())
off_btn.drawButton();
if (on_btn.justPressed()) {
on_btn.drawButton(true);
tft.fillRect(10, 10, 220, 240, NAVY);
// showmsgXY(20, 40, 3, NULL, "KWH PER KG");
showmsgXY(20, 65, 3, NULL, "");
displayKWHPerKg (10, 110, 2, NULL, "");
}
if (off_btn.justPressed()) {
off_btn.drawButton(true);
tft.fillRect(0, 5, 240, 245, NAVY);
// showmsgXY(20,40,3,NULL, "PHASE1=0.0");
// showmsgXY(20,73,3,NULL, "PHASE2=0.0");
showmsgXY(20,105,3,NULL, "");
//showmsgXY(20,180,3,NULL, "TOTAL AMPS");
//showmsgXY(20,205,3,NULL, "0.0");
for (CountAmps; CountAmps <= 25; CountAmps++)
{
// for (Count2; Count2 <= 25; Count2++)
tft.fillRect(0, 5, 240, 245, NAVY);
tft.setTextColor(WHITE);
readPhase();
displayCurrent0 (10,40,2,NULL,"");
displayCurrent1 (10,80,2,NULL,"");
displayCurrent2 (10,115,2,NULL,"");
displayCurrentAverage (10,160,3,NULL,"");
delay(1000);
tft.fillRect(0, 5, 240, 245, NAVY);
readPhase();
displayCurrent0 (10,40,2,NULL,"");
displayCurrent1 (10,80,2,NULL,"");
displayCurrent2 (10,115,2,NULL,"");
displayCurrentAverage (10,160,3,NULL,"");
tft.setTextColor(NAVY);
delay(1000);
}
AverageOverAll (10,190,3,NULL,"");
}
}
#endif
void showmsgXY(int x, int y, int sz, const GFXfont *f, const char *msg)
{
int16_t x1, y1;
uint16_t wid, ht;
//tft.drawFastHLine(0, y, tft.width(), WHITE);
tft.setFont(f);
tft.setCursor(x, y);
tft.setTextColor(WHITE);
tft.setTextSize(sz);
tft.print(msg);
delay(1000);
}
void displayCurrent0(int x, int y, int sz, const GFXfont *f, const char *msg) //Displays all current data
{
// tft.setCursor(x,y);
//for (CountAmps; CountAmps <= 25; CountAmps++)
tft.setCursor(x,y);
tft.print(RMSCurrent[0]);
tft.print("A PH1");
}
void displayCurrent1(int x, int y, int sz, const GFXfont *f, const char *msg) //Displays all current data
{
tft.setCursor(x,y);
tft.print(RMSCurrent[1]);
tft.print("A PH2");
}
void displayCurrent2(int x, int y, int sz, const GFXfont *f, const char *msg) //Displays all current data
{
tft.setCursor(x,y);
tft.print(RMSCurrent[2]);
tft.print("A PH3");
}
void displayCurrentAverage(int x, int y, int sz, const GFXfont *f, const char *msg) //Displays all current data
{
tft.setCursor(x,y);
tft.print(RMSAverage);
tft.print("A Avg");
RMSAverage25 = (RMSAverage25 + 1);
}
void AverageOverAll(int x, int y, int sz, const GFXfont *f, const char *msg) //Displays all current data
{
tft.setCursor(x,y);
tft.print(AmpsAverage25);
tft.print("A Avg");
}
void displayKWHPerKg(int x, int y, int sz, const GFXfont *f, const char *msg)
{
tft.setCursor(x,y);
tft.print(KWHPerKg);
tft.print("KWHPerKG");
}