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

Нужна помощь Light Sleep Mode - стал срабатывать wdt ...

Slacky

Member
и еще
не понятно к чему вы коннектитесь.
У вас нет никаких настроек.
Надо проверить есть ли они по умолчанию или задать их явно.
Ну так это же просто пример. Конектится к моему роутеру, настройки берутся автоматически из флеш, так как ранее были сконфигурированы в другом варианте программы ...
 

Slacky

Member
А WDT не знает что это просто пример. Он думает что Вы серьезно что-то делаете.
Уберите тогда коннект вообще.
Так в реальной проге, с эвентом, с конфигом и прочими настройками, засыпание ведет себя точно также - сброс по wdt ...

Ну и чисто из наблюдений - срабатывание wdt никак не связано в WiFi. Засыпаем нормально, если пины не замыкали, если же позамыкали, то wdt при попытке заснуть ...
 

nikolz

Well-known member
Так в реальной проге, с эвентом, с конфигом и прочими настройками, засыпание ведет себя точно также - сброс по wdt ...

Ну и чисто из наблюдений - срабатывание wdt никак не связано в WiFi. Засыпаем нормально, если пины не замыкали, если же позамыкали, то wdt при попытке заснуть ...
Предположу, что когда Вы позамыкали то у Вас установился статус прерывания так как у Вас нет в проге запрета
Когда входите в сон то сразу срабатывает прерывание так как статус установлен потом вы его не сбрасываете.
Короче что при этом происходит и что и где зависает сложно сказать .
Поэтому надо прерывание в начале запретить и разрешить лишь перед уходом в сон
при выходе снова запретить. тогда жмите не жмите будет один...
 

nikolz

Well-known member
Так в реальной проге, с эвентом, с конфигом и прочими настройками, засыпание ведет себя точно также - сброс по wdt ...
Ну и чисто из наблюдений - срабатывание wdt никак не связано в WiFi. Засыпаем нормально, если пины не замыкали, если же позамыкали, то wdt при попытке заснуть ...
Собрал тест для одной кнопки с переворотом сигнала для прерывания.
Выяснил следующее.
Если не включать NULL_MODE, т е оставить режим станции, то WDT не дает длительно находится в режиме сна.
Код теста:
Код:
#include <ets_sys.h>
#include <osapi.h>
#include <user_interface.h>
#include <os_type.h>
#include <gpio.h>
#include "os_type.h"
#include "stdlib.h"
#define pinN 4 
uint8 Level;
void ICACHE_FLASH_ATTR wakeupLS(void) {
    os_printf("%u\r\n",Level);
    if (Level== GPIO_PIN_INTR_LOLEVEL){Level= GPIO_PIN_INTR_HILEVEL;    }
    else  {        Level= GPIO_PIN_INTR_LOLEVEL;    }
    gpio_pin_wakeup_enable(GPIO_ID_PIN(pinN),Level);
    wifi_fpm_do_sleep(0xFFFFFFF);
}

void ICACHE_FLASH_ATTR user_init(void)
{
    Level=GPIO_PIN_INTR_LOLEVEL;
    if (wifi_get_opmode()!=NULL_MODE) wifi_set_opmode(NULL_MODE);
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO4_U, FUNC_GPIO4);GPIO_DIS_OUTPUT(4);
    wifi_fpm_set_sleep_type(LIGHT_SLEEP_T); 
    wifi_fpm_open();
    wifi_fpm_set_wakeup_cb(wakeupLS); //wakeup callback
    wakeupLS();
}

uint32 ICACHE_FLASH_ATTR user_rf_cal_sector_set(void)
{
    enum flash_size_map size_map = system_get_flash_size_map();
    uint32 rf_cal_sec = 0;
    switch (size_map) {
        case FLASH_SIZE_4M_MAP_256_256:    rf_cal_sec = 128 - 8;     break;
        case FLASH_SIZE_8M_MAP_512_512:    rf_cal_sec = 256 - 5;     break;
        case FLASH_SIZE_16M_MAP_512_512:
        case FLASH_SIZE_16M_MAP_1024_1024:
            rf_cal_sec = 512 - 5;        break;
        case FLASH_SIZE_32M_MAP_512_512:
        case FLASH_SIZE_32M_MAP_1024_1024:
            rf_cal_sec = 1024 - 5;     break;
        default:     rf_cal_sec = 0;    break;
    }
    return rf_cal_sec;
}

void ICACHE_FLASH_ATTR user_rf_pre_init(void)
{}
 

Slacky

Member
@nikolz нашел я что лажает ...

Обратил внимание, что когда все прекрасно засыпает, то в мониторе можно увидеть
Код:
mode : null
Добавление вот такой строчки в функцию засыпания дало интересный результат

Код:
os_printf("wifi mode: %d\n", wifi_get_opmode());
Вывод в монитор, когда все нормально

Код:
Power low. Light sleep now ...
state: 5 -> 0 (0)
rm 0
del if0
usl
mode : null
force slp enable,type: 1
wifi mode: 0
И когда срабатывает wdt

Код:
Power low. Light sleep now ...
force slp enable,type: 1
wifi mode: 1
pm close 7
fpm open,type:1 0
fpm 758

ets Jan  8 2013,rst cause:2, boot mode:(1,7)


ets Jan  8 2013,rst cause:4, boot mode:(1,7)

wdt reset
Осталось понять, как это обойти ...
 

nikolz

Well-known member
@nikolz нашел я что лажает ...

Обратил внимание, что когда все прекрасно засыпает, то в мониторе можно увидеть
Код:
mode : null
Добавление вот такой строчки в функцию засыпания дало интересный результат

Код:
os_printf("wifi mode: %d\n", wifi_get_opmode());
Вывод в монитор, когда все нормально

Код:
Power low. Light sleep now ...
state: 5 -> 0 (0)
rm 0
del if0
usl
mode : null
force slp enable,type: 1
wifi mode: 0
И когда срабатывает wdt

Код:
Power low. Light sleep now ...
force slp enable,type: 1
wifi mode: 1
pm close 7
fpm open,type:1 0
fpm 758

ets Jan  8 2013,rst cause:2, boot mode:(1,7)


ets Jan  8 2013,rst cause:4, boot mode:(1,7)

wdt reset
Осталось понять, как это обойти ...
Поставьте после этого принта задержку 200 мкс.
 

Slacky

Member
Поставьте после этого принта задержку 200 мкс.
Это первое, что я сделал. Не помогает.

Даже вот такую задержку сделал, но там все тупо останавливается на этом цикле ...
Код:
    while(wifi_get_opmode() != NULL_MODE) {
        system_soft_wdt_feed();
        os_delay_us(50000);
    }
 

nikolz

Well-known member
Это первое, что я сделал. Не помогает.

Даже вот такую задержку сделал, но там все тупо останавливается на этом цикле ...
Код:
    while(wifi_get_opmode() != NULL_MODE) {
        system_soft_wdt_feed();
        os_delay_us(50000);
    }
Возможно я не понял Вас.
Я полагал что принт вы поставили перед засыпанием и принт не успевает выполниться
А вот этот цикл я совсем не понимаю. Тем более, что циклы часто и являются источником срабатывания WDT
 

Slacky

Member
Возможно я не понял Вас.
Я полагал что принт вы поставили перед засыпанием и принт не успевает выполниться
А вот этот цикл я совсем не понимаю. Тем более, что циклы часто и являются источником срабатывания WDT
Все просто.

Код:
    bool ret = wifi_station_disconnect();
    os_printf("wifi_disconnect return: %d\n", ret);
    ret = wifi_set_opmode(NULL_MODE);
    os_printf("wifi_mode return: %d\n", ret);
    wifi_fpm_set_sleep_type(LIGHT_SLEEP_T); //light sleep mode
    while(wifi_get_opmode() != NULL_MODE) {
        wifi_set_opmode(NULL_MODE);
        system_soft_wdt_feed();
        os_delay_us(50000);
    }
    os_printf("wifi mode: %d\n", wifi_get_opmode());
Смысл был такой - если wifi_get_opmode() возвращает не 0, значит по какой-то причине не сработала функция wifi_set_opmode(NULL_MODE). Ну так подождем, пока wifi_get_opmode() не вернет 0 и тогда продолжим процедуру засыпания.

Только дело в том, что wifi_get_opmode() не возвращает 0. Т.е. wifi_set_opmode(NULL_MODE) по какой-то причине не отрабатывает вообще ...
 

nikolz

Well-known member
Все просто.

Код:
    bool ret = wifi_station_disconnect();
    os_printf("wifi_disconnect return: %d\n", ret);
    ret = wifi_set_opmode(NULL_MODE);
    os_printf("wifi_mode return: %d\n", ret);
    wifi_fpm_set_sleep_type(LIGHT_SLEEP_T); //light sleep mode
    while(wifi_get_opmode() != NULL_MODE) {
        wifi_set_opmode(NULL_MODE);
        system_soft_wdt_feed();
        os_delay_us(50000);
    }
    os_printf("wifi mode: %d\n", wifi_get_opmode());
Смысл был такой - если wifi_get_opmode() возвращает не 0, значит по какой-то причине не сработала функция wifi_set_opmode(NULL_MODE). Ну так подождем, пока wifi_get_opmode() не вернет 0 и тогда продолжим процедуру засыпания.

Только дело в том, что wifi_get_opmode() не возвращает 0. Т.е. wifi_set_opmode(NULL_MODE) по какой-то причине не отрабатывает вообще ...
1) эту функцию wifi_fpm_set_sleep_type(LIGHT_SLEEP_T); //light sleep mode
можно определить один раз в user_init
---------------------
2) А если так:
------------------------
bool ret = wifi_station_disconnect();
os_printf("wifi_disconnect return: %d\n", ret);
if (wifi_get_opmode() != NULL_MODE ){
ret=wifi_set_opmode(NULL_MODE);
os_printf("wifi_mode return: %d\n", ret);
}
 

Slacky

Member
1) эту функцию wifi_fpm_set_sleep_type(LIGHT_SLEEP_T); //light sleep mode
можно определить один раз в user_init
Думаю это не совсем так, так как в документации есть пример и LIGHT_SLEEP_T устанавливается именно в пользовательской функции засыпания ...
---------------------
2) А если так:
------------------------
bool ret = wifi_station_disconnect();
os_printf("wifi_disconnect return: %d\n", ret);
if (wifi_get_opmode() != NULL_MODE ){
ret=wifi_set_opmode(NULL_MODE);
os_printf("wifi_mode return: %d\n", ret);
}
Вот такой код работает. Если wifi_get_opmode() не вернет NULL_MODE, то мы просто выходим из этой функции. А таймер, следящий за внешним напряжением повторно возвращает программу в эту функцию. Со второго раза NULL_MODE включается всегда.

Код:
void ICACHE_FLASH_ATTR sleepOnNow() {
    wifi_station_disconnect();
    wifi_set_opmode(NULL_MODE);
    os_delay_us(5000);
    if (wifi_get_opmode() != NULL_MODE) return;
    wifi_fpm_set_sleep_type(LIGHT_SLEEP_T); //light sleep mode
    gpio_pin_wakeup_enable(GPIO_ID_PIN(pin_num[HOT_PIN]),
            GPIO_PIN_INTR_LOLEVEL); /* Set the interrupt to look for LOW pulses on HOT_PIN  */
    gpio_pin_wakeup_enable(GPIO_ID_PIN(pin_num[COLD_PIN]),
            GPIO_PIN_INTR_LOLEVEL); /* Set the interrupt to look for LOW pulses on COLD_PIN */
    wifi_fpm_open();
    wifi_fpm_set_wakeup_cb(wakeupFromMotion); //wakeup callback
    wifi_fpm_do_sleep(0xFFFFFFF);
}
 

nikolz

Well-known member
Думаю это не совсем так, так как в документации есть пример и LIGHT_SLEEP_T устанавливается именно в пользовательской функции засыпания ...


Вот такой код работает. Если wifi_get_opmode() не вернет NULL_MODE, то мы просто выходим из этой функции. А таймер, следящий за внешним напряжением повторно возвращает программу в эту функцию. Со второго раза NULL_MODE включается всегда.

Код:
void ICACHE_FLASH_ATTR sleepOnNow() {
    wifi_station_disconnect();
    wifi_set_opmode(NULL_MODE);
    os_delay_us(5000);
    if (wifi_get_opmode() != NULL_MODE) return;
    wifi_fpm_set_sleep_type(LIGHT_SLEEP_T); //light sleep mode
    gpio_pin_wakeup_enable(GPIO_ID_PIN(pin_num[HOT_PIN]),
            GPIO_PIN_INTR_LOLEVEL); /* Set the interrupt to look for LOW pulses on HOT_PIN  */
    gpio_pin_wakeup_enable(GPIO_ID_PIN(pin_num[COLD_PIN]),
            GPIO_PIN_INTR_LOLEVEL); /* Set the interrupt to look for LOW pulses on COLD_PIN */
    wifi_fpm_open();
    wifi_fpm_set_wakeup_cb(wakeupFromMotion); //wakeup callback
    wifi_fpm_do_sleep(0xFFFFFFF);
}
Вы наберите мой код и проверьте.
Если внимательно посмотрите на мой тест то там увидите много интересного.
все что там я использую и говорил Вам я многократно проверял с измерением времени и потребляемого тока.
поэтому я не просто "так думаю", но проверил и убежден, что так работает.
 

nikolz

Well-known member
еще хочу обратить Ваше внимание что когда Вы используете режимы sleep надо либо проверять UART на пусто,
либо давать ему время на вывод иначе сообщение не успеет вывести на экран
 

nikolz

Well-known member
и еще если часто будете изменять режим то протрете дырку во флеш.
Поэтому либо делайте это с if, либо используйте current
 

Slacky

Member
Вы наберите мой код и проверьте.
Если внимательно посмотрите на мой тест то там увидите много интересного.
все что там я использую и говорил Вам я многократно проверял с измерением времени и потребляемого тока.
поэтому я не просто "так думаю", но проверил и убежден, что так работает.
Вот отсюда? https://esp8266.ru/forum/threads/light-sleep-mode-stal-srabatyvat-wdt.3480/page-2#post-52761
Набирал. Если честно, что-то у меня не пошло ...
 

Slacky

Member
еще хочу обратить Ваше внимание что когда Вы используете режимы sleep надо либо проверять UART на пусто,
либо давать ему время на вывод иначе сообщение не успеет вывести на экран
Это понятно, но по большому счету не важно, ну если только для отладки ...
 

Slacky

Member
и еще если часто будете изменять режим то протрете дырку во флеш.
Поэтому либо делайте это с if, либо используйте current
Это я тоже знаю. На current и default все и заточено, а это ж просто пример для проверки ...

Ну и вообще, большое спасибо :)
 

nikolz

Well-known member
В Эклипсе. Ну не совсем не пошло, я не правильно выразился. Я не понял смысла. Ну повыводила она у меня 4 и 5. Ну и все ...
Смысл в данном тесте - тестирование данного режима и отсутствие срабатывание WDT при любом времени сна.
Кроме того, если Вам нужен еще какой-то смысл, то вставляете функцию вашего смысла в {} либо при нуле либо при 1.
Т е в данном варианте не надо держать процессор активным и ждать когда вы отпустите кнопку. Не надо никаких таймеров для этого запускать.
Вы можете сколь угодно долго держать кнопку нажатой а процессор будет спать пока не отпустите и наоборот.
 
Сверху Снизу