Build Sheets

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

18650XIAO ESP32-C6PROBE→ RELAY
RELAYLCARS CORE

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);
}
Lines 104–128 of 130 · Full source →

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.