If you are trying to configure analog for Acebott ESP32 robotics kits, the direct answer is that you must use the ADC1-capable GPIO pins (typically GPIO 32, 33, 34, 35, 36, and 39) exposed on the Acebott shield. The ESP32’s internal ADC is notoriously noisy and non-linear at the voltage rails, meaning a raw analogRead() will yield jittery data. To get stable analog readings for line trackers, potentiometers, or light sensors on an Acebott board, you must use 12-bit resolution, apply an 11dB attenuation, and implement software multisampling.

This guide covers the exact pin mappings for the Acebott ESP32 STEM shield, provides production-ready Arduino C++ code with built-in noise filtering, and details the specific hardware traps that cause ADC failures on this platform.

Hardware Spec Sheet & Parts List

Target Board Variant: This guide targets the Acebott ESP32 Robotics Shield (v2.x) paired with a standard ESP32-WROOM-32E DevKit module. The shield routes specific ESP32 GPIOs to labeled 'A0-A3' or 'Sensor' ports.

Difficulty Rating: Intermediate (Requires understanding of voltage dividers and ADC attenuation)
Estimated Time: 25 minutes

Required Components

  • Microcontroller: ESP32-WROOM-32E DevKit V1 (30-pin or 38-pin variant, depending on your Acebott shield header)
  • Shield: Acebott ESP32 Robotics Expansion Board
  • Analog Sensor 1: 10kΩ Linear Taper Potentiometer (for testing variable voltage)
  • Analog Sensor 2: GL5528 Photoresistor (LDR) with a 10kΩ pull-down resistor
  • Wiring: 22 AWG solid core jumper wires
  • Measurement: True-RMS Digital Multimeter (to verify actual voltage vs. ADC reported voltage)

Acebott ESP32 Analog Pin Mapping

The Acebott shield silkscreen often labels analog ports as A0, A1, A2, etc. However, the ESP32 does not have dedicated 'A' pins like an Arduino Uno. These labels map to specific GPIOs that are hardwired to the ESP32's internal SAR ADC.

Acebott Silkscreen ESP32 GPIO ADC Channel WiFi Safe? Notes & Constraints
A0 / Port 1 GPIO 36 (SVP) ADC1_CH0 Yes Input only. No internal pull-up. Best for LDRs.
A1 / Port 2 GPIO 39 (SVN) ADC1_CH3 Yes Input only. Susceptible to RF noise if WiFi is active.
A2 / Port 3 GPIO 34 ADC1_CH6 Yes Input only. Standard analog input.
A3 / Port 4 GPIO 35 ADC1_CH7 Yes Input only. Standard analog input.
Unused / Internal GPIO 32 ADC1_CH4 Yes Often used for internal battery voltage monitoring on Acebott boards.
Unused / Internal GPIO 33 ADC1_CH5 Yes Available on breakout headers.
Critical Warning: Never use GPIO 4, 0, 2, 15, 25, 26, 27, 12, 13, or 14 for analog sensors if your Acebott robot uses WiFi or Bluetooth. These map to ADC2, which is completely disabled and will return garbage data or zeros when the WiFi radio is active. Always stick to the ADC1 pins listed above.

Stable Analog Reading: The Code

The ESP32's internal ADC suffers from high noise floors and non-linearity near 0V and 3.3V. The code below targets the ESP32 Arduino Core v2.0.14+. It uses analogReadMilliVolts(), which automatically applies the factory eFuse calibration data stored on your specific ESP32 silicon, vastly improving accuracy over the raw analogRead() function. It also implements a 16-sample moving average to eliminate high-frequency jitter.

/*
 * Acebott ESP32 Analog Sensor Reader
 * Target: Acebott ESP32 Shield + ESP32-WROOM-32E
 * Core: ESP32 Arduino Core v2.0.14 or newer
 */

// Pin definitions mapped to Acebott Shield ADC1 ports
#define PIN_POTENTIOMETER 34  // Acebott A2
#define PIN_LDR           36  // Acebott A0

// Multisampling configuration to smooth ESP32 ADC noise
const int SAMPLE_COUNT = 16;
const int SATURATION_THRESHOLD_MV = 3100; // ESP32 ADC non-linear above ~3.1V

void setup() {
  Serial.begin(115200);
  delay(1000); // Allow serial monitor to connect
  
  // Configure ADC for maximum resolution and voltage range
  analogReadResolution(12);       // 12-bit (0-4095)
  analogSetAttenuation(ADC_11db); // Full 0-3.3V range
  
  Serial.println("Acebott ESP32 Analog Reader Initialized.");
}

void loop() {
  // Read Potentiometer with multisampling and error handling
  int pot_mv = readStableAnalogMV(PIN_POTENTIOMETER);
  
  // Read LDR with multisampling and error handling
  int ldr_mv = readStableAnalogMV(PIN_LDR);
  
  // Error Handling: Check for ADC saturation / overvoltage
  if (pot_mv >= SATURATION_THRESHOLD_MV) {
    Serial.printf("[WARN] Potentiometer saturated at %d mV. Check for 5V leak!\n", pot_mv);
  } else {
    Serial.printf("Potentiometer: %d mV\n", pot_mv);
  }
  
  if (ldr_mv >= SATURATION_THRESHOLD_MV) {
    Serial.printf("[WARN] LDR saturated at %d mV. Check pull-down resistor.\n", ldr_mv);
  } else {
    Serial.printf("LDR: %d mV\n", ldr_mv);
  }
  
  Serial.println("-------------------");
  delay(500);
}

// Function to read analog voltage in millivolts with noise filtering
int readStableAnalogMV(int pin) {
  long total_mv = 0;
  for (int i = 0; i < SAMPLE_COUNT; i++) {
    // analogReadMilliVolts uses eFuse calibration for accuracy
    total_mv += analogReadMilliVolts(pin);
  }
  return (int)(total_mv / SAMPLE_COUNT);
}

Debugging ADC Failures & Error Strings

When configuring analog for Acebott ESP32 builds, you will inevitably hit hardware or software snags. If your serial monitor misbehaves, check these first three things:

  1. Verify Voltage Levels: Use a multimeter to ensure the sensor output does not exceed 3.3V. Acebott kits sometimes include 5V sensors; plugging these directly into the shield will saturate the ADC and can permanently damage the GPIO.
  2. Check WiFi/ADC2 Conflicts: If your code initializes WiFi.begin(), ensure you are not using ADC2 pins (GPIO 25, 26, 27, etc.).
  3. Confirm Grounding: The sensor ground must be tied to the Acebott shield's GND. A floating ground will cause the ADC to read random electromagnetic noise.

Common Error Strings and Ranked Causes

Symptom 1: analogRead() returns 4095 continuously (or analogReadMilliVolts returns ~3300)

  • Cause 1 (Most Likely): Overvoltage. A 5V sensor is connected without a voltage divider. The internal ESD protection diodes are clamping the pin to VDD (3.3V).
  • Cause 2: Missing pull-down resistor on an LDR or open-circuit potentiometer wiper. The pin is floating high.
  • Cause 3: You are attempting to read an output-only pin or a pin strapped to VDD on the Acebott shield.

Symptom 2: Readings fluctuate ±150 counts on a stable DC voltage

  • Cause 1: ESP32 inherent ADC noise. Fix this by implementing the multisampling loop provided in the code above.
  • Cause 2: USB power supply noise. The 5V rail from a cheap PC USB port is notoriously noisy. Power the Acebott board via a regulated LiPo battery or a high-quality 5V wall adapter.

Symptom 3: Guru Meditation Error: Core 1 panic'ed (Interrupt wdt timeout on CPU 0)

  • Cause 1: You placed analogRead() or analogReadMilliVolts() inside an Interrupt Service Routine (ISR). The ESP32 ADC read function takes several microseconds and uses RTOS mutexes, which will trigger the Watchdog Timer if called from an ISR. Move analog reads to the main loop() and use a boolean flag in your ISR.

Extending and Simplifying the Build

How to Simplify

If you do not need precise millivolt readings and only care about relative changes (e.g., tracking a line or detecting basic light/dark thresholds), you can simplify the code by dropping analogReadMilliVolts() and using the raw analogRead(). This saves a small amount of CPU overhead. Just remember that raw values will drift with temperature and vary from board to board.

How to Extend (The 16-Bit Upgrade)

The ESP32's internal 12-bit ADC is fundamentally flawed for precision robotics (like calculating exact distances via IR sensors). To extend this build for professional-grade precision, bypass the internal ADC entirely and add an ADS1115 16-Bit I2C ADC.

  • Wiring: Connect ADS1115 SDA to GPIO 21, SCL to GPIO 22, VDD to 3.3V, and GND to GND on the Acebott shield.
  • Result: You gain true 16-bit resolution (0-65535), a programmable gain amplifier (PGA), and hardware-level noise rejection.
  • Cost: An ADS1115 breakout board costs roughly $4 to $8, a highly cost-effective upgrade for advanced Acebott robotics projects.

Frequently Asked Questions

Can I use analog for Acebott ESP32 while WiFi is connected?

Yes, but only if you use ADC1 pins (GPIO 32, 33, 34, 35, 36, 39). The ESP32's WiFi radio shares hardware resources with ADC2. The moment you call WiFi.begin(), the hardware multiplexer locks out ADC2 pins (like GPIO 25, 26, 27). If your Acebott shield routes a specific sensor port to an ADC2 pin, you must either disable WiFi, move the sensor wire to an ADC1 pin, or use an external I2C ADC.

Why does my Acebott line-tracking sensor give digital highs instead of analog values?

Many line-tracking modules included in STEM kits have a built-in comparator chip (like the LM393) with a blue trimmer potentiometer. These modules output a clean Digital HIGH/LOW on the DO (Digital Out) pin, and an analog voltage on the AO (Analog Out) pin. If you are reading 4095 or 0 exclusively, ensure you have wired the sensor's AO pin to the Acebott shield's analog port, not the DO pin. Furthermore, verify the sensor is powered by 3.3V; if powered by 5V, the AO pin will output up to 5V, saturating the 3.3V ESP32 ADC.

How do I calibrate the 3.3V reference on the Acebott board?

You do not need to manually calibrate it in software if you are using ESP32 Arduino Core v2.0.x or newer. Espressif burns a unique calibration value into the eFuse of every ESP32 chip at the factory. The analogReadMilliVolts() function automatically queries this eFuse value and applies the correction curve. If you are using an older core version, you must manually map the raw ADC values using a multimeter and a map() function, but upgrading your board manager package is the recommended fix.