TKK_E32210697/pzem004t.ino

233 lines
7.2 KiB
C++

#include <ThingerESP8266.h> // Library Thinger.io untuk ESP8266
#include <PZEM004Tv30.h> // Library untuk sensor PZEM004Tv30
#include <WiFiManager.h> // Library WiFiManager untuk manajemen koneksi Wi-Fi
#include <NTPClient.h> // Library NTPClient untuk sinkronisasi waktu
#include <WiFiUdp.h> // Library WiFiUDP untuk komunikasi UDP
#include <EEPROM.h> // Library EEPROM untuk penyimpanan data
#define USERNAME "wahyuee" // Username Thinger.io
#define DEVICE_ID "NodeMCU_PZEM" // ID perangkat Thinger.io
#define DEVICE_CREDENTIAL "abogoboga" // Kredensial perangkat Thinger.io
ThingerESP8266 thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL); // Objek ThingerESP8266 untuk menghubungkan ke Thinger.io
// Pin yang terhubung ke relay 4 channel
const int relay1 = D0;
const int relay2 = D1;
const int relay3 = D3;
const int relay4 = D4;
const int buzzerPin = D2; // Pin buzzer
PZEM004Tv30 pzem(14, 12); // GPIO14(D5) ke Tx PZEM004; GPIO12(D6) ke Rx PZEM004
// Variabel untuk menyimpan data sensor
float Voltage, Current, Power, Energy, Frequency, PF, VA, VAR, totalCost;
bool relay1State = LOW; // Relay1 awalnya dalam keadaan hidup
unsigned long relayOffTime = 0; // Waktu saat relay1 dimatikan
const float tariffPerKWh = 1352.0; // Tarif per kWh
unsigned long startTime = 0; // Waktu awal
WiFiUDP ntpUDP; // Objek WiFiUDP untuk komunikasi NTP
NTPClient timeClient(ntpUDP, "pool.ntp.org", 0, 60000); // Klien NTP untuk sinkronisasi waktu, update setiap menit
const int EEPROM_SIZE = 10; // Ukuran EEPROM
const int EEPROM_ADDR = 0; // Alamat EEPROM untuk penyimpanan data
void setup() {
WiFi.mode(WIFI_STA); // Mengatur mode WiFi menjadi station
Serial.begin(115200); // Memulai komunikasi serial dengan baud rate 115200
WiFiManager wm; // Objek WiFiManager untuk manajemen koneksi Wi-Fi
wm.resetSettings(); // Mereset pengaturan WiFiManager
startTime = millis(); // Mendapatkan waktu awal dalam milidetik
// Mengatur pin relay dan buzzer sebagai output
pinMode(relay1, OUTPUT);
pinMode(relay2, OUTPUT);
pinMode(relay3, OUTPUT);
pinMode(relay4, OUTPUT);
pinMode(buzzerPin, OUTPUT);
bool res;
// Menghubungkan ke Wi-Fi dengan WiFiManager
res = wm.autoConnect("AutoConnectAP", "password");
if (!res) {
Serial.println("Failed to connect");
} else {
Serial.println("connected... :)");
}
thing.add_wifi(WiFi.SSID().c_str(), WiFi.psk().c_str()); // Menambahkan koneksi Wi-Fi ke Thinger.io
// Mendefinisikan endpoint untuk data sensor pada Thinger.io
thing["PZEM"] >> [] (pson & out) {
out["voltage"] = String(Voltage, 2);
out["current"] = String(Current, 2);
out["power"] = String(Power, 2);
out["energy"] = String(Energy, 3);
out["frequency"] = String(Frequency, 2);
out["faktor daya"] = String(PF, 2);
out["Apparent Power"] = String(VA, 2);
out["Reactive Power"] = String(VAR, 2);
out["Total Biaya"] = String(totalCost, 2);
};
// Mendefinisikan endpoint untuk setiap relay pada Thinger.io
thing["Perangkat 1"] << digitalPin(relay1);
thing["Perangkat 2"] << digitalPin(relay2);
thing["Perangkat 3"] << digitalPin(relay3);
thing["Perangkat 4"] << digitalPin(relay4);
timeClient.begin(); // Memulai klien NTP
EEPROM.begin(EEPROM_SIZE); // Memulai EEPROM dengan ukuran yang telah ditentukan
unsigned long lastResetTime = 0; // Waktu reset terakhir
EEPROM.get(EEPROM_ADDR, lastResetTime); // Mendapatkan waktu reset terakhir dari EEPROM
if (lastResetTime == 0) { // Jika waktu reset terakhir adalah 0
lastResetTime = timeClient.getEpochTime(); // Mengatur waktu reset terakhir dengan waktu saat ini
EEPROM.put(EEPROM_ADDR, lastResetTime); // Menyimpan waktu reset terakhir ke EEPROM
EEPROM.commit(); // Mengkomit perubahan ke EEPROM
}
}
void loop() {
thing.handle(); // Menghandle koneksi dan komunikasi dengan Thinger.io
timeClient.update(); // Mengupdate waktu dari NTP
// Membaca data dari sensor PZEM-004T
Voltage = pzem.voltage();
Current = pzem.current();
Power = pzem.power();
Energy = pzem.energy();
Frequency = pzem.frequency();
PF = pzem.pf();
// Menghitung Apparent Power (VA)
if (PF == 0) {
VA = 0;
} else {
VA = Power / PF;
}
// Menghitung Reactive Power (VAR)
if (PF == 0) {
VAR = 0;
} else {
VAR = Power / PF * sqrt(1 - sq(PF));
}
totalCost = Energy * tariffPerKWh; // Menghitung total biaya berdasarkan energi dan tarif
// Memeriksa validitas data dan menampilkan nilai-nilai pada Serial console
if (isnan(Voltage)) {
Serial.println("Error membaca tegangan");
} else {
Serial.print("Voltage : ");
Serial.print(Voltage);
Serial.println("V");
}
if (isnan(Current)) {
Serial.println("Error membaca arus");
} else {
Serial.print("Current : ");
Serial.print(Current);
Serial.println("A");
}
if (isnan(Power)) {
Serial.println("Error membaca daya");
} else {
Serial.print("Power : ");
Serial.print(Power);
Serial.println("W");
}
if (isnan(Frequency)) {
Serial.println("Error membaca frekuensi");
} else {
Serial.print("Frequency : ");
Serial.print(Frequency);
Serial.println("Hz");
}
if (isnan(PF)) {
Serial.println("Error membaca faktor daya");
} else {
Serial.print("Faktor Daya : ");
Serial.print(PF);
Serial.println("PF");
}
if (isnan(VA)) {
Serial.println("Error membaca apparent power");
} else {
Serial.print("Apparent Power : ");
Serial.print(VA);
Serial.println("VA");
}
if (isnan(VAR)) {
Serial.println("Error membaca reactive power");
} else {
Serial.print("Reactive Power : ");
Serial.print(VAR);
Serial.println("VAR");
}
if (isnan(Energy)) {
Serial.println("Error membaca energi");
} else {
Serial.print("Energy : ");
Serial.print(Energy, 3);
Serial.println("kWh");
}
if (isnan(totalCost)) {
Serial.println("Error menghitung biaya");
} else {
Serial.print("Total Biaya: ");
Serial.println(totalCost);
}
// Mengaktifkan buzzer jika Apparent Power dalam rentang 90-100 VA
if (VA >= 90 && VA <= 100) {
digitalWrite(buzzerPin, HIGH);
delay(1000);
digitalWrite(buzzerPin, LOW);
delay(1000);
thing.call_endpoint("monitor_listrik"); // Memanggil endpoint yang telah dibuat
} else {
digitalWrite(buzzerPin, LOW);
}
// Jika Apparent Power lebih dari 100 VA, matikan relay1
if (VA > 100) {
if (relay1State == LOW) {
digitalWrite(relay1, HIGH);
relay1State = HIGH;
relayOffTime = millis(); // Mengatur waktu saat relay1 dimatikan
thing.call_endpoint("monitor_listrik1"); // Memanggil endpoint yang telah dibuat
}
} else {
if (relay1State == HIGH && millis() - relayOffTime >= 120000) { // Periksa apakah sudah 2 menit berlalu
digitalWrite(relay1, LOW);
relay1State = LOW;
}
}
// Mengecek apakah sudah 30 hari berlalu dan mereset energi jika ya
unsigned long currentTime = timeClient.getEpochTime();
unsigned long lastResetTime;
EEPROM.get(EEPROM_ADDR, lastResetTime);
if (currentTime - lastResetTime >= 2592000) { // 30 hari = 2592000 detik
pzem.resetEnergy(); // Mereset energi pada sensor PZEM
EEPROM.put(EEPROM_ADDR, currentTime); // Menyimpan waktu reset terakhir ke EEPROM
EEPROM.commit(); // Mengkomit perubahan ke EEPROM
}
Serial.println();
delay(1000);
}