Interesting ESP32 issue: Can't use analogRead with WiFi and/or ESP_WiFiManager Library

See already solved issue Not able to read analog port when using the autoconnect example in ESP_WiFiManager Library

The root cause of this issue is as follows

1. ESP32 has 2 ADCs, named ADC1 and ADC2

2. ESP32 ADCs functions

  • ADC1 controls ADC function for pins GPIO32-GPIO39
  • ADC2 controls ADC function for pins GPIO0, 2, 4, 12, 13, 14, 15, 25, 26 and 27

3… ESP32 WiFi uses ADC2 for WiFi functions

  • in order to use ADC2 for other functions, we have to acquire complicated firmware locks and very difficult to do
  • It’s not advisable to use ADC2 with WiFi

See in file adc_common.c

So it’s suggested to use ADC1, and pins GPIO32-GPIO39

Please see the test results in Not able to read analog port when using the autoconnect example

2 Likes

This is the quick fix if somehow we must use those pins serviced by ADC2 (GPIO0, 2, 4, 12, 13, 14, 15, 25, 26 and 27) to work with ESP32 WiFi

#if !( ESP32 || ESP8266 )
  #error This code is intended to run on the ESP32/ESP8266 platform! Please check your Tools->Board setting.
#endif

#define USE_MULTI_WIFI      true

#if ESP32
  #include <WiFi.h>
  #include <WiFiMulti.h>

  WiFiMulti wifiMulti;

  #define USE_ADC2      true
  //#define USE_ADC2      false

  #if USE_ADC2
    // ADC2 for GPIO0, 2, 4, 12, 13, 14, 15, 25, 26 and 27
    int sensorPin1   = 12;
    int sensorPin2   = 14;  
  #else
    // DC1 for GPIO032-GPIO39
    int sensorPin1   = 34;
    int sensorPin2   = 35;
  #endif
  
  // Kludge to fix ADC2 + WiFi
  #include "soc/sens_reg.h"    // needed for manipulating ADC2 control register
  uint64_t reg_b;             // Used to store ADC2 control register
  //////
  
#elif ESP8266
  #include <ESP8266WiFi.h>
  #include <ESP8266WiFiMulti.h>

  ESP8266WiFiMulti wifiMulti;
  
  int sensorPin1    = 12;     // select the input pin for the potentiometer
  int sensorPin2    = 13;     // select the input pin for the potentiometer
#endif

#define SSID_MAX_LEN      32
#define PASS_MAX_LEN      64

typedef struct
{
  char ssid[SSID_MAX_LEN + 1];
  char pass[PASS_MAX_LEN + 1];
}  WiFi_Credentials;

WiFi_Credentials WiFi_Creds[] =
{
  { "HueNet1", "12345678"},
  { "HueNet2", "12345678"},
  { "HueNet3", "12345678"}
};

#define NUMBER_SSIDS    ( sizeof(WiFi_Creds) / sizeof(WiFi_Credentials) )

uint8_t status;


int sensorValue = 0;            // variable to store the value coming from the sensor

uint8_t connectMultiWiFi(void)
{
  Serial.println("\nConnecting Wifi...");

  int i = 0;
  status = wifiMulti.run();
  delay(3000);

  while ( ( i++ < 10 ) && ( status != WL_CONNECTED ) )
  {
    status = wifiMulti.run();

    if ( status == WL_CONNECTED )
      break;
    else
      delay(3000);
  }

  if ( status == WL_CONNECTED )
  {
    Serial.println("WiFi connected to after " + String(i) + " times.");
    Serial.println("SSID = " + WiFi.SSID());
    Serial.println("RSSI = " + String(WiFi.RSSI()));
    Serial.println("Channel: " + String(WiFi.channel()));
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
  }
  else
    Serial.println("WiFi not connected");

  return status;
}

void check_WiFi(void)
{
  if ( (WiFi.status() != WL_CONNECTED) )
  {
    Serial.println("\nWiFi lost. Call connectMultiWiFi in loop");
    connectMultiWiFi();
  }
}

#if (ESP32 && USE_ADC2)
void save_ADC_Reg(void)
{
  // Save ADC2 control register value : Do this before begin Wifi/Bluetooth
  reg_b = READ_PERI_REG(SENS_SAR_READ_CTRL2_REG);
}

void restore_ADC_Reg(void)
{
  // ADC2 control register restoring 
  WRITE_PERI_REG(SENS_SAR_READ_CTRL2_REG, reg_b);
  SET_PERI_REG_MASK(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_DATA_INV);
}
#endif

void readAnalog(void)
{
#if (ESP32 && USE_ADC2) 
  restore_ADC_Reg();
#endif
  
  sensorValue = analogRead(sensorPin1);
  Serial.print("Pin " + String(sensorPin1) + " = ");
  Serial.println(sensorValue);

  sensorValue = analogRead(sensorPin2);
  Serial.print("Pin " + String(sensorPin2) + " = ");
  Serial.println(sensorValue);
}

void check_status(void)
{
  static ulong checkstatus_timeout  = 0;
  static ulong checkwifi_timeout    = 0;

  static ulong current_millis;

#define WIFICHECK_INTERVAL    1000L
#define ANALOGREAD_INTERVAL   2000L

  current_millis = millis();

#if USE_MULTI_WIFI
  // Check WiFi every WIFICHECK_INTERVAL (1) seconds.
  if ((current_millis > checkwifi_timeout) || (checkwifi_timeout == 0))
  {
    //check_WiFi();
    checkwifi_timeout = current_millis + WIFICHECK_INTERVAL;
  }
#endif

  // Print hearbeat every ANALOGREAD_INTERVAL (2) seconds.
  if ((current_millis > checkstatus_timeout) || (checkstatus_timeout == 0))
  {
    readAnalog();
    checkstatus_timeout = current_millis + ANALOGREAD_INTERVAL;
  }
}

void setup()
{
  // put your setup code here, to run once:
  Serial.begin(115200);
  while (!Serial);

  delay(200);

  Serial.print("\nStarting WiFiMulti_ESP32_AnalogRead on ");
  Serial.println(ARDUINO_BOARD);

#if (ESP32 && USE_ADC2)
  save_ADC_Reg();
#endif  

#if USE_MULTI_WIFI
  for (int i = 0; i < NUMBER_SSIDS; i++)
  {
    wifiMulti.addAP(WiFi_Creds[i].ssid, WiFi_Creds[i].pass);
  }

  connectMultiWiFi();
#endif
  
}

void loop()
{
  // put your main code here, to run repeatedly
  check_status();
}

and this is the terminal output when using in sketch

#define USE_ADC2 true
Starting WiFiMulti_ESP32_AnalogRead on ESP32_DEV

Connecting Wifi...
WiFi connected to after 1 times.
SSID = HueNet1
RSSI = -40
Channel: 2
IP address: 192.168.2.164
Pin 12 = 24
Pin 14 = 20
Pin 12 = 67
Pin 14 = 68
Pin 12 = 17
Pin 14 = 16
Pin 12 = 54
Pin 14 = 81
Pin 12 = 119
Pin 14 = 17
Pin 12 = 51
Pin 14 = 69
Pin 12 = 20
Pin 14 = 5
Pin 12 = 20
Pin 14 = 82
Pin 12 = 36
Pin 14 = 14
Pin 12 = 32
Pin 14 = 22
Pin 12 = 81
Pin 14 = 35
Pin 12 = 83
Pin 14 = 66
Pin 12 = 32
Pin 14 = 26
Pin 12 = 105
Pin 14 = 85
Pin 12 = 80
Pin 14 = 102
Pin 12 = 74
2 Likes