#include <Wire.h>
#include <RTClib.h>
#include <SPI.h>
#include <SD.h>
// ====== USER SETTINGS ======
const uint8_t PIN_CT = A0; // CT on A0
const uint8_t SD_CS = 10; // SD CS pin (UNO=10)
const float ADC_REF = 5.0; // UNO 5V
const int ADC_COUNTS = 1023; // 10-bit ADC
const float MAINS_VRMS = 220.0; // power = I_rms * 220
const float VOLTS_PER_AMP_RMS = (1.0/30.0); // SCT-013-030 (1Vrms @ 30A)
// const float VOLTS_PER_AMP_RMS = 0.5/30.0; // مثال لو عندك SCT-013-000 + burden
const unsigned long MEASURE_WINDOW_MS = 2000; // ~2s RMS
const unsigned long LOG_INTERVAL_MS = 3UL * 60UL * 1000UL; // كل 3 دقائق
// ===========================
RTC_DS3231 rtc;
File logFile;
bool sdOK = false;
char currentDateStr[11]; // "YYYY-MM-DD"
char currentFileName[13]; // "YYMMDD.CSV"
unsigned long lastLogMs = 0;
// ========== Helpers ==========
void makeDateString(const DateTime& dt, char* out) {
snprintf(out, 11, "%04d-%02d-%02d", dt.year(), dt.month(), dt.day());
}
// صيغة 8.3: YYMMDD.CSV
void makeFileNameFromDate(const DateTime& dt, char* out) {
snprintf(out, 13, "%02d%02d%02d.CSV",
dt.year() % 100, dt.month(), dt.day());
}
bool openTodayFileIfNeeded() {
DateTime now = rtc.now();
char dateStr[11], fname[13];
makeDateString(now, dateStr);
makeFileNameFromDate(now, fname);
if (!logFile || strcmp(dateStr, currentDateStr) != 0) {
if (logFile) { logFile.flush(); logFile.close(); }
strcpy(currentDateStr, dateStr);
strcpy(currentFileName, fname);
bool existed = SD.exists(currentFileName);
logFile = SD.open(currentFileName, FILE_WRITE);
if (!logFile) { Serial.println(F("[ERR] open failed!")); return false; }
if (!existed || logFile.size() == 0) {
logFile.println("time_h,power_W");
logFile.flush();
}
Serial.print(F("[OK] Logging to ")); Serial.println(currentFileName);
}
return true;
}
// حساب RMS للتيار
float measureIrms(unsigned long window_ms) {
unsigned long t0 = millis();
double sum = 0.0; uint32_t n = 0;
while (millis() - t0 < window_ms / 10) { sum += analogRead(PIN_CT); n++; }
double mid = (n > 0) ? sum / n : 512.0;
t0 = millis(); n = 0;
double accumSq = 0.0;
while (millis() - t0 < window_ms) {
int raw = analogRead(PIN_CT);
double centered = raw - mid;
double volts = centered * (ADC_REF / ADC_COUNTS);
double inst_I = volts / VOLTS_PER_AMP_RMS;
accumSq += inst_I * inst_I;
n++;
}
return (n > 0) ? sqrt(accumSq / n) : 0.0;
}
// ========== Setup ==========
void setup() {
pinMode(PIN_CT, INPUT);
pinMode(SD_CS, OUTPUT); // مهم مع SD
Serial.begin(115200);
delay(300);
// RTC
if (!rtc.begin()) {
Serial.println(F("[ERR] RTC not found!"));
} else if (rtc.lostPower()) {
rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // set once
Serial.println(F("[WARN] RTC time set to compile time."));
}
// SD
Serial.print(F("Initializing SD..."));
sdOK = SD.begin(SD_CS);
Serial.println(sdOK ? F("OK") : F("FAILED"));
if (!sdOK) return;
if (!openTodayFileIfNeeded()) {
Serial.println(F("[ERR] Failed to open today's CSV."));
}
lastLogMs = millis() - LOG_INTERVAL_MS; // أول تسجيل مباشرة
}
// ========== Loop ==========
void loop() {
if (!sdOK) return;
if (millis() - lastLogMs >= LOG_INTERVAL_MS) {
lastLogMs = millis();
if (!openTodayFileIfNeeded()) return;
// قياس القدرة
float Irms = measureIrms(MEASURE_WINDOW_MS);
float Power = Irms * MAINS_VRMS;
// الوقت العشري مع لف عند 24
DateTime now = rtc.now();
double time_h = now.hour() + now.minute()/60.0 + now.second()/3600.0;
if (time_h >= 24.0) time_h = 0.0;
// عرض
Serial.print(F("t=")); Serial.print(time_h, 3);
Serial.print(F(" h | P=")); Serial.print(Power, 2); Serial.println(F(" W"));
// كتابة في CSV
if (logFile) {
logFile.print(time_h, 3); logFile.print(',');
logFile.println(Power, 2);
logFile.flush();
} else {
Serial.println(F("[ERR] logFile null while writing."));
}
}
}