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

Максимальный размер WEB страницы (html) для ESP8266 ?

Vasiks

Member
Привествую! Ранее никогда не занимался созданием web контента, а тем более на микроконтроллерах. И вот понадобилось сделать устройство, которое на WEB странице отображает около 60 параметров, а рядом поле для их ввода. И должна быть справка-описание каждого параметра (выпадающая при нажатии). Всё шло прекрасно, но на 17 параметре перестало работать. Выкидывает такую гадость:
код ошибки в сообщении ниже
Как выяснилось далее, если уменьшить размер web страницы, например потереть справку, то дальше можно дописывать код и оно работает. Получилось, что максимальный объем(вес) hlml страницы получился около 41Кб. Причем если 40Кб страница, то работает корректно, можно обновлять, менять параметры, никаких сбоев. Если чуть докинуть, например 41Кб, то при обновлении страницы может подвисать или вылетать. Если ещё чуть добавить, то уже не загружается страница, а ESP иногда в ребут уходит.
Собственно как можно таки сделать тяжеловесную страницу? По приблизительным оценкам страничка в итоге будет весить около 180Кб, в основном текст, и 60 полей ввода через которые аяксом будут уходить параметры в ESP. Если страницу на флешке разместить, поможет? Хотя в самой ESP ещё дофига памяти, у меня ESP12S и там 4Мб. А ESP32 потянет? У меня её нет, стоит ли покупать для этого?
Библиотека обычная, которая установиласть в arduino ide под ESP8266 сама, при настройке и загрузке ESP плат - библиотека <ESP8266WebServer.h>
 

Vasiks

Member
код ошибки не поместился в одно сообщение, поэтому вот:
Код:
15:47:59.143 -> ......
15:48:01.618 -> Connected to wiff
15:48:01.652 -> IP address: 192.168.1.15
15:48:01.652 -> HTTP server started
15:48:11.487 ->
15:48:11.487 -> Exception (29):
15:48:11.487 -> epc1=0x4000df64 epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000
15:48:11.858 ->
15:48:11.858 -> >>>stack>>>
15:48:11.858 ->
15:48:11.858 -> ctx: sys
15:48:11.858 -> sp: 3fffec10 end: 3fffffb0 offset: 01a0
15:48:11.858 -> 3fffedb0:  40227927 3ffefc84 00000005 402278bc 
15:48:11.858 -> 3fffedc0:  00000002 40227863 00000002 402269bc 
15:48:11.858 -> 3fffedd0:  402269e5 3fffee80 3ffee0d8 00000016 
15:48:11.858 -> 3fffede0:  40224458 3fffee80 3ffedf84 3ffed988 
15:48:11.858 -> 3fffedf0:  3ffea3d0 3fffee80 3fffee80 00000006 
15:48:11.858 -> 3fffee00:  00575447 00c50ac1 40102686 00000100 
15:48:11.858 -> 3fffee10:  3ffe9d3c 7fffffff 00002200 00000001 
15:48:11.858 -> 3fffee20:  402207bd 00000080 3ffeda0c 00000000 
15:48:11.858 -> 3fffee30:  ffffffe0 3ffeda98 3ffea3e0 3ffee0d8 
15:48:11.858 -> 3fffee40:  3ffecf18 00000040 00000000 4022514f 
15:48:11.858 -> 3fffee50:  00000000 3ffefc84 ffffffe0 00000000 
15:48:11.858 -> 3fffee60:  00000000 3ffee0d8 00000017 0000000f 
15:48:11.858 -> 3fffee70:  40000f58 00000000 6cef81f2 00000000 
15:48:11.858 -> 3fffee80:  00000000 08310b0b 00640100 00000050 
15:48:11.858 -> 3fffee90:  3ffea3f4 00000096 3ffea414 3ffea3e8 
15:48:11.858 -> 3fffeea0:  3ffea40c 3ffea3f4 3ffea3f9 3ffea406 
15:48:11.858 -> 3fffeeb0:  00000000 00000000 3ffea41a 3ffea467 
15:48:11.858 -> 3fffeec0:  3ffea433 3ffea44f 00000000 00000000 
15:48:11.858 -> 3fffeed0:  00000000 00000000 00000040 00000000 
15:48:11.858 -> 3fffeee0:  3fff004c 40224bc2 3ffecf18 3ffefc84 
15:48:11.858 -> 3fffeef0:  00000000 3ffee0d8 3ffecf18 3ffea3d0 
15:48:11.858 -> 3fffef00:  3ffea3d0 000000be 00000000 00000040 
15:48:11.858 -> 3fffef10:  00000000 3ffea3da 4022e30f 3ffecf18 
15:48:11.858 -> 3fffef20:  3ffea3c4 3fffdcc0 3ffe95a8 3ffe95a8 
15:48:11.858 -> 3fffef30:  00000080 3ffecf18 00000000 3ffe85d0 
15:48:11.858 -> 3fffef40:  4022dbcf 3fffdab0 00000000 40208ebb 
15:48:11.858 -> 3fffef50:  3ffe95a8 40000f49 3fffdab0 40000f49 
15:48:11.858 -> 3fffef60:  40000e19 40001878 00000002 00000000 
15:48:11.858 -> 3fffef70:  3fffff10 401047e1 40001878 00000002 
15:48:11.858 -> 3fffef80:  401047e7 3ff3e1a5 fbd52dc0 4a583047 
15:48:11.858 -> 3fffef90:  4010000d 082babef d8929997 e9c140a4 
15:48:11.858 -> 3fffefa0:  4022caa8 3fffef3c 4022ca61 3ffffe18 
15:48:11.858 -> 3fffefb0:  3fffffc0 00000000 00000000 feefeffe 
15:48:11.858 -> 3fffefc0:  feefeffe feefeffe feefeffe feefeffe 
**********кусок вырезал
15:48:12.803 -> 3ffffe70:  3fffbd44 3ffef3f0 3ffffeb0 40204c66 
15:48:12.803 -> 3ffffe80:  3fffbd44 0056005f 09ff0020 402080fc 
15:48:12.803 -> 3ffffe90:  00000001 3ffffeb0 40241baa 402036d0 
15:48:12.803 -> 3ffffea0:  00000001 00000001 3fff05d4 40204cb0 
15:48:12.803 -> 3ffffeb0:  3fff1bac a184a18f 00000000 40208788 
15:48:12.803 -> 3ffffec0:  00000001 4020153c 3ffffef0 4020a9c2 
15:48:12.803 -> 3ffffed0:  00000001 4020153c 3fff05d4 401000e1 
15:48:12.803 -> 3ffffee0:  3fff05d4 3ffef430 3fff05d4 40203706 
15:48:12.803 -> 3ffffef0:  3ffe0000 3fff0000 80fef58c 80000030 
15:48:12.803 -> 3fffff00:  3fff05d4 3ffef430 3ffef3f0 40205536 
15:48:12.803 -> 3fffff10:  0000002f 80000000 81ff1e00 0000008f 
15:48:12.803 -> 3fffff20:  80005054 29021379 40100200 00002198 
15:48:12.803 -> 3fffff30:  00000001 3ffef430 00000001 40100170 
15:48:12.803 -> 3fffff40:  00000001 00000000 3ffef3f0 3ffef58c 
15:48:12.803 -> 3fffff50:  00000001 3ffef414 3ffef3f0 3ffef58c 
15:48:12.803 -> 3fffff60:  00000001 3ffef414 3ffef3f0 4020570b 
15:48:12.803 -> 3fffff70:  00000000 00000000 3fff0e9c 3ffef58c 
15:48:12.803 -> 3fffff80:  3fffdad0 00000000 3ffeedbc 402024dc 
15:48:12.803 -> 3fffff90:  3fffdad0 00000000 3ffeedbc 402057c5 
15:48:12.803 -> 3fffffa0:  3fffdad0 00000000 3ffef54c 40209024 
15:48:12.803 -> <<<stack<<<
15:48:12.803 ->
15:48:12.803 ->  ets Jan  8 2013,rst cause:2, boot mode:(3,7)
15:48:12.880 ->
15:48:12.880 -> load 0x4010f000, len 1392, room 16
15:48:12.880 -> tail 0
15:48:12.880 -> chksum 0xd0
15:48:12.880 -> csum 0xd0
15:48:12.880 -> v3d128e5c
15:48:12.880 -> ~ld
15:48:12.880 -> ⸮#$`{⸮n$
15:48:13.404 -> .
15:48:13.404 -> Connected to wiff
15:48:13.404 -> IP address: 192.168.1.15
15:48:13.404 -> HTTP server started
 

Vasiks

Member
Вот вывод компилятора:
Executable segment sizes:

IROM : 319688 - code in flash (default or ICACHE_FLASH_ATTR)
IRAM : 26688 / 32768 - code in IRAM (ICACHE_RAM_ATTR, ISRs...)
DATA : 1488 ) - initialized variables (global, static) in RAM/HEAP
RODATA : 3236 ) / 81920 - constants (global, static) in RAM/HEAP
BSS : 26816 ) - zeroed variables (global, static) in RAM/HEAP

Скетч использует 351100 байт (33%) памяти устройства. Всего доступно 1044464 байт.
Глобальные переменные используют 31540 байт (38%) динамической памяти, оставляя 50380 байт для локальных переменных. Максимум: 81920 байт.
esptool.py v2.8
Serial port COM3
Connecting....
Chip is ESP8266EX
Features: WiFi
Crystal is 26MHz
MAC: ec:fa:b7:18:71:44
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 460800
Changed.
Configuring flash size...
Auto-detected Flash size: 4MB
Compressed 355248 bytes to 229145...

Writing at 0x00000000... (7 %)
Writing at 0x00004000... (14 %)
Writing at 0x00008000... (21 %)
Writing at 0x0000c000... (28 %)
Writing at 0x00010000... (35 %)
Writing at 0x00014000... (42 %)
Writing at 0x00018000... (50 %)
Writing at 0x0001c000... (57 %)
Writing at 0x00020000... (64 %)
Writing at 0x00024000... (71 %)
Writing at 0x00028000... (78 %)
Writing at 0x0002c000... (85 %)
Writing at 0x00030000... (92 %)
Writing at 0x00034000... (100 %)
Wrote 355248 bytes (229145 compressed) at 0x00000000 in 5.5 seconds (effective 514.8 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...
 

Vasiks

Member
Тут дело в чём получается, если я правильно понимаю... У меня классическое объявление:
Код:
 String s = start_page;
 server.send(200, "text/html", s);
То есть вся моя web страница, весь её код в html и скриптах, это всё запихивается в одну переменную типа String. А каков максимальный размер этой переменной в Arduino IDE, знает кто? Я нашёл один ответ:
.... Максимальная длина строки зависит от того, сколько памяти свободно, когда вы пытаетесь что-то в ней сохранить. ....
Полностью по этому поводу расписано тут: https://issue.life/questions/55342103
И если это так (если это мой случай), то, получается, что у меня оперативки свободно только около 40Кб? Но куда остальные 120Кб делись? В ESP8266 памяти 160Кб, так ведь?
А каков выход из положения? Я смогу что-то выиграть, если разобью страницу на пять страниц, и загружая одну страницу в оперативную память, удалять остальные страницы? Или оно всё сразу должно грузиться и этим нельзя манипулировать?
Чё делать то? Идеи есть у кого?
 

nikolz

Well-known member
Тут дело в чём получается, если я правильно понимаю... У меня классическое объявление:
Код:
 String s = start_page;
server.send(200, "text/html", s);
То есть вся моя web страница, весь её код в html и скриптах, это всё запихивается в одну переменную типа String. А каков максимальный размер этой переменной в Arduino IDE, знает кто? Я нашёл один ответ:

Полностью по этому поводу расписано тут: https://issue.life/questions/55342103
И если это так (если это мой случай), то, получается, что у меня оперативки свободно только около 40Кб? Но куда остальные 120Кб делись? В ESP8266 памяти 160Кб, так ведь?
А каков выход из положения? Я смогу что-то выиграть, если разобью страницу на пять страниц, и загружая одну страницу в оперативную память, удалять остальные страницы? Или оно всё сразу должно грузиться и этим нельзя манипулировать?
Чё делать то? Идеи есть у кого?
внимательно читаем документацию:
RAM size < 50 kB, that is, when ESP8266EX is working under the Station mode and connects to the router, the maximum programmable space accessible in Heap + Data section is around 50 kB.
-------------------
В вашем варианте Вы тратите в два раза больше памяти
так как то,что вы копируете изначально хранится во флеш.
 

Vasiks

Member
внимательно читаем документацию:
RAM size < 50 kB, that is, when ESP8266EX is working under the Station mode and connects to the router, the maximum programmable space accessible in Heap + Data section is around 50 kB.
О как! Документацию я, конечно же, не читал. А зачем оно мне, думал я...
В вашем варианте Вы тратите в два раза больше памяти
так как то,что вы копируете изначально хранится во флеш.
Тут не понял. А как тратить меньше? Ну да, данные на флеш памяти(но её много и не жалко), а потом данные утекают в RAM. То есть всё равно я ограничен памятью RAM, и максимальный размер страницы будет зависеть от нее? Ну другими словами я не смогу выгружать данные из флеш напрямую без использования таких же объёмов RAM?
P.S. Переделал код под ESP32, там заявлено 512Кб RAM. Всё заработало, можно говнокодить дальше. Но, чувствую, целиком что надо не вместится. Но не отчаиваюсь, есть ESP32 CAM, оно же ESP32-S, там, вроде, 4Mb PSRAM. Ну на крайняк нашёл ещё ESP32WROVER-B, пишут, что там 8Mb PSRAM - туда уж точно всё влезет.
P.PS. Конечно я бы рад написать нормально код, чтоб всё работало и на малой памяти, но не умею. ESP12S ~$1.5, ESP32WROVER-B ~$3.
 

pvvx

Активный участник сообщества
Полностью по этому поводу расписано тут: https://issue.life/questions/55342103
Там не всё описано. Если вы дополняете string то производится realloc(), а для увеличения выделенного ранее размера realloc() захватывает новый непрерывный кусок с большим размером свободной памяти и туда копирует старый, а потом освобождает старый. По этому работа со string достаточно медленная. В итоге памяти кучи надо от 2-х раз больше, чем максимальный string с которым вы работаете.
И ещё одно жирное "НО" - когда память дефрагментирована, то большой непрерывный кусок свободной памяти для копирования может и не найтись...
Дефрагментация heap кучи - это частое явление. Чистка возможна когда все освободят занятые кусочки. Это возможно только при перезагрузке.

Передача файла кусками ограничена буферами TCP и для скорости желательно передавать ровно по 2 TCP_MSS или более, но кратно TCP_MSS, учитывая chinked. Если блоки меньше 1 MSS - получите задержку в 200 ms между передачей каждого блока... Не известно, делает ли какую оптимизацию socket в Arduino либах... (я этих либ не пользовал и не собираюсь - может другие уточнят)
 
Сверху Снизу