3

I have a soil sensor that reports value once every 5 minutes, deepsleep in between. Is there a way to also report battery voltage (with ESP.getVcc())?

To get the battery voltage reading to work I need to set ADC_MODE(ADC_VCC); but that disables the reading of the sensor.

5
  • does the ADC_VCC use the same channel on the ADC that your sensor is using? Can you use another channel?
    – Chad G
    Commented May 22, 2018 at 20:06
  • can you set the mode to vcc after you take a sample and before you sleep?
    – dandavis
    Commented May 22, 2018 at 20:44
  • that disables the reading of the sensor ... so enable it after you read the voltage ... what is the problem?
    – jsotola
    Commented May 23, 2018 at 0:18
  • @ChadG esp8266 has only one analog pin
    – Juraj
    Commented May 23, 2018 at 5:06
  • you can use a digital pin and RC circuit to precisely measure voltage as a function of time
    – dandavis
    Commented May 24, 2018 at 18:42

2 Answers 2

3

to read VCC voltage, ADC pin must be kept unconnected. Additionally, the following line has to be added to the sketch: ADC_MODE(ADC_VCC);

The setting of a purpose of the analog pin of esp8266 is at low level and must be projected into the compiled binary. It can't be changed at runtime.

On esp8266 if you want to use the power sensing or to have more ADC you must use an external I2C ADC.

reference

1
  • Was afraid of that, but thanks for confirming.
    – hbruce
    Commented May 24, 2018 at 4:59
2

I found a solution that I believe works great.

Although the ADC_MODE macro cannot be modified after the board is started, we can actually set its integer input as the output of a function and then use RTC memory to trigger different modes, depending for example on how many times the board has been started.

#include "ESP8266WiFi.h" 
#define QUERY_VCC_INTERVAL  10

int adc_selection;
ADC_MODE(get_adc());

int get_adc(){

  typedef struct {
  uint32_t adc_mode;
  uint32_t count;
  } rtcStore;

  rtcStore rtcMem;
 
  system_rtc_mem_read(100, &rtcMem, sizeof(rtcMem));
  
  if ((rtcMem.adc_mode != ADC_VCC) && (rtcMem.adc_mode != ADC_TOUT)) return ADC_TOUT;

  return rtcMem.adc_mode;
}

int get_adc_and_write_change(){

  typedef struct {
  uint32_t adc_mode;
  uint32_t count;
  } rtcStore;

  int a;
  rtcStore rtcMem;
  
  system_rtc_mem_read(100, &rtcMem, sizeof(rtcMem));
  a = rtcMem.adc_mode;

  Serial.print("CYCLE NUMBER: ");
  Serial.println(rtcMem.count);

  if (rtcMem.count > QUERY_VCC_INTERVAL){
        rtcMem.adc_mode = ADC_VCC;
        rtcMem.count = 0;
  } else {
        rtcMem.adc_mode = ADC_TOUT;
        rtcMem.count++;
  }
  
  system_rtc_mem_write(100, &rtcMem, sizeof(rtcMem));

  return a;

}

void setup() { 

  int vcc;
  
  Serial.begin(9600);
  Serial.println(" ---------- ");
  delay(1000);
  
  adc_selection = get_adc_and_write_change();
  Serial.print("VALUE FOR ADC MODE WAS: ");
  Serial.println(adc_selection);

  vcc = ESP.getVcc();
  Serial.print("VALUE WHEN READING VCC: ");
  Serial.println(vcc);
 
  if (adc_selection == ADC_TOUT){
    Serial.println("VCC SHOULD BE 65535"); 
   } else {
    Serial.println("VCC SHOULD NOT BE 65535");
   }

  Serial.println("RESET BOARD TO CONTINUE");
  delay(1000);
  
}

void loop() {
} 

Note that the function gets executed very early on the board startup, so we cannot even count on using or writing to global variable definitions of the script's code. This is why all structures are defined within the get_adc function.

The above code triggers ADC_MODE(ADC_VCC) for every 10 times that ADC_MODE(ADC_TOUT) is triggered. This allows me to read analogue sensors for 10 times after the board is woken up from deep sleep and then read the VCC level to gauge the battery voltage once every 10 times.

Note also that to have VCC readings work correctly I need to connect analogue sensor power to a digital pin and use that to power the sensors ON/OFF as needed.

I have tested the above code with a NodeMCU v3, on the Arduino IDE.

1
  • Great solution from Danielfp. Idon't think the typedef struct needs to be defined twice though. It works for me when above the code.
    – Colin Kerr
    Commented Jul 10, 2024 at 10:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.