System Architecture¶
Table of Contents¶
- Overview
- System Block Diagram
- Power Architecture
- Voltage Domains
- Communication Architecture
- Physical Architecture
- GPIO and Pin Assignment
Overview¶
The Ramgarh Farm Sensor Node is a tightly integrated system where power management, signal conditioning, and data acquisition happen in concert. The architecture is organized into distinct functional blocks—power supply, supervision, sensing, and communication—each with clear responsibilities and electrical contracts. Understanding how these blocks connect, and why each was sized the way it was, is essential for commissioning, troubleshooting, and future revisions.
The node follows a hierarchical power architecture: the battery is the energy reservoir, the boost converter is the primary power distributor (always-on), the ESP32 microcontroller is the orchestrator (wakes, reads, transmits, sleeps), and the supervisor is the watchdog (prevents brownout resets and latch-up). Sensors hang off the microcontroller's GPIO and analog inputs, powered by its 3.3V rail. WiFi is the sole communication path; there is no LoRa, Bluetooth, or cellular backup. This simplicity is deliberate—it keeps power consumption predictable and testing straightforward.
System Block Diagram¶
The complete system from solar panel to server:
graph TD
subgraph PowerGeneration["⚡ POWER GENERATION"]
SP["Solar Panel<br/>6V / 200mA peak<br/>Voc 7.2V"]
end
subgraph PowerPath["🔋 POWER PATH"]
D1["SS14 Schottky<br/>Vf 0.3V drop"]
C1["100µF input<br/>cap"]
C2["10µF input<br/>cap"]
MCP["MCP73871<br/>Solar Charger<br/>• Dual input<br/>• Load sharing<br/>• 500mA charge"]
Q1["P-ch MOSFET<br/>load path<br/>reverse protection"]
BAT["18650 Li-Ion<br/>NCR18650B<br/>3400mAh<br/>3.7V nominal"]
SWITCH["Rocker Switch<br/>Master power"]
end
subgraph BoostStage["⬆️ BOOST CONVERTER"]
MT["MT3608 Module<br/>Input: BAT 3.7V<br/>Output: 5V<br/>Efficiency: 85%<br/>Quiescent: 0.6mA"]
C_IN["10µF input<br/>cap"]
C_OUT["10µF output<br/>cap"]
TRIM["Trimpot<br/>Calibrate to 5.0V"]
end
subgraph Supervision["🛡️ SUPERVISION"]
R_RST["10K pull-up<br/>R_RST_PU"]
MCP100["MCP100-450<br/>Brownout<br/>Threshold: 4.5V<br/>Quiescent: 0.002mA"]
end
subgraph Microcontroller["🧠 MICROCONTROLLER"]
ESP32["ESP32 DevKit V1<br/>• WiFi 802.11b/g/n<br/>• Dual-core 240 MHz<br/>• 12-bit ADC×2<br/>• I2C, SPI, UART<br/>• Deep sleep 0.01mA"]
V3P3["AMS1117 3.3V LDO<br/>onboard ESP32<br/>Max 400mA continuous"]
end
subgraph Sensing["📊 SENSING"]
SOIL_S["Soil Moisture<br/>Capacitive<br/>GPIO26 enable<br/>GPIO34 ADC"]
RAIN_S["Rain Detector<br/>Tipping bucket<br/>GPIO35 ADC"]
I2C_BUS["I2C Bus<br/>GPIO4=SDA<br/>GPIO5=SCL<br/>4.7K pull-ups"]
BH["BH1750<br/>Light sensor<br/>I2C addr 0x23"]
BME["BME280<br/>Temp/Humidity/Pressure<br/>I2C addr 0x77"]
PIR["PIR Motion<br/>GPIO18 input"]
DHT_OPT["DHT22 (optional)<br/>GPIO16 1-wire"]
end
subgraph Monitoring["📈 MONITORING"]
VBAT_DIV["Voltage divider<br/>Ratio 2:1<br/>GPIO32 ADC"]
LED["Status LED<br/>GPIO2 output<br/>Boot constraint: low"]
end
subgraph Communication["☁️ COMMUNICATION"]
WIFI["ESP32 WiFi<br/>2.4 GHz antenna<br/>802.11 b/g/n<br/>Peak TX: 160mA"]
SERVER["Farm Server<br/>Data ingestion<br/>Analytics"]
end
%% Power path connections
SP --> D1
D1 --> C1
D1 --> C2
C1 --> MCP
C2 --> MCP
MCP --> Q1
Q1 --> BAT
BAT --> SWITCH
%% Boost stage
SWITCH -->|3.7V| C_IN
C_IN --> MT
MT --> C_OUT
C_OUT --> TRIM
TRIM -->|5.0V| R_RST
TRIM -->|5V| V3P3
%% Supervision
R_RST --> MCP100
MCP100 -->|EN| ESP32
%% Sensing
V3P3 -->|3.3V| SOIL_S
V3P3 -->|3.3V| RAIN_S
V3P3 -->|3.3V| I2C_BUS
V3P3 -->|3.3V| PIR
V3P3 -->|3.3V| DHT_OPT
V3P3 -->|3.3V| LED
I2C_BUS --> BH
I2C_BUS --> BME
ESP32 -->|GPIO26| SOIL_S
ESP32 -->|GPIO34| SOIL_S
ESP32 -->|GPIO35| RAIN_S
ESP32 -->|I2C| I2C_BUS
ESP32 -->|GPIO18| PIR
ESP32 -->|GPIO16| DHT_OPT
ESP32 -->|GPIO2| LED
%% Monitoring
SWITCH -->|BAT| VBAT_DIV
VBAT_DIV --> ESP32
%% Communication
ESP32 -->|5V| WIFI
WIFI --> SERVER
%% Styling
classDef power fill:#FDB913,stroke:#F57F17,stroke-width:2px,color:#000
classDef boost fill:#FF9800,stroke:#E65100,stroke-width:2px,color:#fff
classDef super fill:#4CAF50,stroke:#2E7D32,stroke-width:2px,color:#fff
classDef mcu fill:#9C27B0,stroke:#6A1B9A,stroke-width:2px,color:#fff
classDef sens fill:#2196F3,stroke:#0D47A1,stroke-width:2px,color:#fff
classDef comms fill:#E91E63,stroke:#C2185B,stroke-width:2px,color:#fff
class SP,D1,C1,C2,MCP,Q1,BAT,SWITCH power
class MT,C_IN,C_OUT,TRIM boost
class R_RST,MCP100 super
class ESP32,V3P3 mcu
class SOIL_S,RAIN_S,I2C_BUS,BH,BME,PIR,DHT_OPT,VBAT_DIV,LED sens
class WIFI,SERVER comms
This diagram shows the complete energy path (gold boxes), the boost supply (orange), the supervisor (green), the microcontroller (purple), all connected sensors (blue), and the WiFi link to the farm server (pink). Every component has a purpose; every wire carries either power, a signal, or data.
Power Architecture¶
The power architecture is a nine-stage cascade from sun to microcontroller. Each stage has efficiency, current limits, and quiescent draws that must be understood.
graph LR
Solar["☀️ Solar Panel<br/>Voc 7.2V<br/>Iph 200mA"]
-->|"6.9V after Schottky"| Charger["🔌 MCP73871<br/>Charger<br/>500mA limit<br/>0.1mA quiescent<br/>~99% efficient"]
Charger -->|"4.2V max charge"| Battery["🔋 Li-Ion 18650<br/>Nominal 3.7V<br/>Usable 2720mAh<br/>Internal R ~100mΩ"]
Battery -->|"3.0-4.2V range"| Switch["🎚️ Rocker Switch<br/>Master enable<br/>0Ω when on"]
Switch -->|"Battery voltage"| Boost["⬆️ MT3608 Boost<br/>5V output<br/>85% efficient<br/>0.6mA quiescent"]
Boost -->|"5.0V nominal"| Supervisor["🛡️ Supervisor<br/>MCP100-450<br/>Brownout gate<br/>0.002mA"]
Supervisor -->|"EN signal"| MCU["🧠 ESP32 + LDO<br/>V3P3 3.3V<br/>0.01mA sleep<br/>160mA TX peak"]
MCU -->|"3.3V to 400mA"| Sensors["📊 Sensors<br/>• Soil<br/>• Rain<br/>• I2C<br/>• PIR<br/>• Optional DHT"]
MCU -->|"160mA peak TX"| WiFi["📡 WiFi Module<br/>2.4 GHz<br/>~20-30mAh per cycle"]
WiFi -->|"Data packets"| Server["☁️ Farm Server<br/>Data storage<br/>Processing"]
style Solar fill:#FDB913,stroke:#F57F17,stroke-width:2px
style Charger fill:#FF9800,stroke:#E65100,stroke-width:2px
style Battery fill:#2196F3,stroke:#0D47A1,stroke-width:2px
style Switch fill:#4CAF50,stroke:#2E7D32,stroke-width:2px
style Boost fill:#FF5722,stroke:#BF360C,stroke-width:2px
style Supervisor fill:#009688,stroke:#00695C,stroke-width:2px
style MCU fill:#9C27B0,stroke:#6A1B9A,stroke-width:2px
style Sensors fill:#00BCD4,stroke:#006064,stroke-width:2px
style WiFi fill:#E91E63,stroke:#880E4F,stroke-width:2px
style Server fill:#3F51B5,stroke:#1A237E,stroke-width:2px
Stage 1: Solar Panel to Charger Input The panel's open-circuit voltage is 7.2 V. A Schottky diode (SS14, 0.3 V forward drop) protects against backfeeding when clouds pass and couples the panel to the charger input. Bulk capacitors (100 µF + 10 µF) smooth ripple and provide transient current buffering.
Stage 2: Charger (MCP73871) The MCP73871 is a dedicated 1S LiPo charger with solar input and load-sharing capability. It monitors the solar input voltage and the battery voltage, managing charging intelligently. When solar is present, it charges the battery and powers the load simultaneously. When solar is absent, it sustains the system from battery alone. Quiescent current is 0.1 mA (negligible).
Stage 3: Battery (18650 Li-Ion) The NCR18650B is a high-discharge-current cell (10A peak available) with 3400 mAh nominal capacity. We derate it to 2720 mAh (80%) for aging margin and voltage margin below the 3.0 V cutoff. Internal resistance is ~100 mΩ, so a 500 mA load draw causes ~50 mV droop (absorbed by the boost converter's input range).
Stage 4: Rocker Switch (Master Power) A simple mechanical switch. When OFF, the entire system is disconnected from the battery (except the charger's internal supervision circuit). When ON, full battery voltage is available downstream. Switch resistance is ~10 mΩ in the ON state (negligible).
Stage 5: Boost Converter (MT3608) The MT3608 is a synchronous buck-boost converter module rated for 5 V output at up to 500 mA. Input range is 2 V to 5 V; we operate it at 3.7 V nominal (battery). Output is set to 5.0 V by a trimpot on the module. Efficiency is approximately 85% under normal load (measured in field validation). Quiescent draw (when not actively switching) is 0.6 mA — this is the largest single contributor to sleep current and is unavoidable with this topology. The boost converter remains powered whenever the rocker switch is ON, even when the ESP32 is in deep sleep.
Stage 6: Supervisor (MCP100-450) The MCP100-450 is a precision voltage supervisor with 4.5 V threshold. Its output is an open-drain gate that drives the ESP32 reset line. When the BOOST rail drops below 4.5 V (equivalent to ~2.8 V on the battery side), the supervisor asserts reset, preventing erratic ESP32 behavior. Once BOOST rises above 4.5 V, reset is released and the ESP32 boots or resumes. Quiescent current is 0.002 mA (negligible).
Stage 7: Microcontroller (ESP32) The ESP32 DevKit V1 is powered from the BOOST 5V rail via an onboard AMS1117 3.3V LDO. In deep sleep, the ESP32 draws 0.01 mA. In active CPU mode (no WiFi), it draws ~80 mA. WiFi TX peaks at 160 mA for a few hundred milliseconds. The 3.3V rail (derived from the LDO) supplies all sensors and peripheral logic.
Stage 8: Sensors All sensors are powered from the 3.3V rail: - Soil moisture (capacitive sensor via N-ch MOSFET gate, GPIO26 controlled) - Rain detector (voltage divider, GPIO35 ADC) - BH1750 (light sensor, I2C) - BME280 (temperature, humidity, barometric pressure, I2C) - PIR (motion detection, GPIO18 input) - DHT22 (optional, 1-wire temperature/humidity, GPIO16) - Voltage monitor (2:1 resistor divider, GPIO32 ADC) - Status LED (GPIO2 output)
Stage 9: WiFi Transmission to Server When the ESP32 transmits, the WiFi module draws 160 mA at peak. A full transmission cycle (WiFi association, TCP handshake, data send, TCP close) takes 10–15 seconds and consumes ~20–30 mAh including overhead and retries.
Voltage Domains¶
The system operates across three distinct voltage domains. Understanding which components belong to which domain is critical for circuit integrity.
BOOST_5V Domain¶
Nominal voltage: 5.0 V (set by MT3608 trimpot) Tolerance: ±2% (4.9–5.1 V target) Max continuous current: 350 mA (MT3608 limit) Source: MT3608 boost converter (always powered when rocker switch is ON) Components on this rail: - ESP32 DevKit VIN - MCP100-450 VDD (supervisor power) - R_RST_PU 10K pull-up resistor
Design note: This rail must be stable and clean. The ESP32 internal LDO is robust but transient voltage dips during WiFi TX can cause brown-outs if the boost converter is not well-bypassed. Always include 10µF (ripple) + 10µF (bulk) capacitors at the boost output.
V3P3 Domain¶
Nominal voltage: 3.3 V (from ESP32 onboard AMS1117 LDO) Max continuous current: 400 mA (thermal limit of LDO; absolute max is 500 mA but requires derating) Source: ESP32 internal LDO, fed from BOOST_5V Components on this rail: - All sensors (BH1750, BME280, PIR, soil moisture, rain detector) - I2C pull-up resistors (4.7K) - Optional DHT22 - Status LED (with current-limiting resistor)
Design note: This rail powers the analog front-end and digital sensors. Do NOT connect any sensor to the 5V rail. Always pull 3.3V from the ESP32 header. The LDO has excellent filtering and low quiescent draw (~1 mA typical).
BAT_P Domain¶
Nominal voltage: 3.0–4.2 V (Li-ion battery range) Max continuous current: 500 mA (internal resistance limits) Source: 18650 battery cell Components on this rail: - Charger input (via Schottky diode) - Boost converter input (via rocker switch)
Design note: This is the primary power distribution bus. All energy flows from here. High-frequency bypassing is not needed on the battery side (the boost converter handles that), but bulk capacitance at the charger input (100µF) smooths solar panel transients.
Communication Architecture¶
The ESP32 acquires data from sensors, buffers readings in RAM, and transmits them over WiFi to the farm server. The communication follows a state machine with three distinct phases.
stateDiagram-v2
[*] --> DeepSleep
DeepSleep --> SensorRead: Wake timer<br/>5-min interval
SensorRead --> SensorRead: Buffer accumulate<br/>Repeat every 5min
SensorRead --> Decision{Buffer full?<br/>3 readings<br/>per Profile B}
Decision -->|Not full| DeepSleep: Return to sleep<br/>next cycle
Decision -->|Full| WiFiConnect: Initiate WiFi<br/>TX sequence
WiFiConnect --> WiFiAssoc: Enable WiFi<br/>Scan for SSID
WiFiAssoc --> TCPConnect: Acquire IP<br/>DHCP
TCPConnect --> HTTPSend: Establish<br/>TCP socket
HTTPSend --> HTTPWait: Send JSON<br/>batch
HTTPWait --> Connected{Connected?<br/>ACK?}
Connected -->|Yes| DeepSleep: Clear buffer<br/>Return to sleep
Connected -->|No| Retry{Retries<br/>< 3?}
Retry -->|Yes| WiFiAssoc: Retry<br/>association
Retry -->|No| Backoff: Exponential<br/>backoff<br/>5min + random
Backoff --> DeepSleep: Keep buffer<br/>Retry next cycle
Phase 1: Deep Sleep and Wake The ESP32 wakes every 5 minutes (Profile B). Wake is triggered by an internal timer. On wake, the CPU initializes GPIO for sensor reading.
Phase 2: Sensor Read GPIO are read, ADC is sampled, I2C bus is polled. Readings are stored in RAM (a simple circular buffer of 3-reading slots). The read operation takes ~1 second total. After read, the CPU goes back to sleep.
Phase 3: Transmission When the buffer contains 3 complete readings (after 15 minutes of wake/read cycles), the ESP32 enables the WiFi module and initiates a connection. This step includes: - WiFi radio boot and scan - Authentication to the farm server's SSID - DHCP IP acquisition - TCP socket establishment - HTTP or MQTT publish (JSON format) - Server ACK confirmation - TCP close and WiFi radio sleep
If the WiFi link is poor or unavailable, firmware retries up to 3 times with exponential backoff. If all retries fail, the buffer is retained and TX is deferred until the next cycle. This provides robustness against temporary WiFi outages.
Data Format (Example)
{
"node_id": "sensor_node_01",
"timestamp": "2026-03-26T14:35:00Z",
"readings": [
{
"ts": "2026-03-26T14:20:00Z",
"soil_moisture_adc": 1847,
"rain_adc": 450,
"light_lux": 12400,
"temp_c": 32.5,
"humidity_rh": 45,
"pressure_pa": 101325,
"motion": false
},
{ /* reading 2 */ },
{ /* reading 3 */ }
],
"battery_mv": 3950,
"rssi_dbm": -65
}
Physical Architecture¶
The sensor node lives in a weatherproof enclosure (HT-5WAY polycarbonate) measuring roughly 120 mm × 85 mm × 60 mm (dimensions pending final measurement). Inside, components are mounted on a custom PCB designed to fit along the enclosure floor.
graph TD
ENC["Enclosure<br/>HT-5WAY Polycarbonate<br/>IP65 rated<br/>~120×85×60 mm"]
ENC --> TOP["Top cover<br/>Clear polycarbonate<br/>Light sensor visible<br/>Desiccant pouch<br/>humidity control"]
ENC --> PCB["Custom PCB<br/>2-layer FR4<br/>~100×70 mm<br/>Component-dense"]
PCB --> ESP["ESP32 DevKit<br/>30×52 mm<br/>Mounted flat<br/>USB-C facing<br/>side hole"]
PCB --> POWER["Power section<br/>• MCP73871 module<br/>• MT3608 module<br/>• Capacitors<br/>• Resistors"]
PCB --> SENSORS["Sensor breakouts<br/>• BH1750 (I2C)<br/>• BME280 (I2C)<br/>• PIR (GPIO18)<br/>• Soil (ADC)"]
PCB --> CONN["Connectors<br/>• Solar panel<br/>(JST 2-pin)<br/>• Battery<br/>(spring pogo)<br/>• Antenna<br/>ext. SMA"]
ENC --> BATT["18650 battery<br/>In spring holder<br/>Easy replacement<br/>Protected from<br/>vibration"]
ENC --> SOLAR["Solar panel<br/>Mounted on roof<br/>South-facing<br/>Flexible cable<br/>through gland"]
ENC --> ANT["WiFi antenna<br/>SMA connector<br/>Mounted on<br/>enclosure lip<br/>unobstructed"]
style ENC fill:#E0E0E0,stroke:#424242,stroke-width:2px
style TOP fill:#E8F5E9,stroke:#2E7D32,stroke-width:2px
style PCB fill:#FCE4EC,stroke:#C2185B,stroke-width:2px
style ESP fill:#F3E5F5,stroke:#6A1B9A,stroke-width:2px
style POWER fill:#FFE0B2,stroke:#E65100,stroke-width:2px
style SENSORS fill:#E0F2F1,stroke:#00695C,stroke-width:2px
style CONN fill:#FFF3E0,stroke:#E65100,stroke-width:2px
style BATT fill:#BBDEFB,stroke:#0D47A1,stroke-width:2px
style SOLAR fill:#FDB913,stroke:#F57F17,stroke-width:2px
style ANT fill:#E91E63,stroke:#880E4F,stroke-width:2px
Enclosure Details: - Material: Clear polycarbonate (allows light into BH1750 sensor) - Ingress protection: IP65 (dust-tight, jet-water resistant) - Mounting: Wall or pole-mount via bracket - Desiccant: Silica gel pouch inside to control humidity in Rajasthan heat - Thermal management: 10°C internal rise over ambient (IPC-2221); ventilation holes with desiccant plug
PCB Layout Principles: - Star grounding from battery negative - Wide traces (0.6–0.8 mm) on 5V and battery rails to minimize voltage drop - Bypass capacitors physically close to IC power pins - Analog and digital grounds separated until they meet at a single point - Antenna connector routed away from switching boost converter noise
Solar Panel: - Small 6V panel (~0.5–1 W) mounted on a bracket angled to the sun - Flexible ribbon cable through a strain-relief gland in the enclosure - JST 2-pin connector for easy disconnect - Can be sun-tracked manually or fixed to geographic south
Battery: - NCR18650B in a standard cylindrical spring holder - Spring contacts make removal easy for testing or replacement - Protected from mechanical shock by foam padding
Antenna: - External SMA connector on the enclosure lid or side - 2.4 GHz quarter-wave or dipole antenna (omni-directional, 0 dBi) - Mounted at least 15 cm from metal objects and the solar panel
GPIO and Pin Assignment¶
All pin assignments are authoritative and locked in the system_parameters.yaml file.
| GPIO | Function | Type | ADC | I2C | Notes |
|---|---|---|---|---|---|
| 34 | SOIL_ADC | Input | ADC1_CH6 | — | Soil moisture analog input (capacitive) |
| 35 | RAIN_ADC | Input | ADC1_CH7 | — | Rain detector analog input (voltage divider) |
| 32 | VBAT_ADC | Input | ADC1_CH4 | — | Battery voltage monitor (2:1 divider) |
| 33 | SPARE_ADC | Input | ADC1_CH5 | — | Reserved for future use |
| 26 | SOIL_PWR_EN | Output | — | — | N-ch MOSFET gate; gates soil sensor supply |
| 2 | STATUS_LED | Output | — | — | Status LED (boot constraint: must be LOW at boot) |
| 16 | DHT22_DATA | I/O | — | — | Optional DHT22 temperature/humidity (1-wire) |
| 4 | I2C_SDA | I/O | — | SDA | I2C bus (4.7K pull-up behind SB1) |
| 5 | I2C_SCL | Output | — | SCL | I2C bus (4.7K pull-up behind SB1) |
| 18 | PIR_IN | Input | — | — | PIR motion detector (GPIO interrupt) |
| 1 | UART0_TX | Output | — | — | Serial debug TX (do not externally connect) |
| 3 | UART0_RX | Input | — | — | Serial debug RX (do not externally connect) |
Critical Constraints: - GPIO2 (STATUS_LED): Must be LOW at boot. Never pull it HIGH during boot sequence or the ESP32 may fail to boot. Use an output-low initialization. - GPIO25: PROHIBITED for ADC in Rev A. WiFi uses ADC2 internally, and GPIO25 (ADC2_CH8) conflicts. Use ADC1 channels only (GPIO 32–39). - I2C pull-ups: Already included onboard ESP32 for GPIO4/5 via solder bridge SB1. Do not add external pull-ups unless explicitly needed for long traces. - ADC input voltage: All ADC inputs must be ≤ 3.3V. The VBAT divider is sized 2:1 (VBat/2) so that 4.2V battery reads 2.1V at GPIO32.
Next Steps¶
- For energy deep dive: Move to Power Model
- For design rationale: See Design Decisions
- For deployment specifics: See Deployment Guide
← Quick Start | Next → Power Model