â Back to Course
Complete Working Code
ðŧ Complete Solar IoT Sensor Code - Battery-Powered Soil Monitoring
ðŧ What You'll Learn:
- ð Run your soil sensor for months on a single battery charge
- ⥠Use deep sleep to wake, read, send, and sleep again
- ð Adjust sleep interval based on conditions (dry = check more often)
- ð Monitor battery voltage and extend life when low
⥠How Solar IoT Works
â° Wake â ð Read Sensor â ðĄ Send Data â ðī Deep Sleep (15 min) â ð Repeat
Total active time: ~3 seconds | Power saved: 99.9%
ðĄ Power Savings Breakdown:
- ðĄ Always on WiFi: 170mA à 24h = 4,080mAh/day â Battery dead in 1 day
- ðī Deep sleep (15 min wake): 170mA Ã 3s + 0.01mA Ã 897s = 0.15mAh/cycle â Battery lasts 6+ months
ð Complete Solar Sensor Code
#include <WiFi.h>
#include <HTTPClient.h>
const char* ssid = "YOUR_WIFI";
const char* password = "YOUR_PASSWORD";
const char* token = "YOUR_TOKEN";
#define SOIL_PIN 32
#define BATTERY_PIN 34
const int DRY = 3800, WET = 1500;
RTC_DATA_ATTR int bootCount = 0;
RTC_DATA_ATTR int lastMoisture = 0;
// ========== READ SENSORS ==========
int readSoil() {
int m = map(analogRead(SOIL_PIN), DRY, WET, 0, 100);
return constrain(m, 0, 100);
}
float readBattery() {
int raw = analogRead(BATTERY_PIN);
return (raw / 4095.0) * 3.3 * 2; // Voltage divider: 2x
}
// ========== SEND TO CLOUD ==========
void sendData(int moisture, float battery) {
WiFi.begin(ssid, password);
int tries = 0;
while (WiFi.status() != WL_CONNECTED && tries < 20) {
delay(200);
tries++;
}
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
http.begin("https://api.oceanremote.net/device/state");
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
String data = "token=" + String(token);
data += "&soil=" + String(moisture);
data += "&battery=" + String(battery);
http.POST(data);
http.end();
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
}
}
// ========== SMART SLEEP ==========
int getSleepMinutes(int moisture, float battery) {
if (battery < 3.3) return 60; // Low battery â sleep longer
if (moisture < 30) return 5; // Very dry â check often
if (moisture > 70) return 30; // Very wet â check less
return 15; // Normal â 15 min
}
// ========== SETUP ==========
void setup() {
Serial.begin(115200);
bootCount++;
int m = readSoil();
float v = readBattery();
Serial.printf("Wake #%d | Soil: %d%% | Battery: %.2fV\n", bootCount, m, v);
// Send only if changed or every 10th reading
if (abs(m - lastMoisture) > 5 || bootCount % 10 == 0) {
sendData(m, v);
lastMoisture = m;
}
int sleep = getSleepMinutes(m, v);
Serial.printf("ðĪ Sleep %d min\n", sleep);
esp_sleep_enable_timer_wakeup(sleep * 60 * 1000000ULL);
esp_deep_sleep_start();
}
void loop() {}
ð Key Power-Saving Techniques
- ðī Deep sleep (2.5ΞA): ESP32 consumes almost nothing between readings
- ðĄ Disable WiFi after sending:
WiFi.disconnect(true); WiFi.mode(WIFI_OFF); - ðĶ Batch data: Send only when moisture changes significantly (>5%)
- âąïļ Send less often: Wet soil? Sleep 30 min. Dry soil? Sleep 5 min.
- ð Use RTC memory:
RTC_DATA_ATTRpreserves variables across deep sleep
â ïļ Solar Sensor Mistakes:
- â Leaving WiFi on after sending data â Battery dead in 2 days
- â Reading sensors every minute â No time to sleep
- â Not using deep sleep â Same battery life as always-on
- â Forgetting
RTC_DATA_ATTRâ Variables reset each wake
ð Real Results - Kenyan Farm:
3 solar sensors installed in remote field with no electricity:
- ð 2600mAh battery + 6V 2W solar panel
- â° Wake every 15 minutes â send data â deep sleep
- ð Result: Running continuously for 8+ months without battery change
ðŊ Quick Reference:
- ⥠Active time: 2-3 seconds per cycle
- ðī Deep sleep: 2.5ΞA (almost zero)
- ðĄ WiFi on: 170mA â Turn off immediately after sending
- ð Battery life: 6-12 months on 2600mAh
- ðū
RTC_DATA_ATTR= survives deep sleep
ðĄ Key Takeaways:
- Apply these concepts directly to your farm or project.
- Take notes on important details for the quiz.
- Use the button below to track your progress.
×