Считать напряжение батареи и значение аналогового датчика с помощью NodeMCU ESP8266.

У меня есть датчик почвы, который сообщает значение каждые 5 минут, а в промежутках находится в состоянии глубокого сна. Есть ли способ также сообщить о напряжении батареи (с помощью ESP.getVcc())?

Чтобы показания напряжения батареи работали, мне нужно установить ADC_MODE(ADC_VCC); но это отключает чтение датчика.

, 👍3

Обсуждение

использует ли ADC_VCC тот же канал на АЦП, который использует ваш датчик? Вы можете использовать другой канал?, @Chad G

Вы можете установить режим vcc после взятия пробы и перед сном?, @dandavis

это отключает чтение датчика ... так что включите его после того, как вы читаете напряжение ... в чем проблема?, @jsotola

@ChadG esp8266 имеет только один аналоговый вывод, @Juraj

вы можете использовать цифровой контакт и RC-цепь для точного измерять напряжение как функцию времени, @dandavis


2 ответа


Лучший ответ:

3

для считывания напряжения VCC вывод ADC должен оставаться неподключенным. Кроме того, в скетч необходимо добавить следующую строку: ADC_MODE(ADC_VCC);

Настройка назначения аналогового вывода esp8266 находится на низком уровне и должна быть проецирована в скомпилированный бинарник. Его нельзя изменить во время выполнения.

На esp8266, если вы хотите использовать измерение мощности или иметь больше АЦП, вы должны использовать внешний АЦП I2C.

справочник

,

Боялся этого, но спасибо за подтверждение., @hbruce


2

Я нашел решение, которое, по моему мнению, отлично работает.

Хотя макрос ADC_MODE не может быть изменен после запуска платы, мы можем фактически установить его целочисленный ввод в качестве вывода функции, а затем использовать память RTC для запуска различных режимов, в зависимости, например, от того, сколько раз плата была началось.

#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() {
} 

Обратите внимание, что функция запускается очень рано при запуске платы, поэтому мы даже не можем рассчитывать на использование или запись в определения глобальных переменных кода скрипта. Вот почему все структуры определяются в функции get_adc.

Приведенный выше код запускает ADC_MODE(ADC_VCC) для каждых 10 срабатываний ADC_MODE(ADC_TOUT). Это позволяет мне считывать аналоговые датчики 10 раз после выхода платы из глубокого сна, а затем считывать уровень VCC для измерения напряжения батареи каждые 10 раз.

Обратите внимание, что для правильной работы показаний VCC мне нужно подключить питание аналогового датчика к цифровому контакту и использовать его для включения/выключения питания датчиков по мере необходимости.

Я протестировал приведенный выше код с помощью NodeMCU v3 в Arduino IDE.

,