Вопрос Auto Light Sleep Mode - модуль отказывается входить в режим

warl0rd

New member
Здравствуйте, уважаемые форумчане!

Модуль - esp-03. NONOS-SDK взят из официального репозитория espressif/ESP8266_NONOS_SDK, с последними коммитами.

В прошивке реализовано установление режима энергосбережения LIGHT_SLEEP_T и последующее подключение к точке доступа. Модуль успешно подключается и его потребление начинает варьироваться, чаще всего видно число 60мА. Дальше я из обычного виндового терминала делаю ping ip_addr и в результате отправки этих 4 ICMP запросов (ответы приходят) энергосбережение модуля рушится и потребление замирает на отметке в 61-62мА. Если выключить точку доступа и включить, то модуль точку теряет, находит, подключается, и режим энергосбережения восстанавливается.

После экспериментов выяснилось, что для порчи энергосбережения нужно отправить минимум 4 пакета с периодом от 0.5 до 0.8 секунды.​

Есть предположение, что виноват может быть lwip стек, который придерживает какой-нибудь таймер, буду пробовать собрать lwip из исходников SDK и пришвартовать их к сборке.

файл user_init.c
Код:
#define SPI_FLASH_SIZE_MAP              FLASH_SIZE_8M_MAP_512_512


#define SYSPART_OTA_SIZE                0x6A000
#define SYSPART_OTA_2_ADDR              0x81000
#define SYSPART_RF_CAL_ADDR             0xFB000
#define SYSPART_PHY_DATA_ADDR           0xFC000
#define SYSPART_SYSTEM_PARAMETER_ADDR   0xFD000

static const partition_item_t st_ptable[] =
{
  { SYSTEM_PARTITION_RF_CAL, SYSPART_RF_CAL_ADDR, 0x1000},
  { SYSTEM_PARTITION_PHY_DATA, SYSPART_PHY_DATA_ADDR, 0x1000},
  { SYSTEM_PARTITION_SYSTEM_PARAMETER, SYSPART_SYSTEM_PARAMETER_ADDR, 0x3000},
};

//***********************************************
ICACHE_FLASH_ATTR
static void init_done(void)
{
  struct station_config sta_conf;

  wifi_set_opmode_current(STATION_MODE);

  wifi_set_sleep_type(LIGHT_SLEEP_T);

  sta_conf.bssid_set = 0;
  os_memcpy(&sta_conf.ssid, AP_SSID, 32);
  os_memcpy(&sta_conf.password, AP_PASSWD, 64);
  wifi_station_set_config_current(&sta_conf);

  wifi_station_disconnect();
  wifi_station_connect();
}

//***********************************************
ICACHE_FLASH_ATTR
void user_pre_init(void)
{
  if (system_partition_table_regist(st_ptable, ARRAY_SIZE(st_ptable), SPI_FLASH_SIZE_MAP) == 0)
  {
    os_printf("system_partition_table_regist fail\r\n");
    while(1);
  }
}

//***********************************************
ICACHE_FLASH_ATTR
void user_init(void)
{
  system_set_os_print(0);

  system_init_done_cb(init_done);
}
 

warl0rd

New member
nikolz, да, это весь код. Я максимально его упростил, оставил только то, что относится к делу.
>> А где колбек wifi?
Если в нём ничего полезного не делается, то он не нужен.
 

warl0rd

New member
nikolz, я готов добавить куски кода, которые смогут изменить ход событий. Что мне следует добавить в первую очередь?? колбек wifi??
Код:
//***********************************************
ICACHE_FLASH_ATTR
static void wifi_event(System_Event_t *ev)
{
}

ICACHE_FLASH_ATTR
static void init_done(void)
{
  ...
  wifi_set_event_handler_cb(wifi_event);
  ...
}
но что в нём делать, не ясно...
 

warl0rd

New member
@nikolz, я добавлю колбэк wifi, с печатью всех событий в него поступающих. И добавлю лог самого SDK, для большего понимания происходящего. Это у меня всё уже было, до того, как я оставил минимум кода.

>>кроме того я не увидел у вас колбек отправки и приема
Отправки и приёма чего?? Вся суть программы заключается в подключении к заданной точке доступа. Больше от программы ничего не требуется. Но так как в SDK вкомпилен стек LWIP с включенным ICMP, то бонусом этот стек отвечает на пинги.

>>Режим Ligh включается не сразу а лишь если процессор простаивает возможно у вас что-то крутится на процессоре
Да, по логу SDK видно, что режим энергосбережения включается: "pm open,type:1 0"
и потребление начинает скакать. Я для того и выскреб из своего кода всё, что можно, чтобы было сложно сказать, что в моём коде что-то крутится. Остаются задачи SDK и LWIP.
 
Последнее редактирование:

warl0rd

New member
@nikolz,
Лог модуля, последняя строчка - включение режима энергосбережения, после этой строчки модуль больше ничего не сообщает.

Код:
00:00:00.069 OS: mode : null
00:00:00.070 OS: mode : sta(18:fe:34:84:7a:d5)
00:00:00.070 OS: add if0
00:00:00.071 OS: sleep enable,type: 1
00:00:00.071 wifi_event OPMODE_CHANGED
00:00:01.589 wifi_event STAMODE_AUTHMODE_CHANGE
00:00:02.910 OS: scandone
00:00:03.794 OS: state: 0 -> 2 (b0)
00:00:03.799 OS: state: 2 -> 3 (0)
00:00:03.803 OS: state: 3 -> 5 (10)
00:00:03.803 OS: add 0
00:00:03.803 OS: aid 1
00:00:03.803 OS: cnt
00:00:03.817 OS: connected with ap_001, channel 11
00:00:03.817 OS: dhcp client start...
00:00:03.818 wifi_event STAMODE_CONNECTED
00:00:06.795 OS: ip:172.16.1.12,mask:255.240.0.0,gw:172.16.0.1
00:00:06.796 wifi_event STAMODE_GOT_IP
00:00:13.803 OS: pm open,type:1 0
>>если вы посылаете пинг то чем вы его принимаете?
Посылаю пинг с помощью терминала винды. Принимает его LWIP стек модуля, так как там включена поддержка ICMP, то стек отвечает на запрос и виндовый терминал видит ответ.
>>я пинг не делал, но возможно стоит поставить колбек приема и посмотреть реакцию
Изначально у меня был колбэк приёма, но он исправно работал - как часы, со включенным энергосбережением или без него - пинги принимались кодом и отправлялся ответ.

>>Вы уверены что ESP может обрабатывать пинги?
Да, уверенность есть. Больше отвечать некому. Точка доступа и её трафик находятся под контролем.

>>В результате я отказался от этого режима так как нет особого смысла в нем
Я разрабатываю телефон с поддержкой WiFi на этом чипе, поэтому режим энергосбережения для меня так важен.
 

nikolz

Well-known member
@nikolz,
Лог модуля, последняя строчка - включение режима энергосбережения, после этой строчки модуль больше ничего не сообщает.

Код:
00:00:00.069 OS: mode : null
00:00:00.070 OS: mode : sta(18:fe:34:84:7a:d5)
00:00:00.070 OS: add if0
00:00:00.071 OS: sleep enable,type: 1
00:00:00.071 wifi_event OPMODE_CHANGED
00:00:01.589 wifi_event STAMODE_AUTHMODE_CHANGE
00:00:02.910 OS: scandone
00:00:03.794 OS: state: 0 -> 2 (b0)
00:00:03.799 OS: state: 2 -> 3 (0)
00:00:03.803 OS: state: 3 -> 5 (10)
00:00:03.803 OS: add 0
00:00:03.803 OS: aid 1
00:00:03.803 OS: cnt
00:00:03.817 OS: connected with ap_001, channel 11
00:00:03.817 OS: dhcp client start...
00:00:03.818 wifi_event STAMODE_CONNECTED
00:00:06.795 OS: ip:172.16.1.12,mask:255.240.0.0,gw:172.16.0.1
00:00:06.796 wifi_event STAMODE_GOT_IP
00:00:13.803 OS: pm open,type:1 0
>>если вы посылаете пинг то чем вы его принимаете?
Посылаю пинг с помощью терминала винды. Принимает его LWIP стек модуля, так как там включена поддержка ICMP, то стек отвечает на запрос и виндовый терминал видит ответ.
>>я пинг не делал, но возможно стоит поставить колбек приема и посмотреть реакцию
Изначально у меня был колбэк приёма, но он исправно работал - как часы, со включенным энергосбережением или без него - пинги принимались кодом и отправлялся ответ.

>>Вы уверены что ESP может обрабатывать пинги?
Да, уверенность есть. Больше отвечать некому. Точка доступа и её трафик находятся под контролем.

>>В результате я отказался от этого режима так как нет особого смысла в нем
Я разрабатываю телефон с поддержкой WiFi на этом чипе, поэтому режим энергосбережения для меня так важен.
Я использую deep-sleep для энергосбережения.
Я реализовывал Ligth без пингов. Зачем вам пинг?
А сколько времени уходит на ответ?
 

nikolz

Well-known member
фактически у вас перестает работать таймер по которому включается и выключается приемник. приемник всегда включен
Попробуйте все-таки сделать еще колбек по таймеру и поставьте в нем принт
 

warl0rd

New member
@nikolz, deep-sleep для моих целей не годится, пакет от Wifi сети может прийти в любой момент, нужно периодически слушать. Light - это самое то.

>>Я реализовывал Ligth без пингов. Зачем вам пинг?
Пинг - это просто удобный метод для тестирования. В винде ping ip_addr и пакеты пошли. Есть подозрение, что модуль раскорячится, если посылать череду любых IP пакетов, но я это не проверял. Когда я впервые увидел, что модуль более не входит в режим энергосбережения - это были именно пакеты пинга.

>>А сколько времени уходит на ответ?
Здесь прослеживается очень характерная картина, пока модуль в режиме энергосбережения - то задержка ответа достигает десятков мс, как только режим ломается - ответ единицы мс и меньше.
Код:
Первый заход:
Ответ от 172.16.1.12: число байт=32 время=5мс TTL=128
Ответ от 172.16.1.12: число байт=32 время=98мс TTL=128
Ответ от 172.16.1.12: число байт=32 время=24мс TTL=128
Ответ от 172.16.1.12: число байт=32 время=274мс TTL=128

Второй заход:
Ответ от 172.16.1.12: число байт=32 время=13мс TTL=128
Ответ от 172.16.1.12: число байт=32 время=248мс TTL=128
Ответ от 172.16.1.12: число байт=32 время=175мс TTL=128
Ответ от 172.16.1.12: число байт=32 время=1мс TTL=128

Третий заход
Ответ от 172.16.1.12: число байт=32 время=160мс TTL=128
Ответ от 172.16.1.12: число байт=32 время=89мс TTL=128
Ответ от 172.16.1.12: число байт=32 время=16мс TTL=128
Ответ от 172.16.1.12: число байт=32 время=22мс TTL=128
После этого режим энергосбережения ломается и далее ответы идут так:
Код:
Ответ от 172.16.1.12: число байт=32 время=6мс TTL=128
Ответ от 172.16.1.12: число байт=32 время=1мс TTL=128
Ответ от 172.16.1.12: число байт=32 время=1мс TTL=128
Ответ от 172.16.1.12: число байт=32 время=3мс TTL=128
 

warl0rd

New member
фактически у вас перестает работать таймер по которому включается и выключается приемник. приемник всегда включен
Попробуйте все-таки сделать еще колбек по таймеру и поставьте в нем принт
Да, это похоже на правду, подскажите, что это за таймер такой, насколько я понимаю - он в потрохах SDK, просто так к нему не подобраться??
 

nikolz

Well-known member
Да, это похоже на правду, подскажите, что это за таймер такой, насколько я понимаю - он в потрохах SDK, просто так к нему не подобраться??
я бы сам хотел его найти.
Попробуйте сначала сделать без пинга чтобы он входил и выходил из режима а потом добавьте пинг.
 

warl0rd

New member
@nikolz, так как это режим Light, то ядро останавливается, и для пробуждения нужна внешняя периферия, таковой в данном случае выступает RTC и его прерыванием ядро и будится. Поэтому, как такового программного таймера включения/выключения радиочасти может и не быть. Нужно ядру заснуть на бикон-интервал, взводится RTC и модуль спит. В моём случае - этого не происходит, видимо что-то мешает уснуть, но вот что, это большой вопрос.

>>Попробуйте сначала сделать без пинга чтобы он входил и выходил из режима а потом добавьте пинг.
Если пинги с ПК на модуль не посылать - то режим работает, я оставлял и наблюдал с пяток часов. Стоит только зарядить с ПК серию пингов - что-то щёлкает - и режим ломается, тоже оставлял на несколько часов, думал - выправится - не помогает. Только если выключить точку доступа и снова включить - то модуль перецепившись - начинает хранить энергию...
 

nikolz

Well-known member
@nikolz, так как это режим Light, то ядро останавливается, и для пробуждения нужна внешняя периферия, таковой в данном случае выступает RTC и его прерыванием ядро и будится. Поэтому, как такового программного таймера включения/выключения радиочасти может и не быть. Нужно ядру заснуть на бикон-интервал, взводится RTC и модуль спит. В моём случае - этого не происходит, видимо что-то мешает уснуть, но вот что, это большой вопрос.

>>Попробуйте сначала сделать без пинга чтобы он входил и выходил из режима а потом добавьте пинг.
Если пинги с ПК на модуль не посылать - то режим работает, я оставлял и наблюдал с пяток часов. Стоит только зарядить с ПК серию пингов - что-то щёлкает - и режим ломается, тоже оставлял на несколько часов, думал - выправится - не помогает. Только если выключить точку доступа и снова включить - то модуль перецепившись - начинает хранить энергию...
Полагаю, если бы было как вы написали то ток потребления упал бы до 20 мка как в deep-sleep, а ток значительно больше при сне
RTC работает в deep-sleep.
Но возможно что вы правы.
В любом случае у меня Ligh работал с активностью от пинов
Попробуйте без пинга
 

warl0rd

New member
@nikolz, на текущий момент я проверил, что отсылка c ПК модулю пачки UDP пакетов ломает режим, от пингов ушёл. Так же я собрал LWIP стек из исходников и прикрутил к проекту. Буду искать в LWIP. Но есть смутное подозрение, что косяк живёт в самом SDK...
 
@nikolz, на текущий момент я проверил, что отсылка c ПК модулю пачки UDP пакетов ломает режим, от пингов ушёл. Так же я собрал LWIP стек из исходников и прикрутил к проекту. Буду искать в LWIP. Но есть смутное подозрение, что косяк живёт в самом SDK...
А вы не пробовали с другими версиями SDK собирать? Скажем у меня проект, который работает с 2.2.1 с 3.0 просто не работает, программа перезагружается на каком-то этапе. Точнее, на этапе SSL подключения к MQTT брокеру.
 

nikolz

Well-known member
А вы не пробовали с другими версиями SDK собирать? Скажем у меня проект, который работает с 2.2.1 с 3.0 просто не работает, программа перезагружается на каком-то этапе. Точнее, на этапе SSL подключения к MQTT брокеру.
версия 2.2.1 отличается от 3.0 принципиально.
хотя на 3.0 смог запустить но пока вернулся на 2.2.1
 

nikolz

Well-known member
@nikolz, на текущий момент я проверил, что отсылка c ПК модулю пачки UDP пакетов ломает режим, от пингов ушёл. Так же я собрал LWIP стек из исходников и прикрутил к проекту. Буду искать в LWIP. Но есть смутное подозрение, что косяк живёт в самом SDK...
Относительно вашей идеи что используется RTC Если бы это было так, то не надо было бы городить огород в deep-sleep с reset.
 

warl0rd

New member
@Dmitry Orlov, спасибо за идею, я собрал:
2.0.0(656edbf) - поведение аналогичное 3.0.0, но ток, при котором режим энергопотребления рабочий - несравненно меньше, чем в 3.0.0 (я вижу числа 5, 19, 30 мА)
2.1.0(116b762) - вообще не отвечает после включения режима и строчки pm open,type:1 0 и практически не потребляет, видимо радиочасть не включается совсем.
2.2.0(f28eaf2) - поведение аналогичное 3.0.0
2.2.1(6ab97e9) - поведение аналогичное 3.0.0

Я теперь в винде запускаю ping -t ip_addr это бесконечный пинг, и как только вижу, что задержка нескольких ответов подряд стала меньше 1 мс, прерываю. Поломка гарантирована.
Код:
Ответ от 172.16.1.12: число байт=32 время=6мс TTL=128
Ответ от 172.16.1.12: число байт=32 время=236мс TTL=128
Ответ от 172.16.1.12: число байт=32 время=161мс TTL=128
Ответ от 172.16.1.12: число байт=32 время=2мс TTL=128
Ответ от 172.16.1.12: число байт=32 время=1мс TTL=128
Ответ от 172.16.1.12: число байт=32 время=1мс TTL=128
Ответ от 172.16.1.12: число байт=32 время=1мс TTL=128
@nikolz, предположу, что deep-sleep это тот режим, выйти из которого можно только подав внешний сигнал на ногу reset. Этот внешний сигнал подаётся блоком RTC, осталось сделать перемычку и вуаля! В то время, как из режима light-sleep можно выйти как по внешнему сигналу на ноге, так и по программному прерыванию от блока RTC. В даташите на NONOS_SDK есть функции аппаратного таймера и сказано, что для работы этого таймера нужно избегать пользования режимом light-sleep. Если аппаратный таймер в режиме light-sleep не работает, то на чём остаётся реализовывать программные таймеры, как не на блоке RTC??
 

nikolz

Well-known member
@Dmitry Orlov, спасибо за идею, я собрал:
2.0.0(656edbf) - поведение аналогичное 3.0.0, но ток, при котором режим энергопотребления рабочий - несравненно меньше, чем в 3.0.0 (я вижу числа 5, 19, 30 мА)
2.1.0(116b762) - вообще не отвечает после включения режима и строчки pm open,type:1 0 и практически не потребляет, видимо радиочасть не включается совсем.
2.2.0(f28eaf2) - поведение аналогичное 3.0.0
2.2.1(6ab97e9) - поведение аналогичное 3.0.0

Я теперь в винде запускаю ping -t ip_addr это бесконечный пинг, и как только вижу, что задержка нескольких ответов подряд стала меньше 1 мс, прерываю. Поломка гарантирована.
Код:
Ответ от 172.16.1.12: число байт=32 время=6мс TTL=128
Ответ от 172.16.1.12: число байт=32 время=236мс TTL=128
Ответ от 172.16.1.12: число байт=32 время=161мс TTL=128
Ответ от 172.16.1.12: число байт=32 время=2мс TTL=128
Ответ от 172.16.1.12: число байт=32 время=1мс TTL=128
Ответ от 172.16.1.12: число байт=32 время=1мс TTL=128
Ответ от 172.16.1.12: число байт=32 время=1мс TTL=128
@nikolz, предположу, что deep-sleep это тот режим, выйти из которого можно только подав внешний сигнал на ногу reset. Этот внешний сигнал подаётся блоком RTC, осталось сделать перемычку и вуаля! В то время, как из режима light-sleep можно выйти как по внешнему сигналу на ноге, так и по программному прерыванию от блока RTC. В даташите на NONOS_SDK есть функции аппаратного таймера и сказано, что для работы этого таймера нужно избегать пользования режимом light-sleep. Если аппаратный таймер в режиме light-sleep не работает, то на чём остаётся реализовывать программные таймеры, как не на блоке RTC??
нет это не так
В deep-sleep все отключается и работает лишь RTC и память RTC. Когда с RTC (GPIO16)придет сигнал на RST то произойдет restart и начнется установка сеанса. Обычно это 4 секунды, мне удалось получить 0.25 сек.
А в в режиме Ligh ответ гораздо быстрее так как рестарта нет. Но и ток больше так как работает система прерываний и еще что-то
 
Сверху Снизу