ESP32 - analogRead(A10) not working with WiFi

I am running into an issue getting analogRead(A10) to work with WiFi enabled on an ESP32 board. I've already had these boards produced at a FAB, so changing the analog pin at this point isn't possible.

I've just now discovered that, according to ESP32 documentation, ADC2 may not work with WiFi. In my code, when commenting out #include <WiFi.h> at the start and WiFi.begin(); in setup, analogRead works properly. With these included, it only outputs 0.

Is there anything I can do in the firmware to fix this? Is it possible to pause some function that WiFi is using to make the reading, then unpause it after? Anything else?

My code is below, used for detecting charge on a battery and outputting to charge indicator LEDs.

#include <WiFi.h>

#define LED_BUILTIN 2

#define LEVEL1 25           // Level1 : GPIO 25 of ESP32
#define LEVEL2 26           // Level2 : GPIO 26 of ESP32
#define LEVEL3 27           // Level3 : GPIO 27 of ESP32
#define LEVEL4 14           // Level4 : GPIO 14 of ESP32

#define VBUS_DETECT 12       //GPIO 13

#define BATTERY_READ A10      //GPIO 4(A10) : Analog READ PIN for the battery voltage

#define BATTERY_0   1950         // ADC value for Battery 0%  - 1950
#define BATTERY_25  2303         // ADC value for Battery 25% - 2200
#define BATTERY_50  2400         // ADC value for Battery 50% - 2275
#define BATTERY_75  2410         // ADC value for Battery 75% - 2310
#define BATTERY_100 2850         // ADC value for Battery 100%  2850

int LEVELS[4] = {25, 26, 27, 14};
int batSensorValue = 0;  // value read from the pot
int full_charged = 0;
hw_timer_t *Timer0_Cfg = NULL;
int prevBatIndex = 0;
int batTimerCount = 0;
int gSensorValue = 0;
int adjustedSensorValue = 0;
int functionalSensorValue = 0;
uint8_t sensorBuffer = 4;
bool chargeFlashFlag = 0;

int getLevelIndex(int value) {
  switch (value) {
    case 0 ... BATTERY_25 - 1:
      return 1;
    case BATTERY_25 ... BATTERY_50 - 1:
      return 2;
    case BATTERY_50 ... BATTERY_75 - 1:
      return 3;
    case BATTERY_75 ... BATTERY_100 - 1:
      return 4;  
    default:
      return 5;
  }
}


void IRAM_ATTR Timer0_ISR() {
  batTimerCount++;

  // read VBUS status in value
  int vbusStatus = digitalRead(VBUS_DETECT);  
  // read the analog in value:
  batSensorValue = analogRead(BATTERY_READ);
  gSensorValue += batSensorValue;

  if(batTimerCount < 10) return;    //continue after 10 loops, then average

  adjustedSensorValue = (vbusStatus == 1 ? ((gSensorValue/10)-58) : (gSensorValue/10));       //if plugged in, reduce sensor value

  if (  (BATTERY_0 - sensorBuffer) <= adjustedSensorValue <= (BATTERY_0 + sensorBuffer) ||
        (BATTERY_25 - sensorBuffer) <= adjustedSensorValue <= (BATTERY_25 + sensorBuffer) ||
        (BATTERY_50 - sensorBuffer) <= adjustedSensorValue <= (BATTERY_50 + sensorBuffer) ||
        (BATTERY_75 - sensorBuffer) <= adjustedSensorValue <= (BATTERY_75 + sensorBuffer) ||
        (BATTERY_100 - sensorBuffer) <= adjustedSensorValue <= (BATTERY_100 + sensorBuffer) )
  {
    functionalSensorValue = adjustedSensorValue + sensorBuffer + 1;
  }
  else functionalSensorValue = adjustedSensorValue; 

  int levelIndex = getLevelIndex(functionalSensorValue);    //define LED level - if plugged in, reduce sensor value

  if (levelIndex == 5) full_charged = 1; else full_charged = 0;

  Serial.print("levelIndex = ");
  Serial.println(levelIndex);

  Serial.print("sensor = ");
  Serial.println(adjustedSensorValue);

  batTimerCount = 0;
  gSensorValue = 0;
  
  
  if(prevBatIndex > vbusStatus) {
    prevBatIndex = 0;
    return;
  }

  for(int i = 0; i < 4; i++) {
    digitalWrite(LEVELS[i], i < levelIndex ? HIGH : LOW);                         //light charger LEDs
  }  

  if(full_charged == 0 && vbusStatus == 1 && chargeFlashFlag == 0)  {
    digitalWrite(LEVELS[levelIndex-1], !digitalRead(LEVELS[levelIndex-1]));       //flash charger LEDs if plugged in and not 100%
  }

  if (vbusStatus == 1) chargeFlashFlag = (chargeFlashFlag+1)%2;
  //Serial.println(chargeFlashFlag);

  prevBatIndex = vbusStatus;

}

void setup() {
  // initialize serial communications at 9600 bps:
  Serial.begin(115200);
  
  WiFi.begin();

  pinMode(LEVEL1, OUTPUT);
  pinMode(LEVEL2, OUTPUT);
  pinMode(LEVEL3, OUTPUT);
  pinMode(LEVEL4, OUTPUT);

  pinMode(VBUS_DETECT, INPUT);

  Timer0_Cfg = timerBegin(0, 80, true);
  timerAttachInterrupt(Timer0_Cfg, &Timer0_ISR, true);
  timerAlarmWrite(Timer0_Cfg, 100000, true);
  timerAlarmEnable(Timer0_Cfg);
}

void loop() {
  delay(1000);
}

1. Are you using 30-pin ESP32 Dev Board? If not, please post the picture of your ESP32 Board.

2. My 30-pin ESP32 Dev Board (Fig-1) shows that GPIO-4 has ADC2_CH0 as alternate function. Your delaration should be:
#define BATTERY_READ 4 //GPIO = ADC2_CH0


Figure-1:

3. The manufacturer's data sheets conatin the following:
ADC1_CH0 to ADC1_CH7
ADC2_CH0 to ADC2_CH9

4. As per data sheets and pin mapping diagram (Fi-2), GPIO-4 has no realtion with WiFi or Flash. GPIO_4/ADC2_CH0 is free and is useable.


Figure-2:

Thanks for the response. Good point, I should have clarified. I am using a 38-pin ESP32-WROOM-32D. The image here shows the pins:

It looks like GPIO4 is associated with ADC10, HSPIHD, HS1-DATA1, and TOUCH0. I'm not certain what these mean. From this, or or documentation, is there any relation with GPIO4 and WiFi?

30-pin ESP32 S and 38-pin ESP32 use the same 48-pin ESP32 MCU. In 38-pin version, the GPIO-4 is seen to contain ADC10 as alternate function which is as per data sheets ADC2-CH0.

Which board do you select from the IDE? I select "ESP32 Dev Module" for my 30pin version.

Figure-2 (made using official documents of Espressif Systems) shows that GPIO-4 is free and can be used. You can also look into the attached official documents/data sheets.
esp32_datasheet_en.pdf (827.7 KB)

But, here is a confusion (which I have discovered now) as to -- is it GPIO-4 or GPIO-8 that is being used by the Flash (Fig-2) ? An excerpt from data sheets (Fig-3); where, both GPIO-4 (ppin-24) and GPIO-8 (ppin-33) show are shown to contain SD_DATA1 as alternate functions:


Figure-3:

I am also selecting ESP32 Dev Module from the IDE. If GPIO4 does not interfere with WiFi functions, do you have any other ideas why it's not working? It's clear from my tests that adding or removing WiFi.begin() makes the difference between working / broken. Is there some WiFi subfunction using GPIO4 that could be disabled?

As the information of Fig-3 is confusing (to me) as to the use of GPIO-4 and GPIO-8, try to avoid using of GPIO-4 as ADC channel. Use some other GPIO as ADC channel and see if your WiFi works.

Unfortunately these boards have already been produced by a FAB, can't change it. I'm wondering if a software fix/workaround is at all possible, while continuing to use GPIO4.

If it is a double layer board, you can cut the PCB trace carefully and use jumpers as needed. Hope, you have made at least few PCBs from which one can be modified.

That's why, it is recommended to develop the project/product using Learning/Dev System and then manufacture the PCB for stnad-alone operation.

Can you psot a picture of the fabricated custom PCB/Board?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.