The standard 25V analog voltage sensor module uses a simple passive resistive voltage divider (30kΩ and 7.5kΩ) to scale down high DC voltages into a 0-5V or 0-3.3V analog signal readable by a microcontroller's ADC. While it is the cheapest way to measure battery banks or solar strings, getting accurate readings requires understanding its analog output limits, scaling math, and susceptibility to noise.
The Voltage Sensor Working Principle
At its core, the voltage sensor working principle relies on Ohm's Law and a passive resistive voltage divider network. The ubiquitous red "25V" analog sensor module found in maker kits contains two precision resistors in series: a 30kΩ high-side resistor and a 7.5kΩ low-side resistor. When you apply a voltage across the input terminals (VCC and GND), the resistors divide the potential proportionally. Because 7.5kΩ is exactly one-quarter of the total 37.5kΩ resistance, the voltage at the junction (the output pin) is exactly 1/5th (or 20%) of the input voltage. This principle is foundational to basic DC circuit theory.
This passive scaling ensures that a maximum input of 25V is stepped down to a safe 5.0V, which perfectly matches the 5V ADC reference of an Arduino Uno. For 3.3V logic boards like the ESP32 or Raspberry Pi Pico, the maximum safe input drops to 16.5V (since 16.5V / 5 = 3.3V). There is no active amplification, no digital conversion on the module itself, and no internal microcontroller—it is purely a passive analog scaling circuit that outputs a continuous, varying voltage.
Output Signal, Wiring, and Pin Mapping
A common mistake beginners make is assuming this module outputs a digital signal or communicates via I2C/SPI. The output is strictly an analog voltage. You must connect the 'S' or 'AO' pin to an Analog-to-Digital Converter (ADC) pin on your microcontroller. The 'DO' (Digital Out) pin on some variants is tied to a raw LM393 comparator with a fixed threshold, which is useless for measuring exact voltage levels; ignore it for this application.
| Module Pin | Function | ESP32 DevKit V1 (3.3V) | Arduino Uno (5V) |
|---|---|---|---|
| VCC / IN+ | High-Side Voltage Input | Positive DC Source (Max 16.5V) | Positive DC Source (Max 25V) |
| GND / IN- | Ground Reference | Source GND + ESP32 GND | Source GND + Arduino GND |
| S / AO | Analog Output (Scaled) | GPIO 34 (ADC1_CH6) | A0 (ADC0) |
| DO | Digital Out (Comparator) | Not Connected | Not Connected |
The Raw-to-Unit Math: Scaling Analog Readings
Because the module outputs an analog voltage, the microcontroller's ADC converts it into a raw integer. To display the actual physical voltage, you must reverse the ADC conversion and then reverse the voltage divider ratio.
Arduino Uno (5V Logic, 10-bit ADC)
The Uno's ADC maps 0-5V to integer values between 0 and 1023. The resolution is 5.0V / 1024 = 0.00488V per step.
- Step 1 (ADC to Output Voltage):
V_out = (Raw_ADC * 5.0) / 1024.0 - Step 2 (Output to Input Voltage):
V_in = V_out * 5.0(The divider ratio multiplier) - Combined Formula:
V_in = (Raw_ADC * 25.0) / 1024.0
ESP32 DevKit V1 (3.3V Logic, 12-bit ADC)
The ESP32 maps 0-3.3V to integer values between 0 and 4095. However, as noted in the Espressif ESP32 ADC documentation, the internal ADC is non-linear and saturates around 3.1V. We use 3.3V for the theoretical math, but empirical calibration is mandatory.
- Step 1 (ADC to Output Voltage):
V_out = (Raw_ADC * 3.3) / 4096.0 - Step 2 (Output to Input Voltage):
V_in = V_out * 5.0 - Combined Formula:
V_in = (Raw_ADC * 16.5) / 4096.0
// ESP32 Oversampling Code Snippet for Noise Reduction
const int adcPin = 34;
const int numSamples = 64;
float readBatteryVoltage() {
uint32_t rawSum = 0;
for (int i = 0; i < numSamples; i++) {
rawSum += analogRead(adcPin);
}
float rawAvg = (float)rawSum / numSamples;
// Theoretical scaling for ESP32 12-bit
float vIn = (rawAvg * 16.5) / 4096.0;
return vIn;
}
Calibration and Interference Mitigation
If you build the circuit and measure a 12.0V car battery, your serial monitor might read 11.4V or 12.8V. This discrepancy is caused by resistor tolerance, ADC non-linearity, and electrical noise.
Calibration Protocol
The 30kΩ and 7.5kΩ resistors on cheap modules typically have a 1% to 5% tolerance. To calibrate, connect a known, stable DC voltage source (like a bench power supply or a freshly measured 12V battery) to the input. Measure the exact input voltage with a trusted digital multimeter. Read the raw ADC average from your microcontroller. Calculate your actual multiplier:
Actual_Multiplier = (Measured_V_In * 4096.0) / Raw_ADC_Avg (for ESP32). Replace the theoretical 16.5 / 4096.0 in your code with Actual_Multiplier.
Common Interference Sources
- High-Impedance EMI Pickup: The 37.5kΩ total resistance of the divider is relatively high. The ADC pin acts like an antenna, picking up 50/60Hz mains hum and switching noise from nearby DC-DC buck converters. Fix: Solder a 100nF (0.1µF) ceramic capacitor directly between the module's analog output pin and GND. This creates a hardware low-pass filter that shorts high-frequency noise to ground.
- Ground Loops: If the GND of the voltage source you are measuring and the GND of the microcontroller are not tied together at a single equipotential point, the ADC will measure the ground offset voltage as part of the signal. Always verify continuity between the source negative terminal and the microcontroller GND pin.
- ESP32 ADC Non-Linearity: The ESP32's internal ADC is notoriously inaccurate near 0V and above 3.0V. If your scaled voltage pushes the ADC pin above 3.0V (an input voltage > 15V), your readings will compress and flatten out. Keep your maximum expected input voltage scaled to roughly 2.8V at the ADC pin to stay in the linear region.
Decision Path: Which Voltage Sensing Method to Choose
The cheap red 25V module is fine for basic hobby projects, but it fails in precision or high-voltage scenarios. Use this decision tree to select the correct hardware for your specific application.
| Application Scenario | Required Accuracy | Recommended Hardware Approach |
|---|---|---|
| Basic 12V battery monitoring, visual LED indicators, cost < $2 | ±5% | Standard 25V Analog Module (Passive Divider) |
| AC Mains measurement (120V/230V RMS) for solar/grid logging | ±2% | ZMPT101B Active AC Voltage Sensor Module (Isolated Transformer) |
| Precision LiFePO4 cell logging, BMS integration, data recording | ±0.5% | External 16-bit I2C ADC + Custom Metal Film Divider |
| High-voltage DC strings (60V-100V) where ground isolation is required | ±1% | Hall-Effect Voltage Sensor (e.g., LV 25-P) or Isolated Amplifier (ISO2400) |
If you are building a solar charge controller, a precise battery monitor, or an ESP32 data logger where a 0.5V error matters, do not use the standard red 25V module. The internal ESP32 ADC and the module's 5% tolerance resistors will frustrate you.
Concrete Recommendation: Buy the Adafruit ADS1115 16-bit I2C ADC (Part No. 1085, ~$11.00) and build your own voltage divider on a protoboard using a 100kΩ and 33kΩ 1% metal film resistor pair (~$0.20). This combination bypasses the ESP32's noisy internal ADC, provides 16-bit resolution (32,768 steps), and yields lab-grade accuracy when paired with a simple software calibration offset. Use the Adafruit ADS1115 library for immediate I2C integration.






