ESP32 ADC – Read Analog Values with Arduino IDE

This article shows how to read analog inputs with the ESP32 using Arduino IDE. Analog reading is useful to read values from variable resistors like potentiometers, or analog sensors.

ESP32 ADC Read Analog Values with Arduino IDE

Reading analog inputs with the ESP32 is as easy as using the analogRead(GPIO) function, that accepts as argument, the GPIO you want to read.

We also have other tutorials on how to use analog pins with ESP board:

Watch the Video

You can watch the video tutorial or keep reading this page for the written instructions.

Analog Inputs (ADC)

Reading an analog value with the ESP32 means you can measure varying voltage levels between 0 V and 3.3 V.

The voltage measured is then assigned to a value between 0 and 4095, in which 0 V corresponds to 0, and 3.3 V corresponds to 4095. Any voltage between 0 V and 3.3 V will be given the corresponding value in between.

ESP32 ADC Analog Read Inputs Range Value

ADC is Non-linear

Ideally, you would expect a linear behavior when using the ESP32 ADC pins. However, that doesn’t happen. What you’ll get is a behavior as shown in the following chart:

This behavior means that your ESP32 is not able to distinguish 3.3 V from 3.2 V. You’ll get the same value for both voltages: 4095.

The same happens for very low voltage values: for 0 V and 0.1 V you’ll get the same value: 0. You need to keep this in mind when using the ESP32 ADC pins.

There’s a discussion on GitHub about this subject.

analogRead() Function

Reading an analog input with the ESP32 using the Arduino IDE is as simple as using the analogRead() function. It accepts as argument, the GPIO you want to read:


The ESP32 supports measurements in 18 different channels. Only 15 are available in the DEVKIT V1 DOIT board (version with 30 GPIOs).

Grab your ESP32 board pinout and locate the ADC pins. These are highlighted with a red border in the figure below.


Learn more about the ESP32 GPIOs: ESP32 Pinout Reference.

These analog input pins have 12-bit resolution. This means that when you read an analog input, its range may vary from 0 to 4095.

Note: 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.

Other Useful Functions

There are other more advanced functions to use with the ADC pins that can be useful in other projects.

  • analogReadResolution(resolution): set the sample bits and resolution. It can be a value between 9 (0 – 511) and 12 bits (0 – 4095). Default is 12-bit resolution.
  • analogSetWidth(width): set the sample bits and resolution. It can be a value between 9 (0 – 511) and 12 bits (0 – 4095). Default is 12-bit resolution.
  • analogSetCycles(cycles): set the number of cycles per sample. Default is 8. Range: 1 to 255.
  • analogSetSamples(samples): set the number of samples in the range. Default is 1 sample. It has an effect of increasing sensitivity.
  • analogSetClockDiv(attenuation): set the divider for the ADC clock. Default is 1. Range: 1 to 255.
  • analogSetAttenuation(attenuation): sets the input attenuation for all ADC pins. Default is ADC_11db. Accepted values:
    • ADC_0db: sets no attenuation (1V input = ADC reading of 1088).
    • ADC_2_5db: sets an attenuation of 1.34 (1V input = ADC reading of 2086).
    • ADC_6db: sets an attenuation of 1.5 (1V input = ADC reading of 2975).
    • ADC_11db: sets an attenuation of 3.6 (1V input = ADC reading of 3959).
  • analogSetPinAttenuation(pin, attenuation): sets the input attenuation for the specified pin. The default is ADC_11db. Attenuation values are the same from previous function.
  • adcAttachPin(pin): Attach a pin to ADC (also clears any other analog mode that could be on). Returns TRUE or FALSE result.
  • adcStart(pin), adcBusy(pin) and resultadcEnd(pin): starts an ADC convertion on attached pin’s bus. Check if conversion on the pin’s ADC bus is currently running (returns TRUE or FALSE). Get the result of the conversion: returns 16-bit integer.

There is a very good video explaining these functions that you can watch here.

Read Analog Values from a Potentiometer with ESP32

To see how everything ties together, we’ll make a simple example to read an analog value from a potentiometer.

For this example, you need the following parts:

You can use the preceding links or go directly to to find all the parts for your projects at the best price!


Wire a potentiometer to your ESP32. The potentiometer middle pin should be connected to GPIO 34. You can use the following schematic diagram as a reference.

Read value from Potentiometer ESP32 Arduino IDE


We’ll program the ESP32 using Arduino IDE, so make sure you have the ESP32 add-on installed before proceeding:

Open your Arduino IDE and copy the following code.

// Potentiometer is connected to GPIO 34 (Analog ADC1_CH6) 
const int potPin = 34;

// variable for storing the potentiometer value
int potValue = 0;

void setup() {

void loop() {
  // Reading potentiometer value
  potValue = analogRead(potPin);

View raw code

This code simply reads the values from the potentiometer and prints those values in the Serial Monitor.

In the code, you start by defining the GPIO the potentiometer is connected to. In this example, GPIO 34.

const int potPin = 34;

In the setup(), initialize a serial communication at a baud rate of 115200.


In the loop(), use the analogRead()function to read the analog input from the potPin.

potValue = analogRead(potPin);

Finally, print the values read from the potentiometer in the serial monitor.


Upload the code provided to your ESP32. Make sure you have the right board and COM port selected in the Tools menu.

Testing the Example

After uploading the code and pressing the ESP32 reset button, open the Serial Monitor at a baud rate of 115200. Rotate the potentiometer and see the values changing.

Read potentiometer ESP32 analogRead

The maximum value you’ll get is 4095 and the minimum value is 0.

Read potentiometer ESP32 analogRead serial monitor Arduino IDE demonstration

Wrapping Up

In this article you’ve learned how to read analog inputs using the ESP32 with the Arduino IDE. In summary:

  • The ESP32 DEVKIT V1 DOIT board (version with 30 pins) has 15 ADC pins you can use to read analog inputs.
  • These pins have a resolution of 12 bits, which means you can get values from 0 to 4095.
  • To read a value in the Arduino IDE, you simply use the analogRead() function.
  • The ESP32 ADC pins don’t have a linear behavior. You’ll probably won’t be able to distinguish between 0 and 0.1V, or between 3.2 and 3.3V. You need to keep that in mind when using the ADC pins.

We hope you’ve find this short guide useful. If you want to learn more about the ESP32, enroll in our course: Learn ESP32 with Arduino IDE.

Other ESP32 guides that you may also like:

Thanks for reading.

Learn how to program and build projects with the ESP32 and ESP8266 using MicroPython firmware DOWNLOAD »

Learn how to program and build projects with the ESP32 and ESP8266 using MicroPython firmware DOWNLOAD »

Enjoyed this project? Stay updated by subscribing our weekly newsletter!

17 thoughts on “ESP32 ADC – Read Analog Values with Arduino IDE”

  1. Thanks Rui for another very useful artical. I found the Other Useful Functions particularly useful.
    Please check the analogSetWidth(width) they seems to be a typo and I am interested in what this does.
    Please explain more the difference between Width, Cycles and Samples. I am sure samples is the number of times a reading is taken, but is the reading returned as an average? What is the limit and do you have a suggested maximum for this?
    Also, is the analogSetAttenuation(attenuation) default set to ADC_11db? I am trying to understand this, because if 1V input = ADC reading of 3959 what would happen with a input of 3.3V. My experience says the default must be ADC_0db.

  2. One of the greatest problems with the ESP32 is it may have 18 ADC inputs, but if you use WiFi you cannot use any of the 10 inputs that direct to ADC2.
    Yes 10 inputs cannot be used!

    What were Espressif thinking when they built the next best IoT device and knobling over half the ADC inputs if you used the typical way to connect to the Internet!

    • If you desperately need more analog inputs, try disconnecting from the WiFi, using the pins, then reconnecting and publishing any results.

      Otherwise, it might be better to consider a simpler WiFi controller and some supporting ADC chips.

  3. If you would like a more linear ADC behavior, you can check my Bitbucket repository at:

    I tried to make an adjustment function for the ADCs of the ESP32.

  4. Sara Santos : i’d like to question, I have an error when trying the df-robot tds sensor using the esp32 board, the sensor reading results are zero, the ADC pin used is gpio 34, power5v. I have tried to replace it with another ADC pin but still the results of the tds readings are zero, please advise

    • Hi.
      I’ve never tried a TDS sensor with the ESP32.
      But that GPIO should work.
      Measure with a multimeter to see if the sensor voltage output is actually changing. This way, you know that the problem is not the sensor.

  5. Hello Sara,

    Minor typo on your function summary table:

    “resultadcEnd(pin)” -> “adcEnd(pin)” to get the result (or similar).

    Otherwise it looks like the function name is “resultadcEnd”.

  6. Hi Rui & co,
    Could you advise the best pin(s) to use to get analog readings from the 36pin do-it ESP32?
    I am using pin 39 now although I get a constant 4096 from an ldr.

    I don’t know what I’d do without Random Nerd Tutorials

      • Thnx Sara,
        Would using adc2 stop NOW from working reliably? Also does it particularly matter which is assigned first in a sketch – ADC pins, WiFi or NOW?
        thank you

        • Hi.
          I haven’t tested ADC with ESP-NOW, so I’m not sure.
          ESP-NOW doesn’t use Wi-Fi, but it uses the Wi-Fi library, so I don’t know if it conflicts.
          Experiment and see what you get.
          As for your second question, it doesn’t matter the order as long as the variables are defined before they are called.


          • My understanding of the ADC2 conflict with WiFi is nothing to do with software, but with internal power routing to the WiFi radio requires power to be diverted from the ADC2 peripheral.
            Once you turn the radio on, the power to ADC2 is robbed, and as a result all readings become unreliable.

Leave a Comment

Download our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.