Both ESP8266-12E and ESP8266-07 have one ADC pin that is easily accessible. This means that those ESP8266 boards can read analog signals. In this tutorial we’ll show you how to use analog reading with the ESP8266 using Arduino IDE, MicroPython or Lua firmware.
As an example, we’ll show you how to read analog values from a potentiometer. This post is divided in three sections:
- ESP8266 Analog Read with Arduino IDE
- ESP8266 Analog Read with MicroPython
- ESP8266 Analog Read with Lua/NodeMCU
ESP8266 ADC Specifications
When referring to the ESP8266 ADC pin you will often hear these different terms interchangeably:
- ADC (Analog-to-digital Converter)
- TOUT
- Pin6
- A0
- Analog Pin 0
All these terms refer to the same pin in the ESP8266 that is highlighted in the next section.
ESP8266 ADC Resolution
The ADC pin has a 10-bit resolution, which means you’ll get values between 0 and 1023.
ESP8266 Input Voltage Range
The ESP8266 ADC pin input voltage range is 0 to 1V if you’re using the bare chip. However, most ESP8266 development boards come with an internal voltage divider, so the input range is 0 to 3.3V. So, in sumary:
- ADC Voltage range in ESP8266 development boards: 0 to 3.3V (for example: ESP8266 12-E NodeMCU Kit, WeMos D1 Mini, …)
- ADC Voltage range in ESP8266 chip: 0 to 1V (for example: ESP-07 chip, ESP-12E chip, …)
ESP8266 NodeMCU Analog Pin
With the ESP8266 12-E NodeMCU kit and other ESP8266 development boards, it is very easy to access the A0, you simply connect a jumper wire to the pin (see figure below).
If you’re using an ESP8266 chip, like the ESP8266-07, you need to solder a wire to that pin.
Parts Required
To show you how to use analog reading with the ESP8266, we’ll read the values from a potentiometer. For that, you need to wire a potentiometer to your board.
Here’s the hardware that you need to complete this tutorial:
- Recommended: ESP8266-12E NodeMCU Kit (read ESP8266 development boards comparison)
- Alternative: 1x ESP8266-07 chip or 1x ESP8266-12E chip + FTDI Programmer
- 100 Ohm Resistor (needed if you’re using a bare chip)
- 220 Ohm Resistor(needed if you’re using a bare chip)
- 1k Ohm Potentiometer
- Breadboard
- Jumper wires
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 Diagram
If you’re using an ESP8266 development board, follow the next schematic diagram.
If you’re using an ESP8266 chip with input voltage range of 0V to 1V, you need to make sure that the input voltage on the A0 pin doesn’t exceed 1V. So, you need a voltage divider circuit, as shown below.
We’re using a 100 Ohm and a 220 Ohm resistor, so that the Vout is 1V.
Recommend reading: ESP8266 Pinout Reference: Which GPIO pins should you use?
1. ESP8266 NodeMCU Analog Read with Arduino IDE
This section shows how to read analog values with the ESP8266 using Arduino IDE.
Install ESP8266 in Arduino IDE
In order to upload code to your ESP8266, you need to install the ESP8266 add-on first, if you haven’t already. Follow the next tutorial:
Code
Copy the following code to your Arduino IDE.
/*********
Rui Santos
Complete project details at https://randomnerdtutorials.com
*********/
const int analogInPin = A0; // ESP8266 Analog Pin ADC0 = A0
int sensorValue = 0; // value read from the pot
void setup() {
// initialize serial communication at 115200
Serial.begin(115200);
}
void loop() {
// read the analog in value
sensorValue = analogRead(analogInPin);
// print the readings in the Serial Monitor
Serial.print("sensor = ");
Serial.print(sensorValue);
delay(1000);
}
The code starts by declaring the ESP8266 analog pin in the analogInPin variable:
const int analogInPin = A0; // ESP8266 Analog Pin ADC0 = A0
The potentiometer value will be stored on the sensorValue variable:
int sensorValue = 0; // value read from the pot
In the setup(), initialize the Serial Monitor for debugging purposes:
void setup() {
// initialize serial communication at 115200
Serial.begin(115200);
}
In the loop(), we read the analog value by using the analogRead() function and passing the analogInPin as an argument. The value is saved on the sensorValue variable:
sensorValue = analogRead(analogInPin);
Finally, the readings are displayed on the Serial Monitor, so that you can actually see what is going on.
Serial.print(sensorValue);
Uploading the Code
Upload the previous code to the ESP8266. Make sure you have the right board and COM port select. Go to Tools> Board and select the ESP8266 model you’re using. In our case, we’re using the ESP8266 12-E NodeMCU Kit.
Go to Tools > Port and select the COM port the ESP8266 is connected to.
Press the Arduino IDE upload button.
Note: if you’re using an ESP-07 or ESP-12E chip, you need an FTDI programmer to upload code.
Demonstration
After uploading the code, open the Serial Monitor at a baud rate of 115200. The analog readings should be displayed.
Rotate the potentiometer and see the values increasing or decreasing.
2. ESP8266 NodeMCU Analog Read with MicroPython
This section show how to read analog values with the ESP8266 using MicroPython firmware.
To follow this tutorial you need MicroPython firmware installed in your ESP8266 board. 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
Script – Analog Reading ESP82266
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)
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).
- To read the analog value, use the read() method on the ADC object.
Demonstration
After uploading the code to the ESP8266 board using Thonny IDE or uPyCraft IDE, rotate the potentiometer.
Check the shell of your MicroPython IDE to read the values from the potentiometer.
3. ESP8266 Analog Read with Lua/NodeMCU
This section shows how use the NodeMCU firmware to read analog values with the ESP8266.
Flashing ESP8266 with Lua/NodeMCU firmware
First, you have to flash your ESPs with NodeMCU firmare.
I recommend using the ESPlorer IDE which is a program created by 4refr0nt to send commands to your ESP8266.
Follow these instructions to download and install ESPlorer IDE:
- Click here to download ESPlorer
- Unzip that folder
- Go to the main folder
- Run ESPlorer.jar
- Open the ESPlorer
Testing the ADC Pin (A0)
To send commands with the ESPlorer IDE, you need to establish a serial communication with your ESP, follow these instructions:
- Connect your ESP-12E or FTDI programmer to your computer
- Set bad raute as 9600
- Select your ESP-12E or FTDI programmer port (COM3, for example)
- Press Open/Close
Then type the following command:
print(adc.read(0))
Click the button “Send” as shown below.
It should return a value between 0 and 1024. Rotate your potentiometer and send the print(adc.read(0)) command a few more times to get the potentiometer value.
When your potentiometer is near 0V it prints 0 and when it reaches 3.3V it should print 1024.
Wrapping Up
In this tutorial we’ve shown you how to read analog values using the ESP8266 analog pin (A0). One important thing to notice is that the ESP8266 analog input range is either 0-1V if you’re using a bare chip, or 0-3.3V if you’re using a development board.
Either way, you should always be careful not to exceed the maximum recommended voltage. You may consider adding a voltage divider circuit when you need a higher input voltage range.
We hope you’ve found this tutorial useful. If you’re just getting started with the ESP8266, we recommend the following resources:
- Home Automation Using ESP8266 (eBook)
- Getting Started with the ESP8266
- ESP8266 GPIO Reference Guide
- ESP8266 Web Server
Thanks for reading.
Really a great job, well done. For me it was very useful.
Thank you!
Rui
I have been watching/reading your tutorials for a while with interest.
I am a little confused with how you have chosen the resistors because you have a parallel combination between the 1K Pot and the 100R (R2).
Also would it not make sense to have added a small value cap of around 100nF between ground and the output from the pot. Pots are notoriously noisey during use?
Hi Rui,
I have to agree with NealB. You do have a parallel resistance that you are not taking into account in the calculation.
The voltage divider should go between the output of the pot and ground. The pot’s fixed terminals should be between the 3.3V and ground. And the 220 Ohm resistor connects to the sweep of the pot. The common connection between the fixed resistors goes to the ADC pin. And the 100 Ohm to ground.
This increases the accuracy of your calculation and lowers the current drain since there is now 1K between 3.3 and ground and not 320 Ohms. Making for less than one third of the current drain.
All assuming very low current to the ADC of course or nothing much would work anyway.
The cap is also a great idea to reduce the noise. Good work Neal.
Thanks for your suggestions. You guys are 100% right and I thought I had the circuit like you guys said, but using Fritizing I’ve messed up the connections I had in real life.
I’ve updated the schematics!
Thanks again for taking the time to leave a comment Paul and NealB.
Have a great day!
I put the whole thing and I returned values min 19 max 60, where am I wrong?
sir i’v a question over here that is how we can send this ADC value from one esp8266 module to another esp8266 module ?
Here’s how you send values from one ESP to another: https://randomnerdtutorials.com/how-to-make-two-esp8266-talk/
I measured the output voltage of 0.25 volts and marks me
Ho risolto, sostituendo il trimmer, e funziona.
Ho poi installato sul ESP 07 lo sketch per il TA SCT 013 e benché ruoti il trimmer non mi restituisce i valori.
Scusami.
I solved it by replacing the trimmer, and it works.
I then installed the ESP 07 sketch for the TA 013 SCT and rotate the trimmer although I do not return values
Awesome! I’m glad it’s working now. Thank you for reading!
Good one Rui! I can see this being useful reading pressure transducers, and controlling with the outcome…
Thank you!
Rui,
I use the Arduino editor w/esp8266 add on. Do you have this code in that IDE?
Is there a reason you are using the NodeMCU editor vs Arduino IDE. I would think the Arduino IDE would have more users. There are many more chips than the ESP8266 and I hate to have to learn a new editor for each new chip!
I have purchased your books and look forward to more such projects in the Arduino IDE format.
Keep up the good work,
Bi;; Miller
Thank you so much for your continuous support. I really appreciate!
For the Arduino IDE everything is very similar, but your send that command: analogRead(A0);
Rui,
I use the Arduino editor w/esp8266 add on. Do you have this code in that IDE?
Is there a reason you are using the NodeMCU editor vs Arduino IDE. I would think the Arduino IDE would have more users. There are many more chips than the ESP8266 and I hate to have to learn a new editor for each new chip!
I have purchased your books and look forward to more such projects in the Arduino IDE format.
Keep up the good work,
Bill Miller
Hi Bill,
Thank you so much for your continuous support. I really appreciate!
For the Arduino IDE everything is very similar, but your send that command: analogRead(A0);
hello Rui why in all project i can not see code
Your tutorials are very helpful for me, I am learning a lot.
Thanks!
Rui
Your tutorials are very helpful for me, I am learning a lot.
Is there a way to read the input voltage on NodeMCU. I would like to be able to read the voltage level of the battery supplying Vin.
Yes, adc.readvdd33(). It’s in the docs.
Hi, really nice to see your website. It seems that ESP8266 is getting more and more popular! Good work!
I only have one comment to make, I am using a nodemcu board (v0.9, yeah, the wide one) and the measurable voltage at A0 is between 0V (well, ground gives a reading of “2”, close enough) and 3V. which is “1024”. I don’t know if this is a recent change or what, but it may help someone…
Thanks! You’re right, some modules are 3V and go to 1024 reading.
nodemcu boards already have a 3.3v divider on them. So input for A0 is 0-3.3v not 0-1v
Yup, but older versions (the first module I bought and tested) was 1v
FYI, The Adafruit HUZZAH ESP8266 is 0-1v input.
Hi Steve.
Thank you for that information.
It may vary depending of the ESP8266 development board you’re using.
Thanks for sharing.
Regards,
Sara
Hello, thanks for the great tutorial. Can I use pin A0 as an output? I want to dim an LED attached to A0.
You mentioned using Multimeter to check if it is 1 volt limit or 3.3 v limit, but did not show how.
So, I risked it and build the same circuit. Wrote a simple Arduino sketch to read the analog value.
I stopped around 600 and measured the voltage It was 1.99 volt So I assumed that my nodemcu is ok for 3.3v.. BTY the version number I have is old and it is is 0.9
can u make a video in english language?
Hi Mahmdul,
Unfortunately I don’t have any companion videos for this blog post… Thanks for asking,
Rui
I am trying to connect esp8266 with dfrobot ph sensor. My code is get uploaded bt on serial monitor it doesnot show any readings. I am not understanding why this is happening? Could you just help me out with that?
Hi.
I’m sorry, but I don’t have any project using a ph sensor :/
Hi Rui ,
I have a question because i see may somthing wrong
Your formular is : Vout = Vin*R2/(R1+R2)
But in your toturol –> R1 = 220ohm, R2=100ohm, right?
So, how you get 3.3V in your connect ?
Because, my opinion –> with that connect. We only get 1.56V at ADC output
Thanks, please advice me
Hi.
You only need that voltage divider if the maximum input voltage on the analog pin of the ESP8266 is 1V (some old versions only support up to 1V).
I need to update this blog post to make it clearer.
Thanks for noticing.
Regards,
Sara 🙂
There is an annoying “feature” of the NodeMCU and the pre-ADC divisor resistor network. The 100K/220K network produces a full count at 3.2v, not 3.3v. So at 3.2v the ADC is already seeing the full 1v. This results in a 3% loss of scale and ADC count is now effectively reduced from the promised 1024 bits down to 993 bits.
You need to take this into account when using a Steinhart-Hart formula to convert the thermistor resistance into Kelvin. Otherwise the formula does not work.
Again I thought of something I needed to do and sure enough – found it here.
Thanks Rui for your great information.
You’re welcome.
Regards,
Sara
Hi, and tanks for a nice web site.
I cannot see that the voltage divider will give the right value.
Let’s assume that the 1K pot is in the middle position. Without the
voltage regulator, there will be 500 ohms from both ground and 3.3V
to the output, giving a voltage of 1.65.
But you cannot add this other voltage regulator and assume that the
voltage is still 1.65.
The path trough the voltage regulator add a resistor of 320 ohm in parallel
to the 500 ohms of the ground side of the pot, gives an effective value of
1 / ( 1/500 + 1/320) = 195 ohms.
The output of the pot will now be 0.96 V and not 1.65.
Hence, the voltage divider will not divide the right voltage.
I believe that the resistors in the voltage divider will have to be significantly higher than the resistance in the pot for this to work.
Regards,
Stein Gulbrandsen
Parabéns! Rui e Sara,
Muito bom seu Poste sobre ADC no Nodemecu será muito útil para leitura de sensores analógicos .
Congratulations!
Carlos Bruni
Salvador Bahia Brasil
Muito obrigada por essas palavras.
Cumprimentos de Portugal.
Sara
Hello,
Thank you very much to share this nice code ! I have a problem. I try to use this code with a DHT22. On the charts it Always shows the same value for temperature (24.3°C), humidity (57%).
If I print the values in the serial monitor Inside the loop, the values changed and are true but not on the charts. It seems that the function of reading temperature, humidity and pressure are not executed.
Could you help me to fix this problem. Thank you very much !
Best regards
Great series Rui & Sara!
One thing that I have noticed with all my ESP8266’s is that when I connect A0 or ADC sirect to ground, I NEVER read 0. It is always a value of 2 and occasionally 3. Have you noticed this at all?
The value can be scaled of course by subtracting 2, but this occasionally gives an error when it is 3.
I suspect this must have something to do with noise on the Vref, but of course there is no decoupling pin for it!
How do you overcome the problem?
How would you go about changing on the fly the color of an icon to match the temperature or humidity?
Hi,
The article like all others is a fantastic read.
Do you have one to read temperature using NTC and ESP8266?
Best regards.
Hello,
Thank you for all!!
About your comment :
“If you want to output PWM signals based on the input voltage of the ADC pin, you need to convert the ADC values to a range of 0 to 255. You need to do this because the PWM output only has 8-bit resolution”
I think that PWM output 8-bit resolution is for Arduino Uno.
I think that Esp8266 use 10 bit for pwm.
It’s correct?
Max
Hi Max.
You are right.
Thanks for pointing that out.
I’ll fix the tutorial.
Regards,
Sara
I need to send the anolog data to a web server have you got anthing on that I see many using digital inputs but i cant get it to work with analog input???
Hi.
ADC2 pins cannot be used when Wi-Fi is used. So, if you’re using Wi-Fi and you’re having trouble getting the value from an ADC2 GPIO, you may consider using an ADC1 GPIO instead, that should solve your problem.
See our GPIO pinout guide: https://randomnerdtutorials.com/esp32-pinout-reference-gpios/
Regards,
Sara
Thanks Sara, Been on it for 3 days got a ADS1115 ill try that . Thanks for your help..
Great tutorial but what is on a ESP8266-01S Chip. We use this smal-tiny-chip for several jobs and all works fine. Last days i tried to read an Voltage within 0 V – 3,3 V. In my understanding there is PIN GPIO0 to use for this in additon with a voltage-divider. I use a 100 kOhm and 220 kOhm resitors. This should brings 0 to 3,3 V in a range of 0 to 1V in the middle of the divider.
Minutes later the first test is placed on a bread-board. The sketch is realy simple like this:
#define LEDPin 2 // Internal LED on GPIO2
const int A0 = 0; // IO0 as ADC-input
void setup() {
// Serial-output active and PIN-Modes
Serial.begin(115200);
pinMode(LEDPin, OUTPUT);
pinMode(A0, INPUT);
// read voltage as (0-1023)
int Voltage = analogRead(A0);
// UB+ calculation depend on 3,3V
float ActualVoltage = (Voltage / 1023) * 3.3;
// Print Voltage on serial-monitor for testing
Serial.print("Voltage: ");
Serial.print(ActualVoltage);
Serial.println(" V");
delay(1000);
}
In every loop-step i see only 0,00 V as output. Where is th ebug in this quite easy run?
I read in an other article that the ESP8266-01S have 2 separate ADC-Modes. One is to read the VCC+ internal and another ist to read voltage on GPIO0 as a ADC-Input.
Have i missed some preparations? Hope you can help this problem on my ESP82-01S chip.
Thanks and have a great day,
Manfred