ESP32 MicroPython ACS712 Current Sensor

This tutorial instructs you how to use the ACS712 current sensor with the ESP32 and MicroPython. In detail, we will learn:

ESP32 MicroPython and ACS712 current sensor module

Overview of ACS712 Current Sensor

Want to know how much power a motor, a lamp or a heater really takes? The ACS712 tells you the current in one wire of that device. The current runs through a thick copper strip inside the chip. Any current makes a magnetic field, and a Hall sensor that sits next to the strip turns this field into a voltage. The copper strip has no electrical link to the sensor side (it is isolated up to 2.1 kV RMS), so the ESP32 stays separated from the measured circuit. The strip is only about 1.2 mΩ, so it barely changes how your device works.

The chip comes in three versions. They look the same, but the sensitivity is different:

Version Current range Sensitivity
ACS712 5A -5A to +5A 185 mV per amp
ACS712 20A -20A to +20A 100 mV per amp
ACS712 30A -30A to +30A 66 mV per amp

This tutorial uses the 30A version (chip ACS712ELCTR-30A-T). Its main data:

Item ACS712 30A
Supply voltage 5V (4.5V to 5.5V), not 3.3V
Current range -30A to +30A, DC and AC
Output at 0A about 2.5V (half of the supply)
Output at +30A / -30A about 4.48V / about 0.52V
Sensitivity 66 mV per amp
Output type ratiometric (follows the real supply voltage)
Bandwidth 80 kHz
Total output error about ±1.5% at 25°C
Isolation 2.1 kV RMS

Pinout

ACS712 current sensor pinout

The module has a 3-pin header on one side:

  • VCC pin: connect to 5 volts. On the ESP32 board, this is the VIN pin when the board runs from USB.
  • GND pin: connect to GND (0 volts).
  • OUT pin: the analog output. It gives about 2.5 volts with no current, and up to about 4.5 volts at full current. This is too high for an ESP32 pin, so it goes through a divider (see below).

On the other side, there is a 2-pin screw terminal (often marked IP+ and IP−, sometimes not marked at all). These two screws go IN SERIES with your load: cut one supply wire of the device and put the terminal in the gap. A current that flows from IP+ to IP− gives a positive value. The module also has a power LED.

How the Voltage Becomes Amps

When no current flows, OUT sits in the middle, at about 2.5 volts. We call this the zero point. Current in one direction raises the voltage, and current in the other direction lowers it, by 66 mV for each amp. So the formula is:

current (A) = (Vout − Vzero) ÷ 0.066

For example, if OUT is 2.581 volts and the zero point is 2.508 volts, the current is 0.073 ÷ 0.066 = about 1.1 A.

The zero point is never exactly 2.5 volts. It changes a little from one module to another and with the real 5 volts supply. That is why the code measures it at startup, while the load is OFF, by averaging 1000 readings.

Also keep in mind: the 30A version is made for big currents. On the ESP32, one ADC step is about 18 mA after the divider, and a noise of 50 to 100 mA at 0 A is normal. It works best for loads of about 0.5 A and more, such as motors, lamps, LED strips, heaters and chargers. If you only need small currents, the 5A version is a better pick.

Wiring Diagram

The ACS712 needs 5 volts, so we power it from the VIN pin of the ESP32 (5 volts from USB). But its OUT pin can reach about 4.5 volts, and an ESP32 pin must stay at 3.3 volts or less. A simple voltage divider fixes this: OUT → 10kΩ → GPIO36 → 20kΩ → GND. The pin now sees only two thirds of the voltage (4.5 volts becomes 3.0 volts). The code multiplies the reading by 1.5 to get the real value back.

We use GPIO36 because it belongs to ADC1. The ADC2 pins stop working when WiFi is on, so ADC1 is the safer choice for later projects.

From To
ACS712 VCC ESP32 VIN (5V)
ACS712 GND ESP32 GND
ACS712 OUT 10kΩ resistor, then ESP32 GPIO36
ESP32 GPIO36 20kΩ resistor, then ESP32 GND
12V adapter + (through DC power jack) ACS712 IP+
ACS712 IP− DC device + wire
DC device − wire 12V adapter − (through DC power jack)
  • How to connect ESP32 and ACS712 current sensor using breadboard
The wiring diagram between ESP32 MicroPython ACS712 current sensor

This image is created using Fritzing. Click to enlarge image

How to connect ESP32 and ACS712 current sensor

※ NOTE THAT:

Mains AC (110V or 220V) can kill. If you are a beginner, practice with a low voltage DC load like the 12V DC device in this tutorial. The screw terminal side of the module carries the full voltage of the load. Never touch the screws or the load wires while a mains circuit is live.

ESP32 MicroPython Code - Measure DC Current

No library is needed. The script uses machine.ADC, which is built into MicroPython. It reads the pin with read_uv(). This function gives the voltage in microvolts and uses the factory calibration stored in the ESP32 chip, so it is more correct than turning the raw read() value into volts by hand.

What the script does:

  • It reads GPIO36 with 11 dB attenuation, so the pin can measure up to about 3.3 volts.
  • It multiplies each reading by 1.5 to undo the divider.
  • At startup, it averages 1000 readings to find the zero point. The load must be OFF at this moment.
  • Then, every 500 ms, it averages 200 readings and turns the voltage into amps with the formula above.
""" This ESP32 MicroPython code was developed by newbiely.com This ESP32 MicroPython code is made available for public use without any restriction For comprehensive instructions and wiring diagrams, please visit: https://newbiely.com/tutorials/esp32-micropython/esp32-micropython-acs712-current-sensor """ from machine import ADC, Pin import time SENSOR_PIN = 36 # ESP32 GPIO36 (ADC1) connected to the middle of the 10k/20k divider on the ACS712 OUT pin SENSITIVITY = 0.066 # ACS712 30A version: 66 mV (0.066 V) per amp DIVIDER_RATIO = 1.5 # The 10k/20k divider makes the voltage 2/3 smaller, so multiply by 1.5 to undo it SAMPLES = 200 # Number of readings averaged for each printed value adc = ADC(Pin(SENSOR_PIN)) adc.atten(ADC.ATTN_11DB) # Allow the pin to read up to about 3.3V def read_sensor_volts(): # read_uv() returns the calibrated pin voltage in microvolts pin_volts = adc.read_uv() / 1000000 # Undo the divider to get the real voltage on the ACS712 OUT pin return pin_volts * DIVIDER_RATIO def average_volts(count): total = 0 for _ in range(count): total += read_sensor_volts() return total / count # Find the zero point. The load MUST be OFF while this runs. print("Calibrating zero point, keep the load OFF...") zero_volts = average_volts(1000) print("Zero point: {:.3f} V".format(zero_volts)) while True: sensor_volts = average_volts(SAMPLES) # Current = voltage change from the zero point / sensitivity current = (sensor_volts - zero_volts) / SENSITIVITY print("Sensor: {:.3f} V | Current: {:.2f} A".format(sensor_volts, current)) time.sleep_ms(500)

Detailed Instructions

Here's instructions on how to set up and run your MicroPython code on the ESP32 using Thonny IDE:

  • Make sure Thonny IDE is installed on your computer.
  • Confirm that MicroPython firmware is loaded on your ESP32 board. Use a recent version, because read_uv() does not exist in very old firmware.
  • If you are new to MicroPython on the ESP32, read the ESP32 MicroPython Getting Started guide first.
  • Wire the ACS712, the two resistors, the 12V DC device (such as a DC motor, LED strip or lamp) and the DC power jack to the ESP32 board according to the provided diagram.
  • Switch the load OFF: leave the 12V adapter unplugged for now.
  • Connect the ESP32 board to your computer with a USB cable.
  • Open Thonny IDE on your computer.
  • In Thonny, go to Tools Options, open the Interpreter tab, and choose MicroPython (ESP32) from the dropdown.
  • Copy the provided MicroPython code and paste it into Thonny's editor.
  • Save the code to your ESP32 by:
    • Clicking the Save button or pressing Ctrl+S.
    • Choosing MicroPython device in the save dialog.
    • Typing main.py as the file name.
  • Click the green Run button (or press F5) to execute the script.
  • Wait until the Shell shows the zero point. Then plug in the 12V adapter, so the DC device turns on.
  • If your DC device is a motor, hold its shaft lightly with your fingers for a moment. The current goes up when the motor works harder.
  • Check out the message in the Shell at the bottom of Thonny.
Shell x
>>> %Run -c $EDITOR_CONTENT
MPY: soft reboot Calibrating zero point, keep the load OFF... Zero point: 2.508 V Sensor: 2.510 V | Current: 0.03 A Sensor: 2.505 V | Current: -0.05 A Sensor: 2.509 V | Current: 0.02 A Sensor: 2.561 V | Current: 0.80 A Sensor: 2.574 V | Current: 1.00 A Sensor: 2.570 V | Current: 0.94 A Sensor: 2.603 V | Current: 1.44 A Sensor: 2.611 V | Current: 1.56 A Sensor: 2.572 V | Current: 0.97 A
MicroPython (ESP32) • CP2102 USB To UART Bridge Controller @ COM12 ≡

Here, the DC device is a 12V DC motor. The first lines show the noise while it is off: a few hundredths of an amp, up or down. That is normal for the 30A version. When the motor runs, the current is about 0.8 to 1 A, and it climbs higher while you slow the shaft with your fingers.

Is the current negative while the DC device runs? The current goes through the module the other way. Swap the two wires on the screw terminal, or just ignore the minus sign.

If you name your script main.py and save it to the MicroPython device, it will run automatically every time the ESP32 is powered on.

※ NOTE THAT:

The ESP32 ADC is not very linear near the top of its range. With the divider, the pin goes above about 2.5 volts only for currents of roughly +19 A or more, so normal loads stay in the good part of the range. For lab-grade results, use an external ADC such as the ADS1115.

Measuring AC Current

With AC, the current changes direction many times every second (50 or 60 times, depending on your country). The OUT voltage swings above and below the zero point, so a plain average would come out close to 0 A. Instead, we use the RMS value, which is the number written on AC devices and meters:

  • Sample the sensor as fast as possible for 200 ms. This covers 10 full cycles at 50 Hz, or 12 cycles at 60 Hz.
  • For each sample, take the difference from the zero point and square it.
  • Take the mean of all the squares, then the square root. This is the RMS voltage.
  • Divide by 0.066 to get the RMS current in amps.

The wiring stays the same. The only change: the screw terminal now sits in series with one wire of an AC device, for example the live wire of a hair dryer cable.

※ NOTE THAT:

Only work on mains wiring if you know how to do it safely. Unplug the device before you touch the screw terminal, and close everything in a box before you plug it back in. If you are not sure, keep using the 12V DC load.

ESP32 MicroPython Code - Measure AC Current

""" This ESP32 MicroPython code was developed by newbiely.com This ESP32 MicroPython code is made available for public use without any restriction For comprehensive instructions and wiring diagrams, please visit: https://newbiely.com/tutorials/esp32-micropython/esp32-micropython-acs712-current-sensor """ from machine import ADC, Pin import time import math SENSOR_PIN = 36 # ESP32 GPIO36 (ADC1) connected to the middle of the 10k/20k divider on the ACS712 OUT pin SENSITIVITY = 0.066 # ACS712 30A version: 66 mV (0.066 V) per amp DIVIDER_RATIO = 1.5 # The 10k/20k divider makes the voltage 2/3 smaller, so multiply by 1.5 to undo it WINDOW_MS = 200 # 200 ms = 10 cycles at 50 Hz, 12 cycles at 60 Hz adc = ADC(Pin(SENSOR_PIN)) adc.atten(ADC.ATTN_11DB) # Allow the pin to read up to about 3.3V def read_sensor_volts(): # read_uv() returns the calibrated pin voltage in microvolts return adc.read_uv() / 1000000 * DIVIDER_RATIO def read_rms_current(): sum_squares = 0 count = 0 start = time.ticks_ms() # Sample as fast as possible during the whole time window while time.ticks_diff(time.ticks_ms(), start) < WINDOW_MS: diff = read_sensor_volts() - zero_volts sum_squares += diff * diff count += 1 # RMS voltage = square root of the mean of the squares rms_volts = math.sqrt(sum_squares / count) return rms_volts / SENSITIVITY # Find the zero point. The load MUST be OFF while this runs. print("Calibrating zero point, keep the load OFF...") total = 0 for _ in range(1000): total += read_sensor_volts() zero_volts = total / 1000 print("Zero point: {:.3f} V".format(zero_volts)) while True: current_rms = read_rms_current() print("AC current (RMS): {:.2f} A".format(current_rms)) time.sleep_ms(500)

Detailed Instructions

  • Make sure the AC device is unplugged, then copy the code above and paste it into Thonny's editor.
  • Save it to your ESP32 as main.py.
  • Click the green Run button (or press F5) and wait for the zero point.
  • Plug in the AC device and switch it on. Keep your hands away from the module.
  • Check out the message in the Shell at the bottom of Thonny.
Shell x
>>> %Run -c $EDITOR_CONTENT
MPY: soft reboot Calibrating zero point, keep the load OFF... Zero point: 2.511 V AC current (RMS): 0.09 A AC current (RMS): 0.08 A AC current (RMS): 2.63 A AC current (RMS): 2.61 A AC current (RMS): 2.64 A AC current (RMS): 2.60 A
MicroPython (ESP32) • CP2102 USB To UART Bridge Controller @ COM12 ≡

This sample comes from a small hair dryer of about 600 W on a 230 V line, so about 2.6 A is the expected value. With the device off, the RMS value is not exactly zero. The noise also gets squared, so it always adds a small positive amount, here about 0.08 A. Values below about 0.15 A mean "nothing is running".

Video Tutorial

※ OUR MESSAGES

  • As freelancers, We are AVAILABLE for HIRE. See how to outsource your project to us
  • Please feel free to share the link of this tutorial. However, Please do not use our content on any other websites. We invested a lot of effort and time to create the content, please respect our work!