Здравствуйте уважаемые коллеги.
Пилю некое управляющее устройство с выходом в сеть на esp.
Код большой с вебмордлй и AJAX, и вряд ли кто-то будет в нем ковыряться, потому размещать его целиком не буду. Если потребуется попробую сделать тестовый пример. Однако возникающая проблема достаточно редка и тестовый пример с нею еще отловить надо будет. Могу утверждать, что блокирующего кода нет. Имеется некоторое количество делеев(50) в качестве паузы dead-time при переключении выходных портов. Могу если что простыню выложить.
Собственно проблема. При тестировании устройства периодически вылезает перезагруз soft wdt reset (далее казус). Сначала напихал везде елдов, но после этого частота возникновения казуса возросла. Убрал все елды- казус возникает спонтанно примерно раз в сутки. Причем , что странно! У меня на тесте стоят две одинаковые платы с кодом последней и предыдущей стабильной версии. На вебмордах и оледе есть аптайм и макс/мин freemem. Таквот, они перезапускаются одновременно. Утечек памяти нет, болтается в районе 39000.
Странно-
Почему одновременно две платы от разных источников питания.
Почему увеличение елдов увеличивает количество казусов.
Учитывая, что платы должны управлять медленным оборудованием и все действующие параметры сидят в EEPROM, можно было бы и забить, но всё же некошерно как то.
Анализатор стека показывает в основном на строки не моего кода. Гдетто внизу перечня иногда болтается строка перед последним оставшемся в loop yield. Попробовал и его убрать- стала болтаться строка с выставлением порта PSF- расширителя после которой делеей(50).
Добавляет лишние обработчики которые и вызывают проблемы.
Насколько большой? Вот это интересно . Ни разу не видел достойный веб на ESP. Хотел сравнить с тем что я делаю (правда не на ESP) а на PIC32.
вебморду с AJAX пишете по взрослому? как для обычных серверов, или учитываете все таки что это не очень шустрый контроллер. Что с обменом в сети?
Decoding stack results 0x40210716: loop_task(ETSEvent)* at C:\Users\Alem\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266*core_esp8266_main.cpp* line 213 0x40100e54: umm_init() at C:\Users\Alem\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266\umm_malloc*umm_malloc.cpp* line 476 0x401000ac: app_entry_redefinable() at C:\Users\Alem\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266*core_esp8266_main.cpp* line 325 0x40100230: ets_post(uint8, ETSSignal, ETSParam) at C:\Users\Alem\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266*core_esp8266_main.cpp* line 181 0x40100230: ets_post(uint8, ETSSignal, ETSParam) at C:\Users\Alem\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266*core_esp8266_main.cpp* line 181 0x40100230: ets_post(uint8, ETSSignal, ETSParam) at C:\Users\Alem\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266*core_esp8266_main.cpp* line 181 0x40100230: ets_post(uint8, ETSSignal, ETSParam) at C:\Users\Alem\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266*core_esp8266_main.cpp* line 181 0x4021d449: esp2glue_err at glue-esp/lwip-esp.c line 112 0x40100230: ets_post(uint8, ETSSignal, ETSParam) at C:\Users\Alem\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266*core_esp8266_main.cpp* line 181 0x40100230: ets_post(uint8, ETSSignal, ETSParam) at C:\Users\Alem\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266*core_esp8266_main.cpp* line 181 0x4021d515: glue2esp_linkoutput at glue-esp/lwip-esp.c line 301 0x4021b4f8: __ssputs_r at /workdir/repo/newlib/newlib/libc/stdio/nano-vfprintf.c line 232 0x4021b434: __ssputs_r at /workdir/repo/newlib/newlib/libc/stdio/nano-vfprintf.c line 182 0x4021d515: glue2esp_linkoutput at glue-esp/lwip-esp.c line 301 0x4021d743: new_linkoutput at glue-lwip/lwip-git.c line 268 0x4021db9e: ethernet_output at netif/ethernet.c line 312 0x4021d743: new_linkoutput at glue-lwip/lwip-git.c line 268 0x40223948: etharp_output_to_arp_index at core/ipv4/etharp.c line 769 0x40100230: ets_post(uint8, ETSSignal, ETSParam) at C:\Users\Alem\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266*core_esp8266_main.cpp* line 181 0x40223a1c: etharp_output_LWIP2 at core/ipv4/etharp.c line 885 0x4021b4f8: __ssputs_r at /workdir/repo/newlib/newlib/libc/stdio/nano-vfprintf.c line 232 0x40106c0d: Twi::busywait(unsigned int) at C:\Users\Alem\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266*core_esp8266_si2c.cpp* line 237 0x4021132c: Twi::write_bit(bool) at C:\Users\Alem\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266*core_esp8266_si2c.cpp* line 280 0x4020808c: iarduino_I2C::writeBytes(unsigned char, unsigned char, unsigned char, unsigned char)* at C:\Users\Alem\Documents\Arduino\libraries\iarduino_OLED-1.1.0\src/iarduino_OLED_I2C.h line 180 0x40216f78: _printf_i at /workdir/repo/newlib/newlib/libc/stdio/nano-vfprintf_i.c line 246 0x4021b434: __ssputs_r at /workdir/repo/newlib/newlib/libc/stdio/nano-vfprintf.c line 182 0x4021b434: __ssputs_r at /workdir/repo/newlib/newlib/libc/stdio/nano-vfprintf.c line 182 0x4021b949: _svfprintf_r at /workdir/repo/newlib/newlib/libc/stdio/nano-vfprintf.c line 662 0x4021b949: _svfprintf_r at /workdir/repo/newlib/newlib/libc/stdio/nano-vfprintf.c line 662 0x402112b1: Twi::write_stop() at C:\Users\Alem\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266*core_esp8266_si2c.cpp* line 262 0x402115dd: Twi::writeTo(unsigned char, unsigned char, unsigned int, unsigned char)* at C:\Users\Alem\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266*core_esp8266_si2c.cpp* line 349 0x402116e0: twi_writeTo(unsigned char, unsigned char, unsigned int, unsigned char)* at C:\Users\Alem\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266*core_esp8266_si2c.cpp* line 983 0x4020caf0: TwoWire::endTransmission(unsigned char) at C:\Users\Alem\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\libraries\Wire*Wire.cpp* line 171 0x4020cb18: TwoWire::endTransmission() at C:\Users\Alem\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\libraries\Wire*Wire.cpp* line 179 0x402080c2: iarduino_I2C::writeBytes(unsigned char, unsigned char, unsigned char, unsigned char)* at C:\Users\Alem\Documents\Arduino\libraries\iarduino_OLED-1.1.0\src/iarduino_OLED_I2C.h line 183 0x40214691: iarduino_OLED::_sendData(unsigned char, unsigned char)* at C:\Users\Alem\Documents\Arduino\libraries\iarduino_OLED-1.1.0\src*iarduino_OLED.cpp* line 354 0x40100ea4: malloc(size_t) at C:\Users\Alem\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266\umm_malloc*umm_malloc.cpp* line 821 0x4020cc5d: iarduino_OLED::_sendBuffer() at C:\Users\Alem\Documents\Arduino\libraries\iarduino_OLED-1.1.0\src*iarduino_OLED.cpp* line 360 0x4020ceca: iarduino_OLED::_print(char, int, int)* at C:\Users\Alem\Documents\Arduino\libraries\iarduino_OLED-1.1.0\src*iarduino_OLED.cpp* line 281 0x402112b1: Twi::write_stop() at C:\Users\Alem\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266*core_esp8266_si2c.cpp* line 262 0x402115dd: Twi::writeTo(unsigned char, unsigned char, unsigned int, unsigned char)* at C:\Users\Alem\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266*core_esp8266_si2c.cpp* line 349 0x40100e7a: free(void)* at C:\Users\Alem\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266\umm_malloc*umm_malloc.cpp* line 595 0x402116e0: twi_writeTo(unsigned char, unsigned char, unsigned int, unsigned char)* at C:\Users\Alem\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266*core_esp8266_si2c.cpp* line 983 0x4020caf0: TwoWire::endTransmission(unsigned char) at C:\Users\Alem\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\libraries\Wire*Wire.cpp* line 171 0x4020cb18: TwoWire::endTransmission() at C:\Users\Alem\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\libraries\Wire*Wire.cpp* line 179 0x40208400: PCF8574::digitalWrite(unsigned char, unsigned char) at C:\Users\Alem\AppData\Local\Temp\arduino_build_890126\sketch*PCF8574.cpp* line 963 0x40100230: ets_post(uint8, ETSSignal, ETSParam) at C:\Users\Alem\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266*core_esp8266_main.cpp* line 181 0x40100251: esp_schedule() at C:\Users\Alem\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266*core_esp8266_main.cpp* line 128 0x402108da: loop_wrapper() at C:\Users\Alem\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266*core_esp8266_main.cpp* line 205
Ну не знаю масштабы, но в 12 закладках 130 кб исходников.
Как распознать взрослый аякс тоже не знаю, но есть ряд страниц оператора , инженера, конфигурационные, для обновления кода по-воздуху и почти все страницы получают и некоторые передают данные без перезагрузки страницы.
И все же непонятно. Все источники утверждают, что воизбежание soft wdt reset надо добавлять yield или delay в блокирующие места, чтобы принудительно передать управление фоновым процессам обслуживания tcp и wifi и избежать срабатывания soft wdt. У меня же получается, что чем елдов и делеев меньше, тем реже происходит рестарт.
у меня от 800кб до 1600кб кода и картинок нет , все в SVG. Даже успевает рисовать шкалы уровня аудио сигнала по четырем каналам. Получается достаточно неплохо.
А как у вас организованы запросы? Как часто они сыпятся?
Чтобы снизить количество запросов и чтения файлов нужно постараться организовать переменные. Можно сделать запросы к JSON файлам. Тогда одним махом делаем и запрос и получаем переменные, в итоге экономим время на чтение HTM файла , который и даром не нужен. Лучше сделать несколько JSONов для каждой вкладки и один общий файл , где будут глобальные переменные влияющие на общий процесс. Но он должен быть по максимуму минимальным . Там размещаем флаги , и этот файл читаем раз в сек. Если там установлены определенные флаги - то уже читаем соответствующий json к конкретной вкладке и не нужно гонять лишние данные.
пишут , пишут и другое, что это костыль , причем не очень удачный . Для мелких учебных задачек еще работает , но на больших проектах приносит проблемы.
Избежать задержек может помочь переход к switch программированию. Или отдать опрос медленных устройств где есть дилеи другому мелкому МК, который соберет данные и отдаст ESP.
Что обе платы падают в одно время?
Тогда вопрос - а что творится в сети по части широковещательных запросов? может у соседа что то просыпается и начинает долбать всех.
раз не знаете - то скорее всего код сделан для больших серверов а не для МК.
ESP не сильно масштабируемая система. Она хороша для одиночных простых задач. Поясню примером.
Например кто то может делать тропинки из тротуарной плитки - то ему не составит труда по освоенной технологии сделать 10, 100 и даже 1000м дорожки. А вот если освоил строительство одноэтажных домов , а потом захочешь делать второй , третий … 10, 100 этажей - то эта технология уже не годится, и нужна другая технология. Так и с ESP хотя каждый по отдельности модуль работает без проблем , но когда начинаешь городить “многоэтажность” - ту ту вылезают разные неприятности.
И это кроется в самой системе, где в угоду простоте создания небольших легких проектов пожертвовали возможностью делать сложные проекты.
ESP всегда позиционировалась для простых проектов.
Ну вот, убрал все yield и delay и , ОЧУДО ! 32 часа полет нормальный. У контрольного модуля с предыдущей версией прошивки аптайм 13 часов. Если все сохранится еще сутки, то прошивка обретет статус стабильной
Модуль контролирует имитатор оборудования (рект.колонна на нане) (датчик уровня, клапан слива, клапан подпитки, клапан отбора, определение потока), отображает на оледе статус оборудования, отсылает статус на агрегатор (как клиент), отображает статус на вебморде, позволяет калибровать оборудование, конфигурировать расположение датчиков и настраивать системные переменные через отдельные страницы вебморды, получает время по ntp, поддерживает перепрошивку « по воздуху».
Пришла есп32 с экранчиком, попробую перенести прошивку на неё.
Нууу я ведь только начинающий волшебник
И потом даже всякое большое оборудование имеет суточный таймер рестарта.
Лет так 35 назад я писал чтото на ассемблере для 1834вм86, так там по тз он работал в цикле перезагрузки 32мс. То есть 50 раз в минуту поднимал данные прошлого цикла из цмд, формировал и отрабатывал управление, читал датчики заносил все в цмд и уходил в перезагруз по аппаратному таймеру.
Если оно в деревне, то как Вы узнаете, что оно не рестартовало?
У меня тоже можно считать, что все работает без коллизий, если не отслеживать аптайм, или просматривать в мониторе лог.
И еще по этому же устройству.
После кардинальной кастрации всех елдов и делеев софт ресеты прекратились. Но пришло время для проявления следующей проблемы, до которой раньше не доживало одним аптаймом.
Железка должна периодически отправлять json на порт другой железки (на меге агрегатор, кто то даже его видел) и этот агрегатор принимает данные из разных мест и принимает их стабильно.
Одна из двух железок теряет вайфай- и не отсылает и не отвечает на вэб запрос морды по 80 порту. Потпробовал делать (по счетчику неудачных попыток) WIFI_OFF и новый коннект, но фактически реконнекта, как при рестарте всего, нет. Сейчас воткнул WiFi.setAutoReconnect(true)
WiFi.persistent(true)
Проверяю, жду, пока отвалится ( когда 5 часов, когда 15).
А как уважаемые кроты решают проблему потери коннекта?