This tutorial shows how to read analog values with the ESP32 and ESP8266 boards using MicroPython firmware. As an example, we’ll read the values from a potentiometer.
Getting analog readings with ESP32 and ESP8266 is a bit different, so there is a section for each board in this tutorial.
Prerequisites
To follow this tutorial you need MicroPython firmware installed in your ESP32 or ESP8266 boards. You also need an IDE to write and upload the code to your board. We suggest using Thonny IDE or uPyCraft IDE:
- Thonny IDE:
- uPyCraft IDE:
- Install uPyCraft IDE (Windows, Mac OS X, Linux)
- Flash/Upload MicroPython Firmware to ESP32 and ESP8266
Analog Readings – ESP8266
ESP8266 only has one analog pin called A0. The ESP8266 analog pin has 10-bit resolution. It reads the voltage from 0 to 3.3V and then, assigns a value between 0 and 1023.
Note: some versions of the ESP8266 only read a maximum of 1V on the ADC pin. Make sure you don’t exceed the maximum recommended voltage for your board.
Analog Readings – ESP32
There are several pins on the ESP32 that can act as analog pins – these are called ADC pins. All the following GPIOs can act as ADC pins: 0, 2, 4, 12, 13, 14, 15, 25, 26, 27, 32, 33, 34, 35, 36, and 39.
Learn more about the ESP32 GPIOs: ESP32 Pinout Reference: Which GPIO pins should you use?
ESP32 ADC pins have 12-bit resolution by default. These pins read voltage between 0 and 3.3V and then return a value between 0 and 4095. The resolution can be changed on the code. For example, you may want to have just 10-bit resolution to get a value between 0 and 1023.
The following table shows some differences between analog reading on the ESP8266 and the ESP32.
ESP8266 | ESP32 | |
Analog pins | A0 (ADC 0) | GPIOs: 0, 2, 4, 12, 13, 14, 15, 25, 26, 27, 32, 33, 34, 35, 36, and 39. |
Resolution | 10-bit (0-1023) | 12-bit (0-4095) |
Change resolution | No | Yes |
Schematic
Analog reading works differently in ESP32 and ESP8266. There is a different schematic and a different script for each board.
To follow this tutorial, you need to wire a potentiometer to your ESP8266 or ESP32 board.
Parts Required
Here’s a list of the parts to you need to build the circuit:
You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!
Schematic – ESP32
Follow the next schematic diagram if you’re using an ESP32 board:
In this example we’re using GPIO 34 to read analog values from the potentiometer, but you can choose any other GPIO that supports ADC. Read our ESP32 Pinout Guide to learn more about the ESP32 GPIOs.
Schematic – ESP8266
Follow the next schematic diagram if you’re using an ESP8266 board:
The ESP8266 supports analog reading only on the A0 pin.
Script
There are a few differences when it comes to analog reading in ESP32 and ESP8266 regarding the code. You should write a slightly different script depending on the board you’re using. Make sure you follow the code for your specific board.
Script – ESP32
The following script for the ESP32 reads analog values from GPIO 34.
# Complete project details at https://RandomNerdTutorials.com/micropython-programming-with-esp32-and-esp8266/
from machine import Pin, ADC
from time import sleep
pot = ADC(Pin(34))
pot.atten(ADC.ATTN_11DB) #Full range: 3.3v
while True:
pot_value = pot.read()
print(pot_value)
sleep(0.1)
How the code works
To read analog inputs, import the ADC class in addition to the Pin class from the machine module. We also import the sleep method.
from machine import Pin, ADC
from time import sleep
Then, create an ADC object called pot on GPIO 34.
pot = ADC(Pin(34))
The following line defines that we want to be able to read voltage in full range.
pot.atten(ADC.ATTN_11DB)
This means we want to read voltage from 0 to 3.3V. This corresponds to setting the attenuation ratio of 11db. For that, we use the atten() method and pass as argument: ADC.ATTN_11DB.
The atten() method can take the following arguments:
- ADC.ATTN_0DB — the full range voltage: 1.2V
- ADC.ATTN_2_5DB — the full range voltage: 1.5V
- ADC.ATTN_6DB — the full range voltage: 2.0V
- ADC.ATTN_11DB — the full range voltage: 3.3V
In the while loop, read the pot value and save it in the pot_value variable. To read the value from the pot, simply use the read() method on the pot object.
pot_value = pot.read()
Then, print the pot value.
print(pot_value)
At the end, add a delay of 100 ms.
sleep(0.1)
When you rotate the potentiometer, you get values from 0 to 4095 – that’s because the ADC pins have a 12-bit resolution by default. You may want to get values in other ranges. You can change the resolution using the width() method as follows:
ADC.width(bit)
The bit argument can be one of the following parameters:
- ADC.WIDTH_9BIT: range 0 to 511
- ADC.WIDTH_10BIT: range 0 to 1023
- ADC.WIDTH_11BIT: range 0 to 2047
- ADC.WIDTH_12BIT: range 0 to 4095
For example:
ADC.width(ADC.WIDTH_12BIT)
In summary:
- To read an analog value you need to import the ADC class;
- To create an ADC object simply use ADC(Pin(GPIO)), in which GPIO is the number of the GPIO you want to read the analog values;
- To read the analog value, simply use the read() method on the ADC object.
Script – ESP8266
The following script for the ESP8266 reads analog values from A0 pin.
# Complete project details at https://RandomNerdTutorials.com/micropython-programming-with-esp32-and-esp8266/
from machine import Pin, ADC
from time import sleep
pot = ADC(0)
while True:
pot_value = pot.read()
print(pot_value)
sleep(0.1)
How the code works
To read analog inputs, import the ADC class in addition to the Pin class from the machine module. We also import the sleep method.
from machine import Pin, ADC
from time import sleep
Then, create an ADC object called pot on A0 pin.
pot = ADC(0)
Note: ADC0 (A0) is the only pin on the ESP8266 that supports analog reading.
In the loop, read the pot value and save it in the pot_value variable. To read the value from the pot, use the read() method on the pot object.
pot_value = pot.read()
Then, print the pot_value.
print(pot_value)
At the end, add a delay of 100 ms.
sleep(0.1)
In summary:
- To read an analog value you use the ADC class;
- To create an ADC object simply call ADC(0). The ESP8266 only supports ADC reading on A0 pin.
- To read the analog value, use the read() method on the ADC object.
Demonstration
After saving the code to your ESP board using Thonny IDE or uPyCraft IDE, rotate the potentiometer.
Check the shell of your MicroPython IDE to read the values from the potentiometer. If you’re using an ESP32 you should get readings between 0 and 4095 — or readings between 0 and 1023 with an ESP8266.
Wrapping Up
In this tutorial we’ve shown you how to read analog values using MicroPython with the ESP32 and ESP8266 boards. There are several GPIOs on the ESP32 that can read analog values. On the other side, the ESP8266 only supports analog readings on the A0 (ADC0) pin.
Reading analog values with the ESP32 and ESP8266 is slightly different, but in summary, you need to create an ADC object, and then use the read() method to get the values.
We hope you’ve found this tutorial useful. If you’re just getting started with MicroPython, you may also like the following resources:
- [eBook] MicroPython Programming with EPS32/ESP8266
- ESP32/ESP8266 GPIOs Explained with MicroPython
- ESP32/ESP8266 Digital Inputs and Digital Outputs with MicroPython
- ESP32/ESP8266 PWM with MicroPython – Dim LED
- ESP32/ESP8266 MicroPython Web Server – Control Outputs
Thanks for reading.
Measurements was not consistent till we made 20K runs and average.
Code:
from machine import Pin, ADC
from time import sleep
pot = ADC(Pin(34)) # use your pin number
pot.atten(ADC.ATTN_11DB) #Full range: 3.3v
myfloat = 0.0
number_of_runs = 20000
for x in range(number_of_runs):
pot_value = pot.read()
myfloat = myfloat + pot_value
if x == 20000:
break
myfloat = myfloat / 20000
print()
print(myfloat)
Hi.
Thanks for sharing that.
You can read more about the inaccuracy of the ESP32 ADC here: https://rntlab.com/question/the-adc-seems-terrible/
Regards,
Sara
What I realized, that board measure correct voltage, just wires needs to be shielded and grounded. Even voltmeter wires introduces a lot of noise. Input pin wire needs to be shielded and shield grounded.
Hello, i have to say that the one above is a very well written tutorial and conteins a lot of useful concepts…
but i have a problem… when i run the code the first print is correct but then it always prints the max value of the potentiometer 4095… what should i do?
Hi.
Double-check the connections of your circuit.
Regards,
Sara
Hi,
I’m using the ESP-32 to mesure voltages in the order of uV (microvolts) so I have to use the intern amplifyer. Does anyone knows how to configure it?
hi
the shell display of Thonny editor is showing random values i.e even the resistance has not been changed , the values keep changing according to the timer ..any advise plz
You need to ‘earth’ the pot casing to the 0 volt pin to get rid of the noise
I abandoned esp32 and bought commercial plc from China. Day and night difference as plc has opto chip on ADC