Skip to main content

Monitoring Battery State via Meshtastic Telemetry

Meshtastic and MeshCore both include power telemetry features that allow a node to report its battery voltage and charge level over the mesh network. This page covers enabling these features, configuring voltage ADC pins for different hardware, interpreting voltage as state-of-charge for LiFePO4 batteries, setting low-battery alerts, and visualising data in Grafana.

Enabling Power Telemetry in Meshtastic

In Meshtastic firmware (2.x), power metrics are part of the Telemetry Module. To enable battery reporting:

Via Meshtastic Python CLI

# Install CLI: pip install meshtastic
# Enable device metrics (includes battery level, voltage, uptime)
meshtastic --set telemetry.device_update_interval 300
# Sets reporting interval to 300 seconds (5 minutes)

# Verify telemetry module is enabled
meshtastic --get telemetry

Via Meshtastic Web App or Mobile App

  1. Open the Meshtastic app and connect to your node.
  2. Navigate to Config → Module Config → Telemetry.
  3. Enable Device Metrics.
  4. Set the update interval (300 - 3600 seconds; use longer intervals for battery-powered nodes to reduce TX duty cycle).
  5. Save and reboot the node.

Once enabled, the node broadcasts a meshtastic.Telemetry protobuf packet on the default channel at the configured interval. The packet includes:

  • battery_level: Integer 0 - 100 (firmware-estimated SoC percentage)
  • voltage: Float in volts (actual measured ADC voltage)
  • channel_utilization: Float (% airtime used)
  • air_util_tx: Float (TX airtime)

Voltage ADC Pin Configuration on Different Boards

Not all Meshtastic hardware platforms use the same pin or divider ratio for battery voltage measurement. The firmware auto-detects the board type from compile-time defines, but custom builds or off-label hardware may need manual configuration.

Board ADC Pin (GPIO) Voltage Divider Ratio Max Measurable Voltage Notes
TTGO T-Beam v0.7 GPIO35 1:2 (100 kΩ / 100 kΩ) ~8.4 V Measures raw LiPo voltage
TTGO T-Beam v1.1 (AXP192) AXP192 PMIC register Internal PMIC ADC Reported via I²C Reads VBAT register; very accurate
TTGO LoRa32 v2.1 GPIO35 1:2 ~8.4 V Same as T-Beam v0.7
Heltec WiFi LoRa 32 v3 GPIO1 (ADC1_CH0) 1:1 (no divider; up to 3.3 V input only) 3.3 V max Only suitable for direct 3.3 V LiPo via USB-C charging; not for 12 V systems
RAK WisBlock RAK4631 GPIO5 (P0.05 / AIN3) 1:2 via RAK5005-O base board ~6 V Reads via nRF52840 SAADC
Wispr / Custom ESP32 User-defined GPIO User-defined User-defined Set in platformio.ini or via power.adc_multiplier_override config key

If the reported voltage seems incorrect, verify with a multimeter at the battery terminals. Then check power.adc_multiplier_override:

meshtastic --set power.adc_multiplier_override 2.0
# Multiplies the raw ADC reading by 2.0 (use for 1:2 divider boards)

Interpreting Voltage as State-of-Charge for LiFePO4

Meshtastic's built-in SoC estimation uses LiPo voltage thresholds (3.0 - 4.2 V per cell). For LiFePO4 packs, these thresholds are incorrect - LiFePO4 cells operate in the 2.5 - 3.65 V range. The firmware will report incorrect percentages unless you compensate.

LiFePO4 Single-Cell (3.2 V nominal) Voltage → SoC Table

Resting OCV (V) Approximate SoC (%) Interpretation
3.60 - 3.65100%Fully charged, absorb phase complete
3.40 - 3.4590%High charge, float plateau
3.30 - 3.3570 - 80%Mid-range - most of usable capacity here
3.27 - 3.3050%Flat region - voltage barely distinguishable from 70%
3.22 - 3.2530%Still flat; lower usable threshold approaching
3.18 - 3.2220%Low battery - alert threshold
3.10 - 3.1810%Critical - immediate recharge needed
< 3.10<5%BMS will soon disconnect; node will shut down

4S LiFePO4 Pack (12.8 V nominal) Voltage → SoC Table

Pack Voltage (V) SoC (%)
14.4 - 14.6100% (end of charge)
13.6 - 13.890%
13.2 - 13.470 - 80%
13.0 - 13.250%
12.8 - 13.030%
12.4 - 12.820%
12.0 - 12.410%
< 11.8<5% (BMS cutoff imminent)

Setting Low-Battery Alerts in Meshtastic

Meshtastic does not natively send alert messages when battery drops below a threshold, but there are two approaches to implement this:

Approach 1 - Node-Red / MQTT Alert Pipeline

  1. Configure Meshtastic MQTT uplink: meshtastic --set mqtt.enabled true --set mqtt.address YOUR_BROKER_IP
  2. In Node-Red, subscribe to msh/US/+/json/LongFast/# (adjust channel name as needed).
  3. Filter for msg.payload.decoded.telemetry.deviceMetrics.voltage below your LVD threshold.
  4. Route low-voltage events to an alert node (email, PushOver, Telegram bot).

Approach 2 - Meshtastic Python Script (Autonomous Node)

import meshtastic
import meshtastic.serial_interface
from meshtastic.mesh_pb2 import MeshPacket

iface = meshtastic.serial_interface.SerialInterface()
LOW_VOLTAGE_THRESHOLD = 3.18 # V per cell for LiFePO4 (20% SoC)

def on_receive(packet, interface):
 if "decoded" in packet and "telemetry" in packet["decoded"]:
 m = packet["decoded"]["telemetry"].get("deviceMetrics", {})
 voltage = m.get("voltage", 0)
 node_id = packet["fromId"]
 if voltage > 0 and voltage < LOW_VOLTAGE_THRESHOLD:
 print(f"LOW BATTERY: Node {node_id} at {voltage:.2f} V")
 # Send alert message on mesh
 iface.sendText(f"⚠ Low battery: {node_id} {voltage:.2f}V", wantAck=False)

iface.localNode.setOwner("MonitorNode")
iface.addReceiveObserver(on_receive)
input("Press Enter to exit\n")
iface.close()

MeshCore Telemetry Equivalent

MeshCore uses a similar but distinct telemetry structure. Battery reporting in MeshCore is enabled via the telemetry section in the node YAML configuration file:

telemetry:
 enabled: true
 interval_s: 300
 battery:
 adc_pin: 35
 adc_vref: 3.3
 divider_ratio: 2.0
 low_voltage_alert: 3.18

MeshCore publishes telemetry packets to MQTT in JSON format. Grafana can consume these via the Grafana MQTT data source plugin or via InfluxDB (Node-Red → InfluxDB → Grafana).

Graphing Battery Data in Grafana

Architecture

Meshtastic Node
 │ (MQTT telemetry JSON)
 ▼
Mosquitto MQTT Broker
 │
 ▼
Node-Red (parse JSON → extract voltage/SoC → write to InfluxDB)
 │
 ▼
InfluxDB 2.x (time-series storage)
 │
 ▼
Grafana (dashboards, alerts)

InfluxDB Line Protocol (Node-Red write node)

measurement: node_battery
tags: node_id, node_name, location
fields: voltage (float), battery_pct (int), soc_lifepo4 (float)
timestamp: nanosecond UNIX timestamp from packet

Grafana Panel Configuration

  • Battery voltage time series: Use a Time Series panel with threshold bands - green above 3.30 V, yellow 3.18 - 3.30 V, red below 3.18 V (per cell) or scale for your pack voltage.
  • Multi-node SoC gauge: Use a Gauge panel per node with min=0, max=100, thresholds at 20% (red) and 40% (yellow).
  • Grafana Alerting: Set an alert rule on avg(voltage) < 3.18 for any node, with a 15-minute evaluation window (to avoid false alarms from momentary load spikes). Route to PagerDuty, Slack, or email.

A complete Grafana dashboard JSON template for Meshtastic power monitoring is maintained in the Mesh America GitHub repository under monitoring/dashboards/meshtastic-power.json.