#define TINY_GSM_MODEM_SIM7600
#define TINY_GSM_RX_BUFFER 1024
#define MODEM_TX 16
#define MODEM_RX 17
#define MODEM_BAUD 115200
#include <EmonLib.h>
#include <Wire.h>
#include <RTClib.h>
#include <TinyGsmClient.h>
#include <ArduinoHttpClient.h>
// ==== EmonLib Calibration ====
#define V_CALIBRATION 106.8
#define I_CALIBRATION 0.52
#define VOLTAGE_SENSOR_PIN 35
#define CURRENT_SENSOR_PIN 34
// ==== Battery SOC (via voltage divider) ====
#define DC_VOLTAGE_PIN 39
const float R1 = 200000.0; // 200k
const float R2 = 5100.0; // 5.1k
const float ADC_REF = 3.3;
const int ADC_RESOLUTION = 4095;
// ==== Relays ====
#define LOAD_RELAY_PIN 18
#define CHARGER_RELAY_PIN 19
// ==== NTC ====
#define NTC_PIN 32
const float SERIES_RESISTOR = 10000.0; // 10k series resistor
const float NOMINAL_RESISTANCE = 10000.0; // Resistance at 25°C
const float NOMINAL_TEMPERATURE = 25.0;
const float B_COEFFICIENT = 3950.0;
// ==== RTC ====
RTC_DS3231 rtc;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
// ==== EmonLib ====
EnergyMonitor emon;
// ==== GSM ====
const char apn[] = "your_apn";
const char user[] = "";
const char pass[] = "";
HardwareSerial SerialAT(1);
TinyGsm modem(SerialAT);
TinyGsmClient client(modem);
HttpClient http(client, "your.api.server", 80); // placeholder
// ==== Helper Functions ====
float readDCVoltageIn()
{
int adcValue = analogRead(DC_VOLTAGE_PIN);
float vOut = adcValue * ADC_REF / ADC_RESOLUTION;
float vIn = vOut / (R2 / (R1 + R2));
return vIn;
}
float readNTCTemperature()
{
int adcValue = analogRead(NTC_PIN);
float voltage = adcValue * ADC_REF / ADC_RESOLUTION;
float resistance = (ADC_REF * SERIES_RESISTOR / voltage) - SERIES_RESISTOR;
float steinhart;
steinhart = resistance / NOMINAL_RESISTANCE;
steinhart = log(steinhart);
steinhart /= B_COEFFICIENT;
steinhart += 1.0 / (NOMINAL_TEMPERATURE + 273.15);
steinhart = 1.0 / steinhart;
steinhart -= 273.15;
return steinhart;
}
String getFormattedTime()
{
DateTime now = rtc.now();
String yearStr = String(now.year());
String monthStr = (now.month() < 10 ? "0" : "") + String(now.month());
String dayStr = (now.day() < 10 ? "0" : "") + String(now.day());
String hourStr = (now.hour() < 10 ? "0" : "") + String(now.hour());
String minuteStr = (now.minute() < 10 ? "0" : "") + String(now.minute());
String secondStr = (now.second() < 10 ? "0" : "") + String(now.second());
String dayOfWeek = daysOfTheWeek[now.dayOfTheWeek()];
return dayOfWeek + ", " + yearStr + "-" + monthStr + "-" + dayStr + " " + hourStr + ":" + minuteStr + ":" + secondStr;
}
void readAndPrintJSONWithTimestamp()
{
emon.calcVI(20, 2000);
float acVoltage = emon.Vrms;
float acCurrent = emon.Irms;
float acPower = emon.apparentPower;
float dcVoltage = readDCVoltageIn();
float tempC = readNTCTemperature();
String timeStr = getFormattedTime();
String jsonString = "{";
jsonString += "\"timestamp\":\"" + timeStr + "\",";
jsonString += "\"ac_voltage\":" + String(acVoltage, 2) + ",";
jsonString += "\"ac_current\":" + String(acCurrent, 4) + ",";
jsonString += "\"ac_power\":" + String(acPower, 4) + ",";
jsonString += "\"dc_voltage_in\":" + String(dcVoltage, 2) + ",";
jsonString += "\"temperature_c\":" + String(tempC, 2);
jsonString += "}";
Serial.println(jsonString);
// sendDataToServer(jsonString); // Placeholder for API call
}
void sendDataToServer(String jsonPayload)
{
http.beginRequest();
http.post("");
http.sendHeader("Content-Type", "application/json");
http.sendHeader("Content-Length", jsonPayload.length());
http.beginBody();
http.print(jsonPayload);
http.endRequest();
int statusCode = http.responseStatusCode();
String response = http.responseBody();
Serial.print("Status: ");
Serial.println(statusCode);
Serial.print("Response: ");
Serial.println(response);
}
void setup()
{
Serial.begin(115200);
pinMode(LOAD_RELAY_PIN, OUTPUT);
pinMode(CHARGER_RELAY_PIN, OUTPUT);
digitalWrite(LOAD_RELAY_PIN, LOW);
digitalWrite(CHARGER_RELAY_PIN, LOW);
emon.voltage(VOLTAGE_SENSOR_PIN, V_CALIBRATION, 1.7);
emon.current(CURRENT_SENSOR_PIN, I_CALIBRATION);
if (!rtc.begin())
{
Serial.println("Couldn't find RTC");
while (1)
;
}
if (rtc.lostPower())
{
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
SerialAT.begin(MODEM_BAUD, SERIAL_8N1, MODEM_RX, MODEM_TX);
delay(3000);
Serial.println("Initializing modem...");
if (!modem.restart())
{
Serial.println("Modem restart failed, trying modem.init()...");
if (!modem.init())
{
Serial.println("Modem failed to initialize.");
while (true)
;
}
}
Serial.println("Connecting to network...");
if (!modem.waitForNetwork(10000))
{
Serial.println("Network connection failed!");
while (true)
;
}
Serial.println("Connecting to Internet...");
if (!modem.gprsConnect(apn, user, pass))
{
Serial.println("GPRS connection failed!");
while (true)
;
}
Serial.println("GSM connected.");
}
void loop()
{
// Turn off charger briefly to take accurate SOC
digitalWrite(CHARGER_RELAY_PIN, LOW);
delay(1000); // Wait for voltage to stabilize
readAndPrintJSONWithTimestamp();
digitalWrite(CHARGER_RELAY_PIN, HIGH);
// Control LOAD_RELAY_PIN based on API (placeholder)
// digitalWrite(LOAD_RELAY_PIN, HIGH or LOW);
delay(10000); // Sample every 10 seconds
}