#include <WiFi.h>
#include <Wire.h> // Include Wire library for I2C communication
#include <LiquidCrystal_I2C.h> // Include the LiquidCrystal I2C library
#include <TimeLib.h> // Include the Time library
#include <time.h>
#include <ESP32Time.h>
/* WiFi credentials */
#define WIFI_SSID "LAPSPOT"
#define WIFI_PASSWORD "qwertyuiop"
#define NTP_SERVER "asia.pool.ntp.org"
#define NTP_OFFSET 14400
#define NTP_DAYLIGHT_OFFSET 0
ESP32Time timeClient(NTP_OFFSET);
unsigned long sendDataPrevMillis = 0, timeUpdatePrevMillis = 0, updatePrevMillis = 0;
#define LCD_ADDRESS 0x27 // I2C address of the LCD
#define LCD_COLUMNS 16
#define LCD_ROWS 2
// Define the LCD display
LiquidCrystal_I2C lcd(LCD_ADDRESS, LCD_COLUMNS, LCD_ROWS);
void initWifi(bool reconnect = false)
{
// LCD: Display the connection status
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Connecting WiFi");
Serial.println("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED)
{
}
// LCD: Display the IP address
lcd.clear();
lcd.setCursor(0, 0);
if (reconnect)
{
char buf[64];
sprintf(buf, "Reconnected to Wi-Fi. IP: %s", WiFi.localIP().toString().c_str());
lcd.print("WiFi Reconnected");
Serial.println("WiFi Reconnected");
Serial.println("Reconnected to Wi-Fi");
}
else
{
char buf[64];
sprintf(buf, "Connected to Wi-Fi. IP: %s", WiFi.localIP().toString().c_str());
lcd.print("WiFi Connected");
Serial.println("WiFi Connected");
Serial.println("Connected to Wi-Fi");
}
lcd.setCursor(0, 1);
lcd.print(WiFi.localIP().toString());
delay(500);
}
void initTime(bool reconnect = false)
{
if (reconnect)
{
configTime(NTP_OFFSET, NTP_DAYLIGHT_OFFSET, NTP_SERVER);
struct tm timeinfo;
if (!getLocalTime(&timeinfo))
timeClient.setTimeStruct(timeinfo);
return;
}
while (true)
{
lcd.clear();
lcd.setCursor(0, 0);
configTime(NTP_OFFSET, NTP_DAYLIGHT_OFFSET, NTP_SERVER);
struct tm timeinfo;
if (!getLocalTime(&timeinfo))
{
timeClient.setTimeStruct(timeinfo);
lcd.print("NTP Time Error");
lcd.setCursor(0, 1);
lcd.print("retrying...");
Serial.println("NTP time error");
delay(500);
continue;
}
timeUpdatePrevMillis = millis();
// Get the current time from RTC
String time_buf = timeClient.getTime("%m/%d %H:%M:%S");
lcd.print("Current Time:");
lcd.setCursor(0, 1);
lcd.print(time_buf.c_str());
Serial.printf("Current Time: %s\n", time_buf.c_str());
delay(500);
return;
}
}
TaskHandle_t uploadDataTask;
void uploadData(void *parameter)
{
while (true)
{
// Update the time every 1 minute
if (millis() - timeUpdatePrevMillis > 60000 && WiFi.status() == WL_CONNECTED)
{
timeUpdatePrevMillis = millis();
initTime(true);
Serial.println("Time updated");
}
if (millis() - sendDataPrevMillis > 2000)
{
sendDataPrevMillis = millis();
if (random(0,1))
{
lcd.setCursor(14, 1);
lcd.write(0x06);
Serial.println("Data sent to Firebase\n");
}
else
{
lcd.setCursor(14, 1);
// add a cross mark
lcd.write(0x07);
Serial.println("Failed to send data to Firebase. Retrying...\n");
}
}
}
}
void setup()
{
// Initialize serial port
Serial.begin(115200);
// Initialize LCD
lcd.init();
lcd.backlight();
// Initialize Wi-Fi
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
// Connect to Wi-Fi
initWifi();
// Initialize Time
initTime();
Serial.println("Setup done");
xTaskCreatePinnedToCore(uploadData, "Task1", 10000, NULL, 0, &uploadDataTask, 0);
lcd.clear();
}
void loop()
{
// Send data to Firebase every 1 second
if (millis() - updatePrevMillis > 500)
{
updatePrevMillis = millis();
// Read the AC voltage value
float acVoltage = zmpt.getVoltageAC(AC_FREQUENCY);
int acCurrent = analogRead(AC_PIN);
float calibrationFactor = 0.005;
float current = (acCurrent - 512) * calibrationFactor;
float power = acVoltage * current;
char power_buf[32];
String time_buf = timeClient.getTime("%m/%d %H:%M:%S");
sprintf(power_buf, "%.2fV %.2fA %.2fW", acVoltage, current);
Serial.println(power_buf);
Serial.println(time_buf.c_str());
Serial.println(timeClient.getEpoch());
// LCD: Display the current time and power consumption
lcd.setCursor(0, 0);
lcd.print(power_buf);
lcd.setCursor(0, 1);
lcd.print(time_buf.c_str());
}
}