An IoT solar power monitoring system is the telemetry layer that bridges your physical power hardware with real-time data dashboards. Rather than relying on the isolated LCD screens mounted on charge controllers, a properly engineered IoT setup aggregates data from the photovoltaic (PV) source, the battery management system (BMS), and the AC load panel into a single MQTT broker. This allows you to track state-of-charge (SoC), trigger automated load-shedding relays during low-solar days, and log historical degradation of your battery bank.

Building this requires matching the right current transformers, shunts, and microcontrollers to your specific DC and AC voltages. Below is the complete blueprint for instrumenting a 48V nominal lithium iron phosphate (LiFePO4) system, including the exact sizing math, topological constraints, and safety protocols required to keep the bank stable under heavy inverter loads.

System Block Architecture & IoT Sensor Specs

To monitor energy flow accurately, you must instrument the entire source-to-load path. The physical architecture of a standard off-grid or hybrid system flows in distinct blocks: PV Array → MPPT Charge Controller → Battery Bank (with BMS) → Hybrid Inverter/Charger → AC Subpanel (Loads). Your IoT layer taps into this chain at three critical nodes: the PV input (to measure harvest), the DC bus (to measure net battery charge/discharge), and the AC output (to measure consumption).

For the microcontroller, the ESP32-WROOM-32 is the industry standard for DIY power telemetry due to its dual-core 240MHz processing, native WiFi/BLE, and multiple hardware UART pins required to talk to RS485 and VE.Direct devices simultaneously. Below is the exact bill of materials and specification table for the sensor layer.

IoT Telemetry Component Spec Sheet (48V DC / 120/240V AC System)
Component / Model Function & Protocol Key Specifications Est. Cost (2026)
Victron SmartShunt 500A DC Bus Net Current (VE.Direct UART) 500A continuous, 10mV/500A shunt, 99% efficiency $145
YHDC SCT-013-030 AC Load Current (Analog ADC) 30A max, 1V AC output, split-core ferrite $12
ESP32-WROOM-32 DevKit Central Telemetry Node (WiFi/MQTT) 3.3V logic, 4MB Flash, 3x hardware UARTs $6
HW-519 RS485 to TTL BMS/Inverter Modbus RTU Translation 3.3V to 5V logic, 300kbps max, auto-direction $4
JBD / Overkill BMS UART Cell-Level Telemetry (Proprietary UART) Reads individual cell mV, MOSFET temp, SoC $15

The SmartShunt is placed on the negative DC bus between the battery bank and the system ground bar. The ESP32 reads the VE.Direct protocol (a simple ASCII hex stream at 19200 baud) to extract net DC voltage and current. Meanwhile, the SCT-013 current transformers clamp around the L1 and L2 hot wires leaving the inverter, feeding into the ESP32’s ADC pins via an op-amp biasing circuit to measure AC wattage.

Battery Bank Sizing, C-Rates, and Series vs. Parallel

Before you can monitor a battery bank, you must size it correctly for your inverter load. Let’s assume a target load of 3000W continuous for 4 hours of autonomy. This dictates a total energy requirement of 12,000Wh.

When wiring cells or pre-packaged 12V batteries to achieve a 48V nominal architecture, you must understand the consequence of series vs. parallel topologies. Wiring in series adds voltage while maintaining Amp-hours (Ah); four 12V 100Ah batteries in series yield 48V (nominal 51.2V for LiFePO4) at 100Ah. Wiring in parallel adds Ah while maintaining voltage; two 48V 100Ah strings in parallel yield 48V at 200Ah. The physical consequence of parallel strings is that current divides based on the path of least resistance. If one string has slightly lower internal resistance or shorter cable runs, it will disproportionately source current and heat up.

Lithium Fire-Safety & Parallel String Warning: Never parallel mismatched cells, and never parallel battery strings of different ages, capacities, or chemistries. If you must parallel multiple 48V battery modules, they must be identical models, purchased in the same batch, and wired with symmetrical cable lengths to ensure equal impedance. Always rely on a high-quality BMS with cell-level balancing and thermal cutoffs to prevent thermal runaway. For maximum safety and longevity, a single monolithic 48V cell block (e.g., a 16S 280Ah server rack battery) is vastly superior to paralleling multiple smaller 12V modules.

Sizing Math: Peukert, Efficiency, and C-Rates

To meet our 12,000Wh requirement, we must factor in Depth of Discharge (DoD) and inverter efficiency. LiFePO4 chemistry safely supports an 80% to 90% DoD without the severe cycle-life degradation seen in lead-acid. Using a conservative 90% DoD, the required bank capacity is 12,000Wh / 0.90 = 13,333Wh.

At a nominal 51.2V (16S LiFePO4), this translates to 13,333 / 51.2 = 260Ah. We would select a 48V 300Ah server rack battery to provide a buffer.

If you were attempting this with Flooded Lead-Acid (FLA), you would have to apply Peukert’s Law. Peukert’s exponent (typically k ≈ 1.3 for FLA) dictates that drawing high currents drastically reduces usable capacity. A 3000W load on a 48V FLA bank pulls roughly 75A. Due to Peukert losses and a strict 50% DoD limit to prevent sulfation, you would need an 800Ah FLA bank to achieve the same 4-hour runtime. LiFePO4 is largely immune to Peukert losses at standard discharge rates, allowing us to size strictly on C-rate limits.

Charge and Discharge Limits: Our 300Ah LiFePO4 bank has a maximum continuous discharge C-rate of 1C (300A) and a recommended charge C-rate of 0.5C (150A). Our calculated DC draw (detailed in the next section) will be roughly 92A, which is a 0.3C discharge rate—well within the safe thermal limits of the cells and the BMS MOSFETs.

Inverter/Charger Sizing & IoT Data Integration

The inverter must handle both the continuous load and the inductive surge of motor startups (like well pumps or refrigerator compressors). For a 3000W continuous load, we calculate the DC current draw factoring in inverter efficiency. High-frequency 48V inverters typically operate at 85% to 90% efficiency under heavy load.

  • DC Draw Calculation: 3000W / (48V × 0.85 efficiency) = 73.5A.
  • NEC-Style Derating: For continuous loads (running 3 hours or more), conductors and overcurrent devices must be sized at 125% of the load. 73.5A × 1.25 = 91.8A.

You must select an inverter rated for at least 4000W continuous (with an 8000W surge capability) to safely handle the 3000W baseline plus transient spikes. The DC cabling from the battery to the inverter should be sized for 100A+ (typically 2/0 AWG copper for short runs to minimize voltage drop below 1%).

Integrating the Inverter into the IoT Mesh

Modern hybrid inverters (like the Victron MultiPlus-II or Growatt SPF series) feature RS485 or CAN bus ports. To integrate this into your ESP32 IoT node, you use the HW-519 RS485-to-TTL module. The ESP32 acts as a Modbus RTU master, polling the inverter’s internal registers every 2 seconds to extract AC output voltage, AC current, and internal MOSFET temperature.

Once the ESP32 aggregates the SmartShunt DC data, the SCT-013 AC data, and the BMS cell voltages, it formats the payload into a JSON object and publishes it via MQTT to a local broker (like Mosquitto running on a Raspberry Pi). A typical MQTT payload for this system looks like this:

{
  "timestamp": 1709234812,
  "pv_watts": 2450,
  "batt_soc": 84,
  "batt_voltage": 52.8,
  "batt_current": -45.2,
  "cell_min_mv": 3328,
  "cell_max_mv": 3331,
  "inv_ac_watts": 2850,
  "inv_temp_c": 42
}

By pushing this data to a dashboard like Home Assistant or Grafana, you transition from simply having a solar system to actively managing it. You can write automation scripts that trigger a 24V DC relay to shed non-essential loads (like a water heater) if the batt_soc drops below 20% or if the cell_min_mv approaches the BMS low-voltage cutoff threshold of 2800mV. This closed-loop telemetry is the defining feature of a true IoT solar power monitoring system, ensuring your hardware survives the worst weather while maximizing your lithium bank's cycle life.