• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Глюки с выходом из длительного сна

Доброго дня.
Делаю мерялку напряжения на аккумуляторе в машине.
Смысл такой: Проснулся, померял, если надо подключился, отправил почту и пошёл спать. Поставил параметр ESP.deepSleep(ESP.deepSleepMax()); Принёс домой, подключил к блоку питания и оставил на выходные. В итоге отработал только 7 раз подряд и всё. Куда копать? Есть мысль, что плохой контакт между reset и резистором и D0. Сделано на ... ну проводках для бредборда. Но
 

CodeNameHawk

Moderator
Команда форума
Ошибка в коде.
Наверняка нет проверок доступности сети.
 
Спасибо за ответ.
Не очень понял, что именно вы имеете ввиду. Но прикладываю код.
Добавил туда комментарии по понятию. Примерно так.
Код:
/*
  Rui Santos
  Complete project details at:
   - ESP32: https://RandomNerdTutorials.com/esp32-send-email-smtp-server-arduino-ide/
   - ESP8266: https://RandomNerdTutorials.com/esp8266-nodemcu-send-email-smtp-server-arduino/

   For ESP8266 devices that don't have external SRAM/PSRAM chip installed, choose the MMU option 3, 16KB cache + 48KB IRAM and 2nd Heap (shared).
 
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
  Example adapted from: https://github.com/mobizt/ESP-Mail-Client
*/

// To send Emails using Gmail on port 465 (SSL), you need to create an app password: https://support.google.com/accounts/answer/185833

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP_Mail_Client.h>

//#define WIFI_SSID "Mi MIX 2S"
//#define WIFI_PASSWORD "987654321"

#define WIFI_SSID "Gosha_Antonina"
#define WIFI_PASSWORD "0505973144"

#define SMTP_HOST "smtp.gmail.com"
#define SMTP_PORT 465

/* The sign in credentials */
#define AUTHOR_EMAIL "почта@gmail.com"
#define AUTHOR_PASSWORD "пароль"

/* Recipient's email*/
#define RECIPIENT_EMAIL "почта@gmail.com"

/* The SMTP Session object used for Email sending */
SMTPSession smtp;

/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status);

int BAT= A0;                          // Аналоговый вход А0 для измерения напряжения батареи
float RatioFactor=5.54;                // Коэффициент соотношения резисторов
bool trigger_Send = true;
float Tvoltage_Threshold_above = 12.6;
float Tvoltage_Threshold_below = 12.4;

int value = LOW;
  float Tvoltage=0.0;
  float Vvalue=0.0,Rvalue=0.0;
unsigned long send_time;                              // Переменная для хранения времени отправки сообщения(через сколько следующее)
//String textMsg; //--> Variable to hold all data that will be sent to email
//ESPTimeHelper ETH; //--> ESPTimeHelper declaration. This is used to get time data from the server.

unsigned long startTime;

void setup(){
  Serial.begin(115200);
  Serial.println();
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
////////Подключаемся в течении 10 секунд, а если нет то нет. По-моим экспериментам хватает. В примере стояло даже 5 секунд, но к телефону не успевало подключаться.  
   while (WiFi.status() != WL_CONNECTED && (millis() - startTime) <= 10000) // try for 10 seconds   
      {
        delay(500);
        Serial.print(".");
      }

  Serial.print("Connecting to AP");
  Serial.println("");
 
//////////////Не подключился??? Иди спать, потом попробуешь сначала.

  if (WiFi.status() != WL_CONNECTED)
  { Serial.println("I'm awake, but I'm going into deep sleep mode for hour without WIFI");
    //ESP.deepSleep(6000e6);
    ESP.deepSleep(ESP.deepSleepMax());
 }
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.println();
 
//----------------------------------------Get time data from server
//  ETH.TZ = 2; //--> GMT+2 . See the GMT list here: https://en.wikipedia.org/wiki/List_of_UTC_time_offsets
 
  // Daylight Saving Time. If your location does not have Daylight Saving Time, just enter the value 0.
//  ETH.DST_MN = 0; //--> See the DST list here: https://en.wikipedia.org/wiki/Daylight_saving_time_by_country

//  Serial.println("Getting time data from server. Please wait...");
//  if (!ETH.setClock(ETH.TZ, ETH.DST_MN)){
//    Serial.println("Can't set clock...");
//    return;
//  }
//  Serial.println("Successfully Get time data.");
  //----------------------------------------

 


}
void loop(){
 

  for(unsigned int i=0;i<10;i++){
    Vvalue=Vvalue+analogRead(BAT);                  // Считываем значение с АЦП
     delay(5);                             
 }
  Vvalue=(float)Vvalue/10.0;                      // Находим среднее значение из 10 измерений
  Rvalue=(float)(Vvalue/1024.0)*3.3;              //Конвертируем значение
  Tvoltage=Rvalue*RatioFactor;                    //Находим исходное напряжение, умножив его на коэффициент
  Serial.print(Vvalue);
  Serial.println("V Analog input");
  Serial.print(Tvoltage);
  Serial.println("V battery input");


  Serial.print("Напряжение - ");
  Serial.print(Tvoltage);
  Serial.println("V");

  if(Tvoltage <= 12.8) {

 

    ///////
     /** Enable the debug via Serial port
   * none debug or 0
   * basic debug or 1
  */
  smtp.debug(1);

  /* Set the callback function to get the sending results */
  smtp.callback(smtpCallback);

  /* Declare the session config data */
  ESP_Mail_Session session;

  /* Set the session config */
  session.server.host_name = SMTP_HOST;
  session.server.port = SMTP_PORT;
  session.login.email = AUTHOR_EMAIL;
  session.login.password = AUTHOR_PASSWORD;
  session.login.user_domain = "";

  /* Declare the message class */
  SMTP_Message message;

  /* Set the message headers */
  message.sender.name = "ESP";
  message.sender.email = AUTHOR_EMAIL;
  message.subject = "ESP Battery voltage";
  message.addRecipient("Gosha", RECIPIENT_EMAIL);

// Сообщение письма
  String textMsg;
  textMsg = "Напряжение батареи = " + String(Tvoltage)+"V";
   message.text.content = textMsg.c_str();
  message.text.charSet = "utf-8";
  message.text.transfer_encoding = Content_Transfer_Encoding::enc_7bit;
  message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_high;
  message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay;
 
      if (!smtp.connect(&session)) return;                    // Подключение к серверу с конфигурацией сеанса



      //////
    if(millis() - send_time > 60000) {                         // 1 минута = 60000
        if (!MailClient.sendMail(&smtp, &message)) Serial.println("Ошибка отправки сообщения, " + smtp.errorReason());
        send_time = millis();
    }

  /* Connect to server with the session config */
  if (!smtp.connect(&session))
    return;

  /* Start sending Email and close the session */
    if (!MailClient.sendMail(&smtp, &message))
    Serial.println("Error sending Email, " + smtp.errorReason());

 ////// Закончили всё, идем спать. 

    }
    Serial.println("I'm awake, but I'm going into deep sleep mode for hour");
    //ESP.deepSleep(6000e6);
    ESP.deepSleep(ESP.deepSleepMax());
}





/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status){
  /* Print the current status */
  Serial.println(status.info());

  /* Print the sending result */
  if (status.success()){
    Serial.println("----------------");
    ESP_MAIL_PRINTF("Message sent success: %d\n", status.completedCount());
    ESP_MAIL_PRINTF("Message sent failled: %d\n", status.failedCount());
    Serial.println("----------------\n");
    struct tm dt;

    for (size_t i = 0; i < smtp.sendingResult.size(); i++){
      /* Get the result item */
      SMTP_Result result = smtp.sendingResult.getItem(i);
      time_t ts = (time_t)result.timestamp;
      localtime_r(&ts, &dt);

      ESP_MAIL_PRINTF("Message No: %d\n", i + 1);
      ESP_MAIL_PRINTF("Status: %s\n", result.completed ? "success" : "failed");
      ESP_MAIL_PRINTF("Date/Time: %d/%d/%d %d:%d:%d\n", dt.tm_year + 1900, dt.tm_mon + 1, dt.tm_mday, dt.tm_hour, dt.tm_min, dt.tm_sec);
      ESP_MAIL_PRINTF("Recipient: %s\n", result.recipients);
      ESP_MAIL_PRINTF("Subject: %s\n", result.subject);
    }
    Serial.println("----------------\n");
  }
}
 

CodeNameHawk

Moderator
Команда форума
Попробуйте отладку, перед переходом в сон, выведе нужные зачения в сериал, такие как размер свободной памяти, отправилась ли почта.
 
Спасибо за ответ. Я пошёл гуглить, но не разобрался как вывести размер свободной памяти (я понимаю, что речь про ESP.getFreeHeap) в сериал. Не получилось.
Но! Я поставил в прошивке сон на минуту. И он уже отправил 69 писем (хорошо, что это бесплатно), я отключал ему WiFi и смотрел, что он просыпается, проверяет и идёт спать снова... Ну нет претензий.
Из этого делаю вывод, что проблема в именно длительном сне. Как поступить? Я могу уменьшить интервал даже до 3 часов например. Не сильно хочется (ну потому что как бы не надо), но можно. Вот с цифрой у меня тогда проблема. Получается 10800е6. Итого должно выйти около 3 часов.
 

svs2007m

Active member
Дружище все давно придумано. У Китайцев в прикуриватель и ... вуаля. Зарядка по USB 2-4А + индикация питания. Цена приемлемая. Ваш колхоз... Ну удачи :)
 
Дружище все давно придумано. У Китайцев в прикуриватель и ... вуаля. Зарядка по USB 2-4А + индикация питания. Цена приемлемая. Ваш колхоз... Ну удачи :)
Спасибо конечно. И он отправляет домой почту, что пора бы зарядить аккумулятор? И кушает на себя что-то приемлимое? Или надо каждый день ходить и смотреть, чё оно там показывает в прикуривателе?
Так что останусь в своём колхозе.
 

svs2007m

Active member
Или надо каждый день ходить и смотреть, чё оно там показывает в прикуривателе?
А это точно для машины на которой ВЫ ездите ? Вам аккумулятор от дедушки достался ? Или "Зеленая энергетика" ? Или нравится движуха снял зарядил и пока спокоен ?
 

nikolz

Well-known member
Доброго дня.
Делаю мерялку напряжения на аккумуляторе в машине.
Смысл такой: Проснулся, померял, если надо подключился, отправил почту и пошёл спать. Поставил параметр ESP.deepSleep(ESP.deepSleepMax()); Принёс домой, подключил к блоку питания и оставил на выходные. В итоге отработал только 7 раз подряд и всё. Куда копать? Есть мысль, что плохой контакт между reset и резистором и D0. Сделано на ... ну проводках для бредборда. Но
У ESP8266 есть проблема выхода из сна. о ней много есть сообщений на англоязычных сайтах.
я там выкладывал свое решение проблемы. кому-то помогло, мне например.
Поищите в инете, давно это было, ссылок не сохранил.
 
У ESP8266 есть проблема выхода из сна. о ней много есть сообщений на англоязычных сайтах.
я там выкладывал свое решение проблемы. кому-то помогло, мне например.
Поищите в инете, давно это было, ссылок не сохранил.
Спасибо за ответ. Читал Вас на хабре ещё до прихода на форум.
Я смотрел много и на англоязычных сайтах, но возможно не знаю как правильно спросить у Гугла, чтобы найти. Из того, что я находил и понял, что гарантированно работает только чуть больше часа (0xffffffff). Плюс обязательно диод или резистор (у меня резистор).
Но если честно, то с Вашим ником гугл ничего по запросу не показал. Значит я спрашиваю не то. Подскажите пожалуйста, какой сайт вы имеете в виду.
 

nikolz

Well-known member
Спасибо за ответ. Читал Вас на хабре ещё до прихода на форум.
Я смотрел много и на англоязычных сайтах, но возможно не знаю как правильно спросить у Гугла, чтобы найти. Из того, что я находил и понял, что гарантированно работает только чуть больше часа (0xffffffff). Плюс обязательно диод или резистор (у меня резистор).
Но если честно, то с Вашим ником гугл ничего по запросу не показал. Значит я спрашиваю не то. Подскажите пожалуйста, какой сайт вы имеете в виду.
На днях пришло сообщение с сайта, если интересно, то вот ссылка на последнее сообщение.
 

pvvx

Активный участник сообщества
Выход из deep-sleep() ничем не отличается от старта чипа по сигналу Reset.

Т.е., в первую очередь, необходимо проверить состояние сигналов на GPIO для нормального старта и правильное соединение GPIO16 c RESET.

Другой проблемой может являться запуск RTC таймера дергающего RESET через GPIO16. Это у же относится к коду вашего приложения. Т.е., до запуска deep-sleep(), желательно отключить всю активность вашего приложения – всякие таймеры, wifi и прочие процессы. Код функции deep-sleep(), как и всё в ESP, написан достаточно криво и его выполнение не гарантированно. К примеру в первые несколько лет SDK нельзя было запускать deep-sleep() на повышенной частоте CPU. Это приводило к случайному сбою в более 50% случаев.

Описывать все тонкости ПО ESP нет смысла, но вам необходимо удостовериться, что ваш код всегда отрабатывает правильно и к моменту вызова deep-sleep() всё хорошо – нет других ошибок.
 

pvvx

Активный участник сообщества
Спасибо за ответ. Читал Вас на хабре ещё до прихода на форум.
Код функции перевода чипа в режим deep-sleep, данный мной и распространенный nikolz используется неверно. Он должен выполняться из IRAM, перед исполнением должны быть запрещены все прерывания и после всех команд установки регистров RTC (перед return функции) должен выполняться while(1); . Это только окончательная часть функции deep-sleep созданная из реверса SDK. В ней нет перевода Flash в sleep режим и прочего...
 

pvvx

Активный участник сообщества
Принёс домой, подключил к блоку питания и оставил на выходные. В итоге отработал только 7 раз подряд и всё. Куда копать?
Проверить, не было-ли отключения сети :)
А так-же проверить, что там на выводах и питании самого ESP при deep-sleep. Многие стабилизаторы не могут работать на нулевую нагрузку - это указано в их документации и без нагрузки чаще всего выдают пилообразное напряжение.
Так-же необходимо проверить что там у вас идет на выводы ESP - вдруг там китай-фича с USB-COM чипом, с которого идет не 3В, а больше, когда нагрузки нет и чип получает питание более 3.3В через защитный диод на GPIO.
Особо надо обратить внимание, что на входе ADC НЕЗЯ превышать напряжение более 1.1В - иначе ESP8266 виснет и глючит.

PS: гадать можно долго, т.к. взятый вами чип имеет множественные аппаратные глюки, а типовой софт к нему, особенно в Arduino - это вообще глюкодром.
 
Сверху Снизу