Many users move from Arduino Uno or Nano to ESP32 and expect analogRead() to behave the same way. The code looks familiar, the function name is the same, and the ESP32 has many analog-capable pins. But the results can be surprising.
ESP32 analog readings may be noisy, nonlinear, unstable, or different from what a multimeter shows. Some pins may stop working when WiFi is enabled. Some readings may never reach the expected full range. This is one of the most common “it worked on Arduino, why not on ESP32?” problems.
The ESP32 ADC is useful, but it is not the same as the simple ADC experience many users know from classic Arduino boards. For serious analog measurements, the ESP32 often needs more care, calibration, filtering, or an external ADC.
Typical Symptoms
- Analog readings jump around even with a stable input voltage.
- The reading does not match the voltage measured with a multimeter.
- The value is nonlinear across the input range.
- The reading changes when WiFi is enabled.
- Some analog pins work without WiFi but fail with WiFi.
- The value never reaches zero or full scale.
- The same sensor works better on Arduino Uno than on ESP32.
- Two ESP32 boards give different readings with the same circuit.
First Important Point: ESP32 ADC Is Not Precision by Default
The ESP32 has built-in analog-to-digital converters, but they are not precision measurement instruments. They are useful for reading approximate voltages, knobs, light sensors, battery levels and other slow signals, but they need careful handling.
Compared with a classic Arduino Uno, ESP32 analog readings can be affected more strongly by:
- ADC attenuation setting.
- Input voltage range.
- Chip-to-chip variation.
- Power supply noise.
- WiFi activity.
- Board layout.
- High source impedance.
- Software configuration.
If you need accurate voltage measurement, do not assume the raw ESP32 ADC number is automatically correct.
Arduino Uno ADC vs ESP32 ADC
| Feature | Arduino Uno / Nano | ESP32 |
|---|---|---|
| Typical ADC resolution | 10-bit | Usually configured up to 12-bit |
| Typical raw range | 0 to 1023 | Often 0 to 4095 |
| Logic / ADC voltage | Usually 5V on classic boards | 3.3V system, not 5V tolerant |
| Linearity | Often predictable enough for simple projects | Can be noticeably nonlinear |
| WiFi interaction | No WiFi built in | ADC2 has limitations when WiFi is active on classic ESP32 |
| Precision measurement | Possible with care | Often better with external ADC |
Common Cause: Expecting 5V Analog Inputs
Classic Arduino Uno boards normally use 5V logic and can read analog voltages from 0V to 5V by default. ESP32 boards use 3.3V logic and ESP32 GPIO pins are not generally 5V tolerant.
This is very important.
Do not connect a 5V analog signal directly to an ESP32 analog input. This can damage the ESP32.
If a sensor outputs 0V to 5V, use a voltage divider, level shifting, signal conditioning, or a different sensor output range before connecting it to ESP32.
Common Cause: Wrong Attenuation Setting
The ESP32 ADC can use different attenuation settings. These settings change the approximate input voltage range that can be measured.
If the attenuation is wrong, the ADC may saturate too early or use only part of its useful range.
Depending on the Arduino core and ESP32 variant, functions and exact ranges can vary, but the general idea is:
- Lower attenuation is better for smaller voltages.
- Higher attenuation allows measuring higher voltages up to around the 3.3V range.
- Higher attenuation may also affect accuracy and linearity.
For Arduino-style ESP32 code, you may see functions such as:
analogSetPinAttenuation(analogPin, ADC_11db);
Always check the board package documentation for the exact ESP32 core version you are using.
Common Cause: ADC2 and WiFi Conflict
On the classic ESP32, the ADC pins are split between ADC1 and ADC2. ADC2 has an important limitation: it cannot always be used freely while WiFi is active.
This causes a very common problem:
- Analog input works in a simple test sketch.
- Then WiFi is added.
- The same analog input stops working or gives strange results.
For classic ESP32 WiFi projects, use ADC1 pins for analog measurements whenever possible.
This one detail can save hours of confusion.
Common Cause: Using the Wrong Pin
Not every ESP32 GPIO is usable as an analog input. Some pins are digital only. Some pins are input-only. Some pins are connected to flash memory or board hardware. Some pins are not available on certain modules.
Before using an analog pin, check the exact board pinout.
Be careful with:
- GPIOs used for flash or PSRAM.
- Boot strapping pins.
- Pins used by onboard LEDs, buttons or USB circuits.
- Pins that are not actually connected on the development board.
- ADC2 pins in WiFi projects on classic ESP32.
Common Cause: Floating Input
A floating analog input gives random values. This is true on Arduino and ESP32, but the ESP32 can make the problem look even more dramatic because of WiFi, high impedance inputs and board noise.
An unconnected ADC pin is not zero. It is an antenna.
Basic tests:
- Connect the ADC pin to GND. It should read near zero.
- Connect the ADC pin to 3.3V. It should read near the top of the configured range.
- Connect a potentiometer between 3.3V and GND, with the wiper to the ADC pin. The value should change smoothly.
Common Cause: High Source Impedance
The ADC input needs to sample the voltage. If the sensor output or voltage divider resistance is too high, the sample capacitor inside the ADC may not charge quickly enough. The result can be inaccurate or unstable readings.
This often happens with high-value voltage dividers used to save power.
Symptoms include:
- Readings drift slowly.
- The value depends on the previous ADC reading.
- Touching the wire changes the reading.
- A multimeter shows the correct voltage, but ESP32 reads differently.
Possible fixes:
- Use lower resistor values in the voltage divider.
- Add a capacitor from ADC input to ground for slow signals.
- Read the input more than once and ignore the first reading.
- Buffer the signal with an op-amp if accuracy matters.
Common Cause: Power Supply Noise
The ESP32 can create noise on its own power rails, especially when WiFi transmits. External modules can add even more noise.
If the analog sensor uses the same noisy supply as the ESP32, the sensor output and ADC reference environment may both be unstable.
Noise sources include:
- WiFi current peaks.
- Switching regulators.
- USB power noise.
- Relay coils.
- Motors.
- Servos.
- LED strips.
- TFT backlights.
Good wiring, decoupling capacitors, short analog leads and separated load power paths can improve readings.
Common Cause: Ground Noise
The ADC measures voltage relative to the ESP32 ground. If that ground shifts because motor, relay or LED current flows through the same ground path, the analog reading changes.
This can make a perfectly stable sensor look noisy.
Better practice:
- Keep high-current loads out of the ESP32 ground path.
- Use thicker wires for load current.
- Use separate power routing for motors, relays and LED strips.
- Connect grounds at a sensible common point.
- Keep analog wires away from noisy load wiring.
Common Cause: Nonlinear Readings
ESP32 ADC readings are not always perfectly linear. A voltage increase of 0.5V may not produce the exact same raw count change across the whole range.
For simple knobs, light sensors or rough battery level displays, this may be acceptable. For measurement instruments, it is not.
Possible solutions:
- Calibrate the reading against known voltages.
- Use a correction table.
- Use a voltage range where the ADC behaves better.
- Use an external ADC for precision.
Common Cause: Expecting Full 0 to 4095 Range
Many examples assume a 12-bit ADC range of 0 to 4095. In practice, the usable range may not perfectly cover 0V to 3.3V in a linear way, depending on attenuation, chip variation and board design.
Do not blindly convert like this and expect precision:
voltage = analogRead(pin) * 3.3 / 4095.0;
This may be good enough for rough estimates, but not for calibrated measurements.
Better Basic Reading Method
For slow signals, averaging several readings is often better than trusting one raw value.
const int analogPin = 34;
int readAverageADC() {
long total = 0;
for (int i = 0; i < 32; i++) {
total += analogRead(analogPin);
delay(2);
}
return total / 32;
}
void setup() {
Serial.begin(115200);
}
void loop() {
int raw = readAverageADC();
Serial.print("ADC raw average: ");
Serial.println(raw);
delay(500);
}
Averaging helps reduce random noise. It does not fix wrong voltage range, bad grounding or ADC nonlinearity.
Testing with a Potentiometer
A potentiometer is a good first test for ESP32 analog input behavior.
Wire it like this:
- One outside pin to 3.3V.
- Other outside pin to GND.
- Middle pin to an ESP32 ADC input.
Turn the knob slowly and watch the serial monitor. The value should change smoothly. If it jumps wildly, check wiring, pin choice, power and grounding.
Testing with Known Voltages
For better diagnosis, apply known voltages to the ADC input and record the raw readings.
For example, test approximately:
- 0.0V
- 0.5V
- 1.0V
- 1.5V
- 2.0V
- 2.5V
- 3.0V
This helps reveal offset, nonlinearity and saturation. Do not exceed the safe input voltage of the ESP32 pin.
Using an External ADC
For reliable analog measurements, an external ADC is often the best solution. A common choice is an ADS1115-style I2C ADC module.
An external ADC can provide:
- Better resolution.
- More predictable readings.
- Differential input options.
- Programmable gain.
- Cleaner separation from ESP32 internal ADC limitations.
This is especially useful for battery monitors, sensor measurements, bridge sensors, slow precision readings and projects where the value actually matters.
When the Internal ESP32 ADC Is Good Enough
The internal ESP32 ADC is still useful. It is often good enough for:
- Reading a potentiometer.
- Detecting approximate battery level.
- Reading a light-dependent resistor.
- Simple threshold detection.
- Approximate analog sensors.
- User controls where exact voltage is not important.
It is less ideal for calibrated instruments, precision voltage measurement, small sensor signals or anything requiring high accuracy.
Recommended Troubleshooting Steps
- Check that the analog signal never exceeds 3.3V.
- Use an ADC1 pin if WiFi is used on classic ESP32.
- Connect the analog input to GND and confirm near-zero reading.
- Connect the input to 3.3V and confirm high reading.
- Test with a potentiometer before testing a complex sensor.
- Measure the actual voltage with a multimeter.
- Use the correct attenuation setting.
- Average multiple readings for slow signals.
- Improve power and ground wiring.
- Use an external ADC if accuracy matters.
Quick Diagnostic Table
| Symptom | Likely Cause | First Thing to Try |
|---|---|---|
| Random reading with nothing connected | Floating ADC input | Connect input to GND as a test |
| Analog fails when WiFi starts | ADC2 conflict or power noise | Use ADC1 pin and check supply stability |
| Reading does not match multimeter | ADC nonlinearity, attenuation or calibration issue | Measure known voltages and calibrate |
| Value jumps when relay/motor switches | Ground noise or supply dip | Separate load power and improve grounding |
| Value changes slowly or depends on previous reading | Source impedance too high | Lower divider resistance or add input capacitor |
| Reading clips too early | Wrong attenuation or voltage too high | Set attenuation correctly and verify input voltage |
What Not to Do
- Do not connect 5V analog signals directly to ESP32 pins.
- Do not use ADC2 pins for classic ESP32 WiFi projects unless you know the limitation.
- Do not expect raw ESP32 ADC values to be precision voltage measurements.
- Do not troubleshoot analog problems with floating inputs.
- Do not ignore power supply and ground layout.
- Do not assume all ESP32 boards behave exactly the same.
CANABLOX Practical Note
CANABLOX is a good fit for projects where stable analog measurements are needed with modern controllers. Instead of relying only on the ESP32 internal ADC, a CANABLOX ADC module can provide a cleaner and more predictable analog measurement path over I2C.
This is especially useful when using ESP32, ESP32-C3, ESP32-C6, ESP32-S3, RP2040, RP2350 or other XIAO-style controllers in the same modular system. The controller can handle communication and logic, while a dedicated ADC module handles the analog measurement more consistently.
Conclusion
The ESP32 ADC is useful, but it should not be treated exactly like the ADC on an Arduino Uno. ESP32 analog readings can be affected by attenuation, WiFi, pin choice, power noise, source impedance and nonlinearity.
For simple knobs, rough sensors and threshold detection, the internal ADC can work well with good wiring and averaging. For accurate measurements, use calibration or an external ADC.
If an analog value looks wrong on ESP32, start with the basics: safe voltage range, ADC1 pin choice, known test voltages, stable ground, proper attenuation and realistic expectations.
