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

Нужна помощь light sleep, не реагирует на время сна в light sleep

alexsvk

New member
Здравствуйте. Пересмотрел много тем на форуме, но никак не могу разобраться с light sleep. Есть несколько проблем:
1) Прерывание по кнопке срабатывает отлично. А вот с прерыванием по таймеру есть проблемы. Esp просто выходит из сна циклически, но если в скобках писать максимальное время сна, то всё работает нормально.
Код:
void sleepNow() {
  Serial.println("going to light sleep...");
  wifi_station_disconnect();
  wifi_set_opmode(NULL_MODE);
  wifi_fpm_set_sleep_type(LIGHT_SLEEP_T); //light sleep mode
  gpio_pin_wakeup_enable(GPIO_ID_PIN(2), GPIO_PIN_INTR_LOLEVEL); //set the interrupt to look for HIGH pulses on Pin 0 (the PIR).
  wifi_fpm_open();
  delay(100);
  wifi_fpm_set_wakeup_cb(wakeupFromMotion); //wakeup callback
  wifi_fpm_do_sleep(60000000);
  delay(100);
}
void wakeupFromMotion(void) {
  wifi_fpm_close;
  wifi_set_opmode(STATION_MODE);
  wifi_station_connect();
}
2)После того, как esp вышла из сна, нужно отправить данные на сервер. Но esp не подключается к wifi.
Функция для отправки данный на сервер:
Код:
WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");
    return;
  }

  // Создаём url


  Serial.print("Requesting URL: ");
  Serial.println(url);

  // Отправляем данные на сервер

                 unsigned long timeout = millis();
  while (client.available() == 0) {
    if (millis() - timeout > 5000) {
      Serial.println(">>> Client Timeout !");
      client.stop();
      return;
    }
  }

  // Read all the lines of the reply from server and print them to Serial
  while (client.available()) {
    String line = client.readStringUntil('\r');
    Serial.print(line);
  }

  Serial.println();
  Serial.println("closing connection");
В Serial пишет connection failed.
Подскажите, пожалуйста, как можно решить данные проблемы. Использую Esp12f
 

nikolz

Well-known member
Здравствуйте. Пересмотрел много тем на форуме, но никак не могу разобраться с light sleep. Есть несколько проблем:
1) Прерывание по кнопке срабатывает отлично. А вот с прерыванием по таймеру есть проблемы. Esp просто выходит из сна циклически, но если в скобках писать максимальное время сна, то всё работает нормально.
Подскажите, пожалуйста, как можно решить данные проблемы. Использую Esp12f
полагаю надо ждать соединения и после установления передавать.
 

alexsvk

New member
озвучьте проблему , чтобы не искать где про нее.
Во время light sleep пробуждение по кнопке работает отлично. Если включить прерывание по времени, т.е. изменить 0xFFFFFFFF на любое другое число, возникает такое ощущение, что esp все равно на то число в скобках, и она начинает циклически выполнять loop(т.е. засыпает, но сразу пробуждается)
 

alexsvk

New member
пример покажите и скажите какое время вы установили и через какое время просыпается
Код:
void sleepNow() {
  Serial.println("going to light sleep...");
  wifi_station_disconnect();
  wifi_set_opmode(NULL_MODE);
  wifi_fpm_set_sleep_type(LIGHT_SLEEP_T); //light sleep mode
  gpio_pin_wakeup_enable(GPIO_ID_PIN(2), GPIO_PIN_INTR_LOLEVEL); //set the interrupt to look for HIGH pulses on Pin 0 (the PIR).
  wifi_fpm_open();
  delay(100);
  wifi_fpm_set_wakeup_cb(wakeupFromMotion); //wakeup callback
  wifi_fpm_do_sleep(0xFFFFFFFF);
  delay(100);
}

void wakeupFromMotion(void) {
  wifi_fpm_close;
  wifi_set_opmode(STATION_MODE);
  wifi_station_connect();
}
Вместо 0xFFFFFFFF пытался ставить: 60*1000*1000, 0x1C9C380, 30000000
Просыпается моментально, не реагирует на время
 

alexsvk

New member
Я пишу на Си . У меня все работает.
-------------------------
попробуйте так:
-------------------------------
Код:
void sleepNow() {
  wifi_station_disconnect();
  wifi_set_opmode(NULL_MODE);
  wifi_fpm_set_sleep_type(LIGHT_SLEEP_T);
  wifi_fpm_open();
  wifi_fpm_set_wakeup_cb(wakeupFromMotion);
  wifi_fpm_do_sleep(10000*1000);
}
void wakeupFromMotion(void) {
wifi_fpm_do_wakeup();
  wifi_fpm_close();
  wifi_set_opmode(STATION_MODE);
  wifi_station_connect();
}
К сожалению, не помогло
 

alexsvk

New member
попробуйте собрать только этот пример без остального кода который у вас в скетче.
Так тоже не работает.
Вот мой код:
Код:
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
extern "C" {
#include "gpio.h"
}
extern "C" {
#include "user_interface.h"
}
void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  sleepNow();
Serial.println("Hello");
}

void sleepNow() {
  Serial.println("going to light sleep...");
  wifi_station_disconnect();
  wifi_set_opmode(NULL_MODE);
  wifi_fpm_set_sleep_type(LIGHT_SLEEP_T); //light sleep mode
  gpio_pin_wakeup_enable(GPIO_ID_PIN(2), GPIO_PIN_INTR_LOLEVEL); //set the interrupt to look for HIGH pulses on Pin 0 (the PIR).
  wifi_fpm_open();
  delay(100);
  wifi_fpm_set_wakeup_cb(wakeupFromMotion); //wakeup callback
  wifi_fpm_do_sleep(10000*1000);
  delay(100);
}

void wakeupFromMotion(void) {
  wifi_fpm_do_wakeup();
  wifi_fpm_close;
  wifi_set_opmode(STATION_MODE);
  wifi_station_connect();
}
 

alexsvk

New member
nikolz,
попробуйте вот такой тест :
  1. #include <ESP8266WiFi.h>
  2. #include <ESP8266WebServer.h>
  3. extern "C" {
  4. #include "gpio.h"
  5. }
  6. extern "C" {
  7. #include "user_interface.h"
  8. }
  9. void setup() {
  10. Serial.begin(9600);
  11. wifi_fpm_set_sleep_type(LIGHT_SLEEP_T);
  12. wifi_fpm_open();
  13. }
  14. void loop() {
  15. // put your main code here, to run repeatedly:
  16. Serial.println("Hello");
  17. sleepNow();
  18. }
  19. void sleepNow() {
  20. Serial.println("going to light sleep...");
  21. wifi_fpm_set_wakeup_cb(wakeupFromMotion); //wakeup callback
  22. wifi_fpm_do_sleep(10000*1000);
  23. }
  24. void wakeupFromMotion(void) {
  25. Serial.println("wakeup");
  26. sleepNow();
  27. }
Нет, этот код тоже не хочет работать. А вы не знаете, можно ли реализовать выход из deep sleep и по кнопке, и по времени?
ESP надо подключить к роутеру в режиме STA
У вас подключается ? Есть сообщение о соединении?
Предположу, что в ардуино этот режим не будет работать так как есть цикл loop.
После выхода из сна подключается, но не всегда. Иногда требуется очень много времени для подключения.
 

Сергей_Ф

Moderator
Команда форума
@alexsvk по времени и по ресет. У меня работает deep sleep без проблем. В коде проверяем по какому событию пробудились. Как уже говорил полгода на двух АА батарейках живет уже.
 

nikolz

Well-known member
nikolz,

Нет, этот код тоже не хочет работать. А вы не знаете, можно ли реализовать выход из deep sleep и по кнопке, и по времени?

После выхода из сна подключается, но не всегда. Иногда требуется очень много времени для подключения.
я исправил тест
попробуйте должен работать
  1. #include <ESP8266WiFi.h>
  2. #include <ESP8266WebServer.h>
  3. extern "C" {
  4. #include "gpio.h"
  5. }
  6. extern "C" {
  7. #include "user_interface.h"
  8. }
  9. void setup() {
  10. Serial.begin(9600);
  11. wifi_fpm_set_sleep_type(LIGHT_SLEEP_T);
  12. wifi_fpm_open();
  13. sleepNow();
  14. }
  15. void loop() {
  16. // put your main code here, to run repeatedly:
  17. Serial.println("Hello");
  18. }
  19. void sleepNow() {
  20. Serial.println("going to light sleep...");
  21. wifi_fpm_set_wakeup_cb(wakeupFromMotion); //wakeup callback
  22. wifi_fpm_do_sleep(10000*1000);
  23. }
  24. void wakeupFromMotion(void) {
  25. Serial.println("wakeup");
  26. sleepNow();
  27. }
=================================
deep-sleep это режим пробуждения по времени.
пробуждение делается по сигналу таймера RTC ESP и этот сигнал через GPIO16 поступает на pin RST
Для чего их соединяем.
вот пример кода:
void setup() {
Serial.begin(115200);
// Deep sleep режим на 30 секунд . Для просыпания соедините GPIO 16 с RESET pin
Serial.println("I'm awake, but I'm going into deep sleep mode for 30 seconds");
ESP.deepSleep(30e6);
// Deep sleep mode до тех пор пока на RESET pin не подадите LOW signal (например внешней кнопкой)
//Serial.println("I'm awake, but I'm going into deep sleep mode until RESET pin is connected to a LOW signal");
//ESP.deepSleep(0);
}
-----------------------
Пример вечного сна закомментирован.
============================
Для реализации просыпания по времени и по кнопке надо соединить GPIO16 c RST и подключить кнопку тоже к RST.
Чтобы определить от чего произошел рестарт можно кнопку соединить с каким либо пином.
и при рестарте проверять пины на предмет нажатия кнопки.
---------------------------------
Однако нельзя просто так соединить кнопку и с reset и с пином.
Надо сделать следующую схему
GPIO16 соединит с RST через диод шоттки (анод к RST)
кнопку соединить с пином который будете читать на пин поставить подтяжку к Vcc
а с RST кнопку соединить через RC цепочку R и C параллельно. R примерно ком 100 а С примерно 0.1 мкф.
------------------------
Далее исполняете пример кода для заданного времени
В результате ESP будет рестартовать через указанное время либо по нажатию кнопки
В функции setup вы читаете пин с кнопкой и решаете нажата она или нет.
 
Последнее редактирование:

Сергей_Ф

Moderator
Команда форума
Чтобы определить от чего произошел рестарт можно кнопку соединить с каким либо пином.
если нужна одна кнопка, то незачем так усложнять. Можно просто подключить кнопку от ресет на ноль и посмотрет статус загрузки.
Код:
#define REASON_RESET 5
extern "C" {
  #include "user_interface.h"
}
struct rst_info *rstInfo = system_get_rst_info();
uint32_t reason = rstInfo->reason;
if ( reason == REASON_RESET ){
...
} else {
...
}
При пробуждении по таймеру он не равен 5, по ресет - равен.
Единственное неудобство - кнопка срабатывает по отпусканию, но если очень мешает то можно добавить конденсатор в цепь сброса.
 
Последнее редактирование:

nikolz

Well-known member
если нужна одна кнопка, то незачем так усложнять. Можно просто подключить кнопку от ресет на ноль и посмотрет статус загрузки.
Код:
#define REASON_RESET 5
extern "C" {
  #include "user_interface.h"
}
struct rst_info *rstInfo = system_get_rst_info();
uint32_t reason = rstInfo->reason;
if ( reason == REASON_RESET ){
...
} else {
...
}
При пробуждении по таймеру он не равен 5, по ресет - равен.
Единственное неудобство - кнопка срабатывает по отпусканию, но если очень мешает то можно добавить конденсатор в цепь сброса.
Не соглашусь с Вами.
В моем варианте можно сделать кнопку ресет и любой другой сухой контакт и даже несколько контактов или кнопок
В вашем вы просто используете кнопку ресет.
Это две большие разницы.
 

alexsvk

New member
я исправил тест
попробуйте должен работать
  1. #include <ESP8266WiFi.h>
  2. #include <ESP8266WebServer.h>
  3. extern "C" {
  4. #include "gpio.h"
  5. }
  6. extern "C" {
  7. #include "user_interface.h"
  8. }
  9. void setup() {
  10. Serial.begin(9600);
  11. wifi_fpm_set_sleep_type(LIGHT_SLEEP_T);
  12. wifi_fpm_open();
  13. sleepNow();
  14. }
  15. void loop() {
  16. // put your main code here, to run repeatedly:
  17. Serial.println("Hello");
  18. }
  19. void sleepNow() {
  20. Serial.println("going to light sleep...");
  21. wifi_fpm_set_wakeup_cb(wakeupFromMotion); //wakeup callback
  22. wifi_fpm_do_sleep(10000*1000);
  23. }
  24. void wakeupFromMotion(void) {
  25. Serial.println("wakeup");
  26. sleepNow();
  27. }
Опять не хочет работать. В начале просто моментально проскакивает сон и начинает писать Hello. По поводу Deep Sleep, попробую позже собрать схему. Спасибо за подробное описание.
 

Сергей_Ф

Moderator
Команда форума
@nikolz я же не спорю. Если надо несколько кнопок, то надо делать как у вас. Кстати ещё один недостаток простой схемы/кода - срабатывание при подаче питания. Если недопустимо - то...
 

nikolz

Well-known member
@nikolz я же не спорю. Если надо несколько кнопок, то надо делать как у вас. Кстати ещё один недостаток простой схемы/кода - срабатывание при подаче питания. Если недопустимо - то...
я собственно то же не спорю. просто у меня всегда стоит кнопка RST
а проверку рестарта я делаю для определения необходимости осуществлять начальную инициализацию.
Если использовать Вашу логику то инициализация при включении питания исключается
а это существенно усложняет либо замедляет просыпание устройства
 

nikolz

Well-known member
так работает ESP в режиме Light sleep.
на картинке ток потребления. сон 100 мс.
upload_2018-10-31_9-10-42.png
 

alexsvk

New member
если нужна одна кнопка, то незачем так усложнять. Можно просто подключить кнопку от ресет на ноль и посмотрет статус загрузки.
Код:
#define REASON_RESET 5
extern "C" {
  #include "user_interface.h"
}
struct rst_info *rstInfo = system_get_rst_info();
uint32_t reason = rstInfo->reason;
if ( reason == REASON_RESET ){
...
} else {
...
}
При пробуждении по таймеру он не равен 5, по ресет - равен.
Единственное неудобство - кнопка срабатывает по отпусканию, но если очень мешает то можно добавить конденсатор в цепь сброса.
Код работает некорректно. Либо я что-то не так делаю, либо где-то проблема в коде. Код неправильно выводит причину рестарта
 

Сергей_Ф

Moderator
Команда форума
@alexsvk ну тут же не весь код. Что именно у вас выводится?
возможно я немного ошибся с кодом причины перезагрузки - писал по памяти
вот из документации:
Код:
REANSON_DEFAULT_RST = 0, // normal startup by power on
REANSON_WDT_RST = 1, // hardware watch dog reset
REANSON_EXCEPTION_RST = 2, // exception reset, GPIO status won’t change
REANSON_SOFT_WDT_RST = 3, // software watch dog reset, GPIO status won’t change
REANSON_SOFT_RESTART = 4, // software restart ,system_restart , GPIO status won’t change
REANSON_DEEP_SLEEP_AWAKE = 5, // wake up from deep-sleep
Ну, конечно, 5 - это просыпание. Сорри.
 
Сверху Снизу