/* Session 4 — Autonomous field node: SD card CSV logging + deep sleep (ESP32) SD module (SPI): CS->5, SCK->18, MISO->19, MOSI->23, VCC 3.3V/5V (check your module), GND DHT22 -> GPIO 4, soil -> GPIO 34, battery divider (100k/100k) -> GPIO 33 Wakes every 15 minutes, logs one CSV line, sleeps (~10 µA on a bare ESP32 module). Power budget example: 2000 mAh Li-ion, awake 3 s @ 80 mA, sleep @ 0.15 mA (DevKit LDO) -> ~26 days. */ #include #include #include #define SD_CS 5 #define DHT_PIN 4 #define SOIL_PIN 34 #define BAT_PIN 33 #define SLEEP_MINUTES 15 DHT dht(DHT_PIN, DHT22); RTC_DATA_ATTR uint32_t bootCount = 0; // survives deep sleep (RTC memory) void goToSleep() { esp_sleep_enable_timer_wakeup((uint64_t)SLEEP_MINUTES * 60ULL * 1000000ULL); Serial.flush(); esp_deep_sleep_start(); } void setup() { Serial.begin(115200); bootCount++; dht.begin(); delay(2000); // DHT22 warm-up float t = dht.readTemperature(), h = dht.readHumidity(); int soil = analogRead(SOIL_PIN); float bat = analogReadMilliVolts(BAT_PIN) * 2 / 1000.0; if (!SD.begin(SD_CS)) { Serial.println("SD init failed — check wiring / FAT32 format"); goToSleep(); } bool newFile = !SD.exists("/farmlog.csv"); File f = SD.open("/farmlog.csv", FILE_APPEND); if (f) { if (newFile) f.println("boot,uptime_min,air_temp_c,air_hum_pct,soil_raw,battery_v"); f.printf("%lu,%lu,%.1f,%.1f,%d,%.2f\n", bootCount, bootCount * SLEEP_MINUTES, t, h, soil, bat); f.close(); Serial.printf("logged boot #%lu t=%.1f h=%.1f soil=%d bat=%.2fV\n", bootCount, t, h, soil, bat); } if (bat > 0.5 && bat < 3.3) { Serial.println("battery critical -> sleeping 4x longer"); esp_sleep_enable_timer_wakeup((uint64_t)SLEEP_MINUTES * 4 * 60ULL * 1000000ULL); esp_deep_sleep_start(); } goToSleep(); } void loop() {} // never reached — every wake-up starts again from setup()