01 · Brief
Firmware is written, breadboard testing completed, the next step is installation. A battery node will be at the tree and a mains relay indoors. The node deep-sleeps, wakes hourly, reads the capacitive probe and the battery divider, fires one ESP-NOW packet to the relay, and sleeps again. It holds no WiFi association at all. The relay keeps the WiFi and forwards each packet to the server as an authenticated post.
On the dashboard it will feed the ARBORETUM strip on the Nowcast page: soil moisture and battery percentage beside the weather station’s readings. And the new Oak tree can stay hydrated.
02 · System
03 · Source
node.ino
// --- ESP-NOW: channel must match the relay's (pinned on the router) ---
WiFi.mode(WIFI_STA);
esp_wifi_set_channel(WIFI_CHANNEL, WIFI_SECOND_CHAN_NONE);
if (esp_now_init() != ESP_OK) { LOGLN("esp_now_init failed"); goToSleep(false); }
esp_now_register_send_cb(onSent);
esp_now_peer_info_t peer = {};
memcpy(peer.peer_addr, relayMac, 6);
peer.channel = WIFI_CHANNEL;
peer.encrypt = false;
esp_now_add_peer(&peer);
for (int attempt = 0; attempt < SEND_RETRIES; attempt++) {
sendDone = false;
esp_now_send(relayMac, (const uint8_t *)&pkt, sizeof(pkt));
unsigned long t0 = millis();
while (!sendDone && millis() - t0 < SEND_WAIT_MS) delay(5);
if (sendOk) break;
LOGLN("send retry");
}
LOGLN(sendOk ? "delivered" : "gave up");
// Low battery: this reading already announced it — now protect the cell.
goToSleep(vbatMv < LOW_BATT_CUTOFF_MV);
}04 · Lessons
The ESP-NOW channel must be pinned to the relay's WiFi channel, or the node's packets vanish silently.
The probe is powered from a GPIO only during the 200 millisecond read. Everything else is deep sleep.
Probes have to be water-proofed.