Interfacing analog electronic sensors requires more than just calling analogRead(). Unlike digital sensors that output pre-calculated I2C or SPI data packets, analog sensors output a continuous variable voltage (typically 0.1V to VCC) that must be sampled by a microcontroller's Analog-to-Digital Converter (ADC). To get accurate physical measurements, you must map the raw ADC counts to voltage using the correct reference baseline, then scale that voltage to physical units using the sensor's specific sensitivity curve. This guide provides the exact math, wiring constraints, and hardware filtering techniques required to extract clean data from analog sensors using modern Arduino and ESP32 platforms.
The Sensing Principle: Translating Physics to Voltage
Analog electronic sensors operate on the principle of transduction, converting a physical phenomenon—such as thermal energy, gas concentration, or luminous flux—into a proportional electrical signal. Inside a sensor like the TMP36 temperature IC, a precision bandgap circuit generates a voltage that shifts linearly with ambient temperature. In resistive sensors like photoresistors (LDRs) or MQ-series gas sensors, the physical stimulus alters the internal resistance of a semiconductor material, which is then converted to a voltage using an external voltage divider circuit.
The microcontroller cannot read this continuous voltage directly. Instead, its internal ADC samples the voltage at discrete intervals and quantizes it into a binary number (the "raw count"). The resolution of this conversion depends on the ADC's bit-depth and reference voltage. A 10-bit ADC yields 1,024 discrete steps, while a 12-bit ADC yields 4,096 steps. Understanding the exact relationship between these raw steps, the ADC's reference voltage, and the sensor's transduction curve is the foundation of accurate embedded measurement.
Reference Data: Common Analog Electronic Sensors
Before wiring any sensor, you must verify its supply requirements and baseline output. Supplying a 3.3V sensor with 5V will destroy it, while powering a 5V ratiometric sensor with 3.3V will skew your ADC math. Below is a specification matrix for three of the most common analog sensors used in embedded projects.
| Sensor Model | Measurand | Supply Range (VCC) | Output Type | Nominal Output @ Baseline | Sensitivity / Scale Factor |
|---|---|---|---|---|---|
| TMP36 | Temperature | 2.7V - 5.5V | Linear Voltage | 750 mV @ 25°C | 10 mV / °C |
| MQ-135 | Air Quality (NH3, CO2) | 5.0V ± 0.1V | Resistive (Divider) | ~2.5V in clean air | Logarithmic (Rs/R0 curve) |
| GL5528 LDR | Light (Illuminance) | 3.3V - 5.0V | Resistive (Divider) | Varies with fixed resistor | Non-linear (Log-Log) |
| ACS712-30A | AC/DC Current | 4.5V - 5.5V | Linear Voltage | VCC / 2 (Zero current) | 66 mV / Ampere |
Wiring, Pinouts, and Supply Requirements
Analog sensors are highly susceptible to voltage drops and ground loops. Always route the sensor's ground directly to the microcontroller's primary analog ground (AGND if available, or the main GND star point), rather than daisy-chaining it through high-current motor or relay grounds.
| Sensor Pin | Arduino Uno (ATmega328P) | ESP32 DevKit V1 | Wiring Notes & Constraints |
|---|---|---|---|
| VCC | 5V Pin | 3V3 Pin (or 5V if sensor requires) | Ensure supply is decoupled with a 100nF ceramic capacitor placed within 2mm of the sensor pin. |
| GND | GND | GND | Use thick ground wires (22 AWG min). Avoid sharing ground return paths with inductive loads. |
| OUT (Signal) | A0 - A5 | GPIO32 - GPIO39 (ADC1) | ESP32 Warning: Never use ADC2 pins (GPIO0, 2, 4, 12-15, 25-27) for sensors if WiFi is active; ADC2 is hijacked by the WiFi radio. |
A common mistake when interfacing electronic sensors with the ESP32 is wiring the analog output to GPIO34, only to find the readings freeze when the WiFi connects. GPIO34 is ADC1, which is safe, but if you accidentally wire to GPIO25 (ADC2), the WiFi driver will override your ADC readings. Always stick to ADC1 pins (GPIO32-39) for sensor inputs on ESP32.
The Math: Converting Raw ADC Counts to Physical Units
The most frequent point of failure in sensor projects is incorrect ADC math. The formula to convert a raw ADC reading to voltage is:
Voltage = (Raw_ADC_Count × V_ref) / ADC_Max_Steps
Arduino Uno (10-bit, 5V reference):
ADC_Max_Steps = 1023. V_ref = 5.0V.
Resolution = 5.0 / 1023 = 4.88 mV per step.
ESP32 (12-bit, 3.3V reference):
ADC_Max_Steps = 4095. V_ref = 3.3V.
However, the ESP32 ADC is notoriously non-linear, and the usable range with 11dB attenuation is roughly 0.1V to 2.5V. Using the basic formula (adc * 3.3 / 4095) on an ESP32 will yield errors of up to 15%. To fix this, modern ESP32 Arduino Core (v2.x and v3.x) includes the analogReadMilliVolts() function, which utilizes the factory-calibrated eFuse data to return a highly accurate millivolt reading, bypassing the non-linearity lookup tables entirely.
Worked Example: TMP36 on ESP32
The TMP36 datasheet specifies an output of 750mV at 25°C, with a scale factor of 10mV/°C. The formula for Celsius is: Temp_C = ((Voltage_mV - 750) / 10) + 25.
// ESP32 TMP36 Interfacing Code (Arduino Core v2.x+)
const int SENSOR_PIN = 34; // GPIO34 is on ADC1, safe for WiFi
void setup() {
Serial.begin(115200);
// Set attenuation to 11dB to allow readings up to ~2.5V
analogSetAttenuation(ADC_11db);
}
void loop() {
// Use the calibrated millivolt function, NOT analogRead()
uint32_t voltage_mV = analogReadMilliVolts(SENSOR_PIN);
// TMP36 Math: 750mV offset at 25C, 10mV per degree
float temp_c = ((voltage_mV - 750.0) / 10.0) + 25.0;
Serial.printf("Voltage: %lu mV | Temp: %.2f C\n", voltage_mV, temp_c);
delay(1000);
}
Calibration, Scaling, and Interference Sources
Even with perfect math, analog electronic sensors are vulnerable to environmental noise and manufacturing tolerances. Understanding what the output actually is, how to calibrate it, and how to filter interference is what separates a prototype from a reliable product.
Calibration and Scaling Requirements
Linear sensors (TMP36, ACS712) require single-point offset calibration. You measure a known baseline (e.g., 0A current or ice-water bath) and adjust the offset variable in your code to match. Non-linear resistive sensors (MQ-135, Thermistors) require curve fitting. For thermistors, you must implement the Steinhart-Hart equation using the manufacturer's A, B, and C coefficients. For MQ gas sensors, you must map the logarithmic Rs/R0 ratio using a lookup table or logarithmic regression derived from the datasheet's sensitivity graph.
Common Interference Sources
- 50/60Hz Mains Hum: Unshielded analog wires act as antennas, picking up electromagnetic fields from nearby AC wiring. This manifests as a slow, rhythmic oscillation in your raw ADC data.
- Switching Regulator Noise: Cheap buck converters (like the LM2596) used to step down 12V to 5V introduce high-frequency switching noise (typically 50kHz - 150kHz) onto the VCC rail, which the ADC aliases into your readings.
- High-Impedance Voltage Dividers: Using 1MΩ resistors in an LDR voltage divider creates a high-impedance source. The ESP32's ADC sampling capacitor cannot charge fully during the sampling window, resulting in artificially low and erratic readings.
Hardware and Software Fixes
To mitigate high-impedance and EMI issues, follow these hardware design rules outlined in Analog Devices' ADC layout guidelines:
- Lower the Impedance: Keep voltage divider resistors under 10kΩ. If power consumption is a concern, use an op-amp voltage follower (buffer) between the divider and the ADC pin.
- RC Low-Pass Filter: Solder a 100Ω series resistor and a 100nF ceramic capacitor to ground directly at the microcontroller's ADC pin. This creates a hardware low-pass filter with a cutoff frequency of ~16kHz, killing high-frequency switching noise before it hits the ADC.
- Twisted Pair Wiring: When running sensor wires longer than 15cm, twist the Signal and GND wires together. This ensures that any induced magnetic interference affects both wires equally, presenting as common-mode noise which the ADC inherently rejects.
- Software Oversampling: Instead of taking one reading, take 64 readings, sum them, and divide by 64 (or use a bit-shift right by 6). This increases the effective resolution of a 10-bit ADC to 13 bits and averages out random thermal noise.
For a deeper dive into minimizing noise in analog sensor circuits, refer to the Texas Instruments application note on analog sensor noise reduction. By combining the analogReadMilliVolts() function with a simple hardware RC filter, you can achieve laboratory-grade accuracy from basic analog electronic sensors on both Arduino and ESP32 platforms.






