/* Meranie spotreby el. energie pomocou kniznice od openenergymonitor.org Meranie napatia, prudu, realneho vykonu, zdanliveho vykonu, ucinnika Pripojenie LCD 16x4 HD44780 a zobrazenie udajov na nom Vypocet priemernych hodnot za 5 minut a hodinu Webserver s obvodom Wiznet W5100 Arduino NANO/UNO s ATMEGA 328 Nezabudnut spravit kalibraciu merania napatia a prudu nizsie http://www.pablox.net EmonLibrary examples openenergymonitor.org, Licence GNU GPL V3 */ #include "EmonLib.h" #include #include #include EnergyMonitor emon1; // ============ pripojenie LCD 16x4 HD44780 - RS, E, D4, D5, D6, D7 ============ LiquidCrystal lcd(2, 3, 4, 5, 6, 7); // ============ nastavenie ETHERNETU, upravit IP podla potreby alebo pouzit DHCP ============ byte mac[] = {0xFE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEF}; IPAddress ip(192,168,137,1); // pevna IP EthernetServer server(80); EthernetClient client; // ============ UPRAVIT HODNOTY TAK, ABY BOLO MERANIE SPRAVNE ============ float Ucal = 146; // kalibracia merania napatia float Ical = 19.3; // kalibracia merania prudu // popisky pre usetrenie pamate String labels[6] = {" Realny prikon: ", " Zdanlivy prikon: ", " Napatie siete: ", " Prud: ", " Ucinnik: ", "Priemerne hodnoty "} ; int minutes = 5; // pocet minut, pocas ktorych sa bude robit prve priemerovanie, v tomto pripade 5 minut int hour_cycles = 12; // pocet 5-minutovych cyklov pre hodinove priemery (5*12 = 60 minut) unsigned long previousMillis; // spracovanie casu // pomocne premenne pre vypocty hodinovych a 5-minutovych priemerov int hourCount = 0; int measCount = 0; // premenne pre meranie, priemerovanie atd. float realPower, apparentPower, powerFActor,supplyVoltage, Irms; // premenne pre aktualne hodnoty float awgRpwr,awgApwr,awgVolt,awgCurr,awgPF = 0; // priemerne hodnoty float oldawgRpwr,oldawgApwr,oldawgVolt,oldawgCurr,oldawgPF = 0; // premenne pre 5 minutove priemery float hourRealpwr, hourApppwr,hourVolt,hourCurr,hourPF = 0; // premenne pre aktualne hodinove priemery float oldhourRealpwr, oldhourApppwr,oldhourVolt,oldhourCurr,oldhourPF = 0; // premenne pre hodinove priemery // ============================================================ UVODNE NASTAVENIA =============================================================================== void setup() { Serial.begin(9600); lcd.begin(16, 4); // LCD 16x4 // nastavenie ethernet servera //Ethernet.begin(mac, ip); // staticka IP Ethernet.begin(mac); // DHCP server.begin(); Serial.print("Server je na adrese "); Serial.println(Ethernet.localIP()); emon1.voltage(2, Ucal, 1); // Meranie napatia, ADC 2 ; fazovy posun emon1.current(1, Ical); // Meranie prudu cez prudovy transformator, ADC 1 } // ========================================================== HLAVNA SLUCKA =================================================================================== void loop() { get_pwr(); // nacita aktualne hodnoty measCount += 1; // zaznamenava pocet vykonanych merani za 5 minut, aby vedel vypocitat priemerne hodnoty display_lcd(); // zobrazi udaje na LCD, podla potreby upravit zobrazenie // uklada si aktualne namerane hodnoty awgRpwr += realPower; awgApwr += apparentPower; awgVolt += supplyVoltage; awgCurr += Irms; awgPF += powerFActor; webserver(); // aktualizuje udaje na webserveri // =================================== kontroluje cas, ak uplynie 5 minut, spracuje namerane hodnoty a vypocita 5 minutove priemery ======================================== unsigned long currentMillis = millis(); if (currentMillis - previousMillis > (60000 * minutes)) { previousMillis = currentMillis; // nuluje hodnoty pred novym vypoctom oldawgRpwr = 0; oldawgApwr = 0; oldawgVolt = 0; oldawgCurr = 0; oldawgPF = 0; // vypocita a ulozi si priemerne hodnoty za 5 minut oldawgRpwr = awgRpwr / measCount; oldawgApwr = awgApwr / measCount; oldawgVolt = awgVolt / measCount; oldawgCurr = awgCurr / measCount; oldawgPF = awgPF / measCount; Serial.println("5 minutove priemery " + String(millis()/1000/60) + "min: " + String(oldawgRpwr) + " " + String(oldawgApwr) + " " + String(oldawgVolt) + " " + String(oldawgCurr) + " " + String(oldawgPF)); // vynuluje premennne pre dalsie meranie awgRpwr = 0; awgApwr = 0; awgVolt = 0; awgCurr = 0; awgPF = 0; measCount = 0; // vynuluje pocet merani vykonanych za 5 minut // spocitava si namerane 5-minutove priemery hourRealpwr += oldawgRpwr; hourApppwr += oldawgApwr; hourVolt += oldawgVolt; hourCurr += oldawgCurr; hourPF += oldawgPF; hourCount += 1; // pomocna premenna pre hodinove priemery, aby sa vedelo, ze bolo vykonane dalsie 5-minutove meranie // vynuluje premenne pre nove meranie awgRpwr = 0; awgApwr = 0; awgVolt = 0; awgCurr = 0; awgPF = 0; } // ================================================== ak ubehlo 12 5-minutovych cyklov (60 minut), vypocita hodinove priemery ================================================= if (hourCount == hour_cycles ) { // vynuluje povodne hodnoty hodinovych priemerov pre nove meranie oldhourRealpwr = 0; oldhourApppwr = 0; oldhourVolt = 0; oldhourCurr = 0; oldhourPF = 0; // vypocita a ulozi si hodinove priemery oldhourRealpwr = hourRealpwr / hour_cycles; oldhourApppwr = hourApppwr / hour_cycles; oldhourVolt = hourVolt / hour_cycles; oldhourCurr = hourCurr / hour_cycles; oldhourPF = hourPF / hour_cycles; Serial.println("Hodinove priemery " + String(millis()/1000/60) + "min: " + String(oldhourRealpwr) + " " + String(oldhourApppwr) + " " + String(oldhourVolt) + " " + String(oldhourCurr) + " " + String(oldhourPF)); // vynuluje premenne pre hodinove priemery pre dalsie meranie hourRealpwr = 0; hourApppwr = 0; hourVolt = 0; hourCurr = 0; hourPF = 0; hourCount = 0; } } // ============================================================ KONIEC ======================================================================================== void webserver() // generuje web stranku pre zobrazenie udajov { EthernetClient client = server.available(); if (client) { boolean currentLineIsBlank = true; while (client.connected()) { if (client.available()) { // send a standard http response header client.println(F("HTTP/1.1 200 OK")); client.println(F("Content-Type: text/html")); client.println(F("Connection: close")); client.println(F("Refresh: 10")); // obnovuje stranku kazdych 10s client.println(); client.println(F("")); client.println(F("")); client.println(F("

Monitorovanie spotreby el. energie

")); client.println(F("
")); client.println(F("")); client.println(F("")); client.print(F("Cas od spustenia: ")); client.print(millis()/1000/60); client.println(F(" minut")); client.println(F("
")); client.println("Aktualne hodnoty "); client.println(F("
")); client.println(F("
")); client.println(labels[0] + String(realPower) + " W"); // realny prikon client.println(F("
")); client.println(labels[1] + String(apparentPower) + " VA"); // zdanlivy prikon client.println(F("
")); client.println(labels[2] + String(supplyVoltage) + " V"); // napatie siete client.println(F("
")); client.println(labels[3] + String(Irms) + " A"); // prud client.println(F("")); client.println(F("
")); client.println(labels[4] + String(powerFActor)); // ucinnik client.println(F("
")); client.println(F("
")); client.println(labels[5] + " za poslednych 5 minut "); client.println(F("
")); client.println(F("
")); client.println(labels[0] + String(oldawgRpwr) + " W"); client.println(F("
")); client.println(labels[1] + String(oldawgApwr) + " VA"); client.println(F("
")); client.println(labels[2] + String(oldawgVolt) + " V"); client.println(F("
")); client.println(labels[3] + String(oldawgCurr) + " A"); client.println(F("")); client.println(F("
")); client.println(labels[4] + String(oldawgPF)); client.println(F("
")); client.println(F("
")); client.println(labels[5] + " za poslednu hodinu "); client.println(F("
")); client.println(F("
")); client.println(labels[0] + String(oldhourRealpwr) + " W"); client.println(F("
")); client.println(labels[1] + String(oldhourApppwr) + " VA"); client.println(F("
")); client.println(labels[2] + String(oldhourVolt) + " V"); client.println(F("
")); client.println(labels[3] + String(oldhourCurr) + " A"); client.println(F("")); client.println(F("
")); client.println(labels[4] + String(oldhourPF)); client.println(F("
")); client.println(F("")); break; } } } delay(1); // ukonci spojenie client.stop(); } // ================================== zobrazuje hodnoty na LCD, podla potreby upravit zobrazovane udaje =========================================== void display_lcd() { lcd.clear(); lcd.setCursor(0, 0); lcd.print("RePWR: "); lcd.print(String(realPower,0)); lcd.print(" W"); lcd.setCursor(0, 1); lcd.print("ApPWR: "); lcd.print(String(apparentPower,0)); lcd.print(" VA"); lcd.setCursor(0, 2); lcd.print("Volt: "); lcd.print(String(supplyVoltage,0)); lcd.print(" V"); lcd.setCursor(0, 3); lcd.print("Cur: "); lcd.print(String(Irms,1)); lcd.print("A/"); lcd.print(String(powerFActor)); } // ====================== pomocou kniznice spravi meranie hodnot a ulozi do premennych ==================== // ============ ak treba, povolit/zakazat vypisovanie na UART odkomentovanim posledneho riadku ============ void get_pwr() // { emon1.calcVI(20,2000); // Calculate all. No.of half wavelengths (crossings), time-out realPower = emon1.realPower; // realny vykon apparentPower = emon1.apparentPower; // zdanlivy vykon powerFActor = emon1.powerFactor; // ucinnik supplyVoltage = emon1.Vrms; // napajacie napatie Irms = emon1.Irms; // efektivna hodnota prudu // posiela namerane udaje na UART Serial.println(String(realPower) + "W " + String(apparentPower) + "VA " + String(supplyVoltage) + "V " + String(Irms) + "A " + String(powerFActor)); } //================================================================================================================