The ACS712 measures current with a Hall-effect sensor: the current passes through a copper path in the chip, and the output voltage moves away from 2.5 V in proportion. It is a common choice for solar, battery and motor projects.
On the ESP32 DevKit V1 the module needs 5 V on VIN, and its output must go through a 10 kΩ / 20 kΩ divider into D35 because it swings above 3.3 V. The sketch measures the zero point at boot, averages 200 calibrated readings, and prints current and power for a 12 V DC load.
Wiring
| ESP32 DevKit V1 | ACS712 current sensor (5 A / 20 A / 30 A) | Wire | Notes |
|---|---|---|---|
| — | IP+ | — | To 12 V DC supply (+) (not drawn) |
| — | IP- | — | To 12 V DC load (+), e.g. LED strip or small pump; load (−) back to the supply (−) (not drawn) |
| VIN | VCC | red | The ACS712 needs 4.5–5.5 V. VIN is 5 V when the board runs from USB. |
| GND | GND | black | |
| D35 | OUT | yellow | Via 10 kΩ / 20 kΩ divider — 10 kΩ from OUT to D35, 20 kΩ from D35 to GND. 2.5 V at 0 A becomes 1.67 V; the sketch multiplies by 1.5. |
5 V (4.5–5.5 V) part, 3.3 V board. OUT sits at VCC/2 (2.5 V) at zero current and swings towards 0 or 5 V. On ESP32/Pico, scale OUT with a divider (e.g. 10 kΩ / 20 kΩ) and account for it in code.
Board quirks
- OUT idles at VCC/2 (2.5 V) and swings up to about 4.5 V at full current — above the ESP32’s 3.3 V limit. The 10 kΩ / 20 kΩ divider keeps the whole swing between about 0.3 V and 3.0 V, inside the ADC’s accurate window.
- The zero point moves with the 5 V supply (the sensor is ratiometric) and with temperature, so the sketch measures it at boot. Start it with the load switched off.
- A 5 A ACS712 gives 185 mV/A; after the divider that is about 123 mV/A at the pin, and the ESP32 ADC is noisy by ±10–20 mV. Expect about ±0.1 A resolution, even with the 200-sample average. For small currents (under 1 A) use an INA219 on I2C instead.
- D35 is on ADC1 and input-only — right for an analog sensor and unaffected by Wi-Fi, so you can add a power dashboard later.
- This guide is low-voltage DC only. Putting the ACS712’s screw terminals in a 230 V circuit is electrician-only work: the cheap modules have small gaps between the mains and logic tracks. For mains current use a non-invasive CT clamp (SCT-013) or a PZEM-004T installed by an electrician.
Code
// ACS712 current sensor (5 A version) on an ESP32 DevKit V1, measuring a 12 V DC load.
// VCC → VIN (5 V), GND → GND, OUT → 10 kΩ → D35 (GPIO35), 20 kΩ from D35 to GND.
// The divider turns OUT (2.5 V ± 185 mV/A) into 1.67 V ± 123 mV/A at the pin.
// Start it with NO current flowing — the zero point is measured at boot.
constexpr uint8_t CUR_PIN = 35; // ADC1_CH7, input-only — works with Wi-Fi on
constexpr float DIVIDER = 1.5f; // (10 kΩ + 20 kΩ) / 20 kΩ
constexpr float MV_PER_A = 185.0f; // 5 A: 185, 20 A: 100, 30 A: 66 (read the chip marking)
float zeroMv = 2500; // OUT at 0 A, measured in setup()
float readOutMv(int samples) {
uint32_t sum = 0;
for (int i = 0; i < samples; i++) sum += analogReadMilliVolts(CUR_PIN);
return sum / (float)samples * DIVIDER; // millivolts at the module's OUT pin
}
void setup() {
Serial.begin(115200);
delay(500);
zeroMv = readOutMv(500);
Serial.printf("ACS712 on GPIO35 — zero at %.0f mV (keep the load off during start-up)\n", zeroMv);
}
void loop() {
float mv = readOutMv(200); // averaging tames the ESP32 ADC noise
float amps = (mv - zeroMv) / MV_PER_A;
if (fabsf(amps) < 0.05f) amps = 0; // below the noise floor of a 5 A sensor
Serial.printf("OUT %.0f mV Current %.2f A (≈ %.1f W at 12 V)\n", mv, amps, amps * 12.0f);
delay(1000);
}// ACS712 current sensor (5 A version) on an ESP32 DevKit V1, measuring a 12 V DC load.
// VCC → VIN (5 V), GND → GND, OUT → 10 kΩ → D35 (GPIO35), 20 kΩ from D35 to GND.
// The divider turns OUT (2.5 V ± 185 mV/A) into 1.67 V ± 123 mV/A at the pin.
// Start it with NO current flowing — the zero point is measured at boot.
constexpr uint8_t CUR_PIN = 35; // ADC1_CH7, input-only — works with Wi-Fi on
constexpr float DIVIDER = 1.5f; // (10 kΩ + 20 kΩ) / 20 kΩ
constexpr float MV_PER_A = 185.0f; // 5 A: 185, 20 A: 100, 30 A: 66 (read the chip marking)
float zeroMv = 2500; // OUT at 0 A, measured in setup()
float readOutMv(int samples) {
uint32_t sum = 0;
for (int i = 0; i < samples; i++) sum += analogReadMilliVolts(CUR_PIN);
return sum / (float)samples * DIVIDER; // millivolts at the module's OUT pin
}
void setup() {
Serial.begin(115200);
delay(500);
zeroMv = readOutMv(500);
Serial.printf("ACS712 on GPIO35 — zero at %.0f mV (keep the load off during start-up)\n", zeroMv);
}
void loop() {
float mv = readOutMv(200); // averaging tames the ESP32 ADC noise
float amps = (mv - zeroMv) / MV_PER_A;
if (fabsf(amps) < 0.05f) amps = 0; // below the noise floor of a 5 A sensor
Serial.printf("OUT %.0f mV Current %.2f A (≈ %.1f W at 12 V)\n", mv, amps, amps * 12.0f);
delay(1000);
}Expected serial output
ACS712 on GPIO35 — zero at 2497 mV (keep the load off during start-up)
OUT 2499 mV Current 0.00 A (≈ 0.0 W at 12 V)
OUT 2721 mV Current 1.21 A (≈ 14.5 W at 12 V)
OUT 2885 mV Current 2.10 A (≈ 25.2 W at 12 V)ACS712 on GPIO35 — zero at 2497 mV (keep the load off during start-up) OUT 2499 mV Current 0.00 A (≈ 0.0 W at 12 V) OUT 2721 mV Current 1.21 A (≈ 14.5 W at 12 V) OUT 2885 mV Current 2.10 A (≈ 25.2 W at 12 V)
Common errors
Shows 0.3–0.5 A with nothing connected
The zero was taken while current was flowing, or the 5 V supply changed after boot. Switch the load off and press EN to re-measure.
Current reads negative
The current flows from IP- to IP+. Swap the two load wires on the screw terminals, or accept the sign.
Readings capped at a certain current
The divider is missing or reversed and OUT is clipping at the ADC’s 3.1 V limit. Check 10 kΩ is from OUT to D35 and 20 kΩ from D35 to GND.