ESP32 ADC with Arduino IDE – Measuring voltage example

In this tutorial, we will learn how how to use ADC (analog to digital converter) module of ESP32 development board with Arduino IDE. Furthermore, We will learn to measure analog voltage with ESP32 ADC channels.

ESP32 ADC Introduction

ESP32 board has two 12 bit analog to digital converters.  The type of ADCs used in this development board is SAR-based which is also known as successive approximation registers. To know more about types of ADC’s, check this analog to digital converter tutorial

Both these ADCs support up to 18 analog channels which means we can connect eighteen analog sensors at a time with this board. But ADC2 is shared between other resources of this development board.  So we have two ADCs in ESP32 ADC1 and ADC2.  Pin mapping of ADC channels for both ADCs is shown below.

ESP32 ADC1 Pin Mapping

Following is a pin mapping of with ESP32 devkit DOIT board. Although ESP32 chip ADC1 has eight channels, Devkit DOIT board supports only 6 channels. But still, we have enough analog channels for analog sensor interfacing.

  • ADC1_CH0 >>>GPIO36
  • ADC1_CH1 >>>Not available on this board Devkit DoIT ( 30 pins version )
  • ADC1_CH2 >>> NA
  • ADC1_CH3 >>>GPIO39
  • ADC1_CH6 >>>GPIO34
  • ADC1_CH7 >>> GPIO35
  • ADC1_CH4 >>> GPIO32
  • ADC1_CH5 >>> GPIO33

ESP32 ADC2 Pin Mapping

Pin mapping for ADC2 channel is given below. Devkit DOIT board ADC2 supports 10 analog channels and all these analog channels are available on Devkit do it board.

  • ADC2_CH0 >>>GPIO0
  • ADC2_CH1 >>> This channel is not available on Devkit DOIT board
  • ADC2_CH2 >>>GPIO2
  • ADC2_CH3 >>> GPIO15
  • ADC2_CH4 >>> GPIO13
  • ADC2_CH5 >>> GPIO12
  • ADC2_CH6 >>>GPIO14
  • ADC2_CH7 >>> GPIO27
  • ADC2_CH8 >>> GPIO25
  • ADC2_CH9 >>> GPIO26

Although we have 10 analog channels available in ADC2, all these channels are shared among other resources. For example, ADC2 is shared with WiFi drivers, therefore you can only use it after WiFi drivers are not started. You have to make your program smart enough to switch between two resources. The easy way is to turn off the WiFi driver when you want to use ADC2 and read the analog value and after that turn on the WiFi driver when you want to update value to the server etc. I will explain more about it in later parts of this series of tutorials. The figure below shows the pins of analog channels on Devkit DOIT:

ESP32 ADC channels pinout

How to use Analog to digital converter channels of ESP32

Now, let’s see how to write code or program for reading ADC values of with any of these 15 channels available on this board. After that, we will see an example, where we connect a variable resistor with the analog channel and measure voltage and display it on the serial monitor of Arduino IDE. ESP32 analog channels are of 12 bit which means the minimum step of each voltage level is between 0 and 4095. Analog channel produces a digital value between 0 and 4095 according to the voltage at the input of the analog channel. For example

  • If the voltage is 0 at the input of the analog channel, the digital value will be zero.
  • If the voltage is 3.3 volt at the input, the digital value will be 4095. So the maximum voltage limit is 3.3 volt.
  • But we can measure higher voltage else by using voltage step down methods like voltage divider method, step down transformer method in case of ac voltage measurement.

You may like to check our previous project on high voltage measurement with other microcontrollers. Although a different microcontroller is used in these projects, you can apply the same concepts to ESP32 ADC for measurement of current, voltage, power factor and ac power.

One main disadvantage of ESP32 ADC is that it has a non linear behavior. Graph below shows its non-linear curve. you can find more information about it on this link.

ESP32 adc curve non linear

Program for ESP32 Analog to digital converter

So we are using Arduino IDE in these tutorials.  Arduino IDE provides built in function to read analog values that is analogRead function.

  • analogRead(analog_pin_number) : We will use this function to read analog value. This analogRead function has only one argument which is a pin number of the analog channel you want to use. I have already provided pin mapping of all analog channels with GPIO pins above. So you will only pass the name of GPIO pin to this function like analogRead(36), it will read the value from ADC1 channel zero. The figure above also shows the pin number and respective analog channels.
  • You just need to store the output of this function in any variable other than character types. Because the character type variable can store values between 0 and 255 only.

If you are just getting start with ESP32 programming, check these earlier tutorials:

Now make this circuit diagram on your bread board and after that, we will write a code to measure voltage using a variable resistor.

measure analog voltage ESP32

In the above circuit diagram, a variable resistor is used. one terminal of the variable resistor is connected with ground and other terminal with 3.3 volt. Center terminal of the variable resistor is connected with GPIO15 which is ADC2 channel three or ADC2_CH3.

Code for analog voltage measurement using ESP32 ADC

Code for analog voltage measurement is shown below. All the functions used in this code have already explained in the previous tutorial and in this tutorial except serial.begin() and serial.println() functions.

const int Analog_channel_pin= 15;
int ADC_VALUE = 0;
int voltage_value = 0; 
void setup() 
{
Serial.begin(115200);
}
void loop() 
{
ADC_VALUE = analogRead(Analog_channel_pin);
Serial.print("ADC VALUE = ");
Serial.println(ADC_VALUE);
delay(1000);
voltage_value = (ADC_VALUE * 3.3 ) / (4095);
Serial.print("Voltage = ");
Serial.print(voltage_value);
Serial.print("volts");
delay(1000);
}

Now  I will explain the working of code line by line.  In these lines, first we give a name to ADC2_CH3 as Analog_channel_pin and after that, we initialized two integer variables to zero. One variable is used to store digital value and other variable is used to store voltage.

const int Analog_channel_pin= 15;
int ADC_VALUE = 0;
int voltage_value = 0;

In the setup() function, we have serial.begin function is used to initialize serial communication of esp32 and serial communication rate is defined by baud rate. So we have initialized the baud rate of 115200.  Serial communication will be used to send data from ESP32 board to serial monitor of Arduino IDE.

Serial.begin(115200);

Now the main function of this code is a loop part where we are taking an analog input and displaying it on serial monitor of Arduino IDE with the help of these lines.  serial.print function is used to transmit data without a new line at the end and serial.println() function is also used to transmit data but it also includes new line character at the end of the string. After that delay function is used to add a delay of one second. It is not necessary to add delay but we did it check to receive value after every one second.

ADC_VALUE = analogRead(Analog_channel_pin);
Serial.print("ADC VALUE = ");
Serial.println(ADC_VALUE);
delay(1000);

Now in the last part, the first line will convert the digital value of ADC_VALUE into voltage.  ADC_VALUE is multiplied with a resolution of ESP32 ADC which is 3.3 / 4095. Resolution is also know as a minimum step of adc for each corresponding value of voltage. For example, if ADC_VALUE counts 10, its mean it has taken 10 steps or value at the input pin is 10 times the resolution of adc.  So to convert ADC_VALUE back into voltage we simply multiply it with resolution as we done in the first line.  After that Serial.print function sends a string of “voltage = ” and then voltage value and after that unit of voltage is transmitted to the serial monitor.

voltage_value = (ADC_VALUE * 3.3 ) / (4095);
Serial.print("Voltage = ");
Serial.print(voltage_value);
Serial.print("volts");
delay(1000);

So when you run this code on ESP32 board, you will get the value of adc and voltage value after every one second on serial monitor of Arduino IDE.

ADC ESP32 values on serial monitor

you can also check ESP32 Webserver tutorial.

We have similar guide with MicroPython here:

9 thoughts on “ESP32 ADC with Arduino IDE – Measuring voltage example”

  1. Hello,

    Your tutorial about ESP32 ADC https://microcontrollerslab.com/adc-esp32-measuring-voltage-example/ is really interesting, as well as other ESP32 articles, thanks.

    For using ADC2 while WiFi activated, you said: “I will explain more about it in later parts of this series of tutorials.”. Have you done this and where? I can’t find it.

    I’m using ESP32-Cam board where ADC1 is not available, and WiFi is activated so I can’t measure voltage with ADC2…
    In https://github.com/espressif/arduino-esp32/issues/102 a “fix” seems to allow using ADC2 while WiFi activated, but no explanation about the consequences on WiFi and why WiFi modifies ADC2 configuration… This fix seems to work for me, whereas switching WiFi off for reading ADC2 doesn’t.

    So if you have more informations about how to do it in a safe way, let me know please.

    Regards,

    Marc

    Reply
  2. I fixed your example code for you
    “`
    const int Analog_channel_pin= 15;
    int ADC_VALUE = 0;
    double voltage_value = 0;
    void setup()
    {
    Serial.begin(115200);
    }
    void loop()
    {
    ADC_VALUE = analogRead(Analog_channel_pin);
    Serial.print(“ADC VALUE = “);
    Serial.print(ADC_VALUE);
    voltage_value = (ADC_VALUE * 3.3 ) / (4095);
    Serial.print(” | Voltage = “);
    Serial.print(voltage_value);
    Serial.println(“volts”);
    delay(1000);
    }
    “`

    Reply
  3. Interesting tutorial – thanks. I am trying to connect an RFID RMD6300 to and ESP32 (TTG0 T8). On the arduino uno I connect the RMD6300 TX cable to the ~6 pin and the RX cable to the 8 pin and it works perfectly. I am trying to work out what the equivalent pins would be on the ESP32. Can you help?

    Reply

Leave a Comment