PunchEx-Miss Taraba Comfort Williams diesThe Jerusalem PostJewish safety isn’t partisan: No party’s victory can substitute for that obligation - editorialInquirerKin honor ‘desaparecidos’ on All Souls’ Day한겨레‘833대1 경쟁률·전원 합격’ 청춘영화가 욕망의 스릴러로…‘최종면접’ZDF heuteAktuelle Pressemitteilungen des ZDFCNN Türk"SUSUZ YAZ" İÇİN GERİ SAYIM BAŞLADI! Suyun yaktığı hayatlar...Wirtualna PolskaZłe wieści dla rządu Tuska. Ten sondaż mówi wszystkoComplete SportsSuper Falcons Receive Tinubu’s $100,000 Reward For Record 10th WAFCON TitleSözcüSon dakika... Korkmaz Enes Ergun tutuklandı!SportstarRanji Trophy live score, round 4: Tamil Nadu dominates Chandigarh; Urvil Patel scores century for Gujarat; VID 105/6 vs MPn-tvBitterer Abend für Weltmeister: Dennis Schröder wird aus Startformation gekicktColliderEvery Jane Austen Love Interest, Ranked
The Daily Newsstand · Free, Always
Tuesday, November 3, 2026

LLM после работы: интерактивная книга на ESP32-P4. Часть 2: ESP-IDF, дисплей и первая анимация

Translate

В предыдущей статье мы с дочкой начали собирать собственную интерактивную книгу на ESP32-P4, где дочь придумывает основных персонажей и является источником вдохновения, а я с помощью нейросетей превращаю её фантазии в реальность в виде изображений, звуков и анимации. Делаем несколько сюжетных веток, где решение принимает ребенок, получаем 16 различных концовок, и всё это на английском языке для пущего образовательного эффекта.

Смысл затеи: провести вместе время за созиданием, так, чтобы было интересно и дочери (придумать, повозиться с результатом), и мне (освоить новую панель и ИИ), а также получить крутую развивающую штуку (логика, память, английский язык). Один из комментаторов к прошлой статье назвал это новой настоящей формой технологического искусства – не буду с ним спорить.

Делаем книгу на отдельной тач-скрин панели (Elecrow CrowPanel Advanced ESP32-P4), т.к. хотелось сделать самостоятельное устройство, а не просто приложение на планшете или телефоне. Одно устройство – одна функция: без дополнительных соблазнов в виде ютьюба. Кроме того – сами панели весьма интересные, они не так давно появились, и чего на них только сейчас не делают – это такой очень бюджетный вариант сделать полноценный HMI для чего угодно.

В этой статье настроим среду разработки и сделаем первые шаги: запустим дисплей, сенсор, разберемся с LVGL и научимся выводить свою графику. Исходники – выложены в репозиторий, берите, делайте похожее или что-то совершенно новое, буду рад, если поделитесь результатом, можем выкладывать ваши работы в тот же репозиторий.

Настройка ESP-IDF и PSRAM

Для работы с MIPI DSI и тяжелой графикой мы используем официальный фреймворк ESP-IDF 5.5.2. Эта версия выбрана не случайно: официальные BSP от Elecrow для панелей требуют версию не ниже 5.4.2, а в ветке 5.5 были исправлены критические баги с таймерами и энергопотреблением для чипов ESP32-P4.

Первое, что нужно сделать перед сборкой – включить внешнюю память. Без этого при попытке загрузить картинку разрешением 1024×600 (которая занимает больше мегабайта) система упадет с ошибкой Out of Memory.

В menuconfig переходим в раздел Component config -> ESP PSRAM. Включаем Support for external PSRAM.

На плате CrowPanel распаяно 32 МБ PSRAM. Мы выбираем режим 16-Line-Mode PSRAM и устанавливаем частоту 200 МГц. Такой режим работы обеспечивает высокую пропускную способность, необходимую для быстрой подгрузки кадров анимации в буфер дисплея.

Инициализация BSP и выделение задачи для LVGL

Плата использует высокоскоростной интерфейс MIPI DSI для связи с дисплеем. Настраивать его тайминги вручную – долго и чревато ошибками, поэтому мы используем готовый компонент espressif__esp32_p4_function_ev_board от Elecrow.

Вся инициализация железа происходит в функции app_main:

extern "C" void app_main(void)
{
    bsp_display_cfg_t display_cfg = {
        .lvgl_port_cfg = ESP_LVGL_PORT_INIT_CONFIG(),
        .buffer_size = BSP_LCD_H_RES * BSP_LCD_V_RES,
        .double_buffer = BSP_LCD_DRAW_BUFF_DOUBLE,
        // ... флаги настройки буферов
    };
    
    // Привязываем задачу LVGL к конкретному ядру
    display_cfg.lvgl_port_cfg.task_affinity = kLvglTaskCore;
    
    if (!bsp_display_start_with_config(&display_cfg)) {
        ESP_LOGE(TAG, "display init failed");
        return;
    }
}

Здесь мы видим, как настраивается порт для графической библиотеки LVGL. Ключевой момент – параметр task_affinity.

ESP32-P4 двухъядерный, и мы можем распределить выполнение задач между ядрами. В частности, задачу LVGL, которая отвечает за обработку графического интерфейса и анимаций, закрепляем за конкретным ядром (в нашем случае kLvglTaskCore). Пока это ядро занято пересчетом пикселей и анимаций, второе ядро ESP32-P4 остается свободным для выполнения фоновых задач: чтения файлов с SD-карты или обработки логики.

Сам BSP внутри себя поднимает esp_lcd, настраивает MIPI DSI и инициализирует тач-контроллер GT911.

Анимация заставки на LVGL

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

В LVGL для этого есть lv_anim_t. Он позволяет менять свойства графических объектов во времени: например, перемещать их из одной точки в другую.

В нашем случае элементы заставки движутся по вертикальной оси Y.

lv_anim_t anim;
lv_anim_init(&anim);
lv_anim_set_var(&anim, obj);
lv_anim_set_exec_cb(&anim, title_screen_anim_set_y_cb);
lv_anim_set_values(&anim, group[i].final_y + start_offset_y, group[i].final_y);
lv_anim_set_time(&anim, duration_ms);
lv_anim_set_path_cb(&anim, lv_anim_path_ease_out);
lv_anim_start(&anim);

В этом фрагменте мы создаем объект анимации, задаем ему начальное и конечное положение по оси Y (заставляя элементы «выезжать» на экран) и применяем функцию плавности lv_anim_path_ease_out. Это позволяет облакам и звездам на заставке двигаться естественно, без резких рывков.

В принципе, для первых экспериментов с анимацией этого достаточно. Можно создавать несколько графических объектов и запускать для них разные движения, используя стандартные средства LVGL.

Дальше эту же графическую библиотеку будем использовать и для остальных элементов книги.

Аппаратные нюансы: SD-карта и питание

В процессе выяснились две особенности, которые могут вас затормозить, когда вы будете делать свой вариант книги, если о них не знать.

Карта памяти

Так как ресурсов (картинки, звук) много, а памяти на самой панели – мало, их приходится хранить на внешней microSD карте.

Вот оно, гнездо для карточки

Вот оно, гнездо для карточки

При самой первой загрузке панель может не увидеть карту памяти из-за особенностей инициализации контроллера. В этом случае достаточно перезагрузить панель (выключить и включить питание), и карта прочитается корректно. А, ну и карта должна быть отформатирована в FAT32. Ещё замечание (столкнулся с этим уже в следующем проекте, там была существенно выше скорость чтения с карты) – не все карты одинаковые. Могут отваливаться, если карта у вас старая (ниже Class 10), или неоригинальная (заказывал на озон несколько разных карт одинакового класса у разных продавцов, пока не пришло то, что работает). В этом проекте вряд ли эта ошибка появится, но для будущих проектов – имейте в виду.

Питание

Ещё одна странность, не претендую на правильность решения, но у меня сработало.

Когда запускается тяжелая анимация и громкий звук, нагрузки на шину питания возрастают. Случается, что панель внезапно перезагружается, или гаснет экран.

Опытным путём установили, что можно подключить второй кабель USB во второе гнездо (USB 2.0), и этот эффект пропадает.

Логика работы приложения: Story Loop и Full Story

Сейчас в прошивке реализовано два режима работы: демо и интерактивный.

  • Демо-режим (Story Loop): панель сама крутит историю, если лень принимать решения. Также это инструмент для отладки – можно запустить сюжет по кругу и проверить, не утекает ли память при долгой работе.

  • Интерактивный режим (Full Story). Это тот самый режим для дочки, ради которого всё затевалось. История останавливается на развилке и ждет, пока ребенок сам нажмет на кнопку.

Для реализации автоматического перехода в режиме Story Loop используется программный таймер LVGL – lv_timer_create(). После появления экрана выбора запускается таймер на 10 000 мс (STORY_LOOP_CHOICE_DELAY_MS). Если за это время касания не произошло, таймер срабатывает и программно эмулирует нажатие кнопки.

В выложенных исходниках в режиме Full Story доступна только одна сюжетная ветка. Недоступные варианты выбора блокируются: кнопка получает состояние LV_STATE_DISABLED, поверх нее отрисовывается полупрозрачный слой, а на уровне логики координатора блокируется обработка события выбора. Это защищает от случайного перехода в незаконченные ветки сюжета.

Работа с настройками и состояние паузы

Экран настроек (где регулируется громкость и яркость) можно открыть прямо во время чтения. Чтобы анимации и звук не конфликтовали с меню, реализована система паузы.

При открытии настроек функция settings_opened() сохраняет текущую фазу сюжета, а затем удаляет все активные таймеры через lv_timer_del() (включая 10-секундный таймер ожидания выбора). Блокировка мьютексами здесь не используется, так как удаление таймеров безопасно останавливает логику. После закрытия настроек сценарий запускается с сохраненной фазы, но отсчет времени на выбор начинается заново.

Что получилось и что дальше

Пока мы рассмотрели графическую часть – у нас есть настроенная среда, работающий дисплей, LVGL. Сделали заставку с несколькими анимированными объектами и стали понятны некоторые особенности панели.

Дальше – покажу, как устроен сюжетный движок и хранятся данные, и покажу, как генерили картинки, звуки, тексты и речь, поделюсь промптами (там хоть и не «рокет сайенс», но не будет лишним, особенно если вы не генерили раньше много картинок в одном стиле, сюжете, с одинаковыми героями).

Если у вас такая же панель (подойдут и 7 и 9 и 10.1 дюйма от Elecrow на P4), можете попробовать запустить нашу книгу и посмотреть, как она работает, взять исходники и собрать свой собственный вариант. Повторюсь, буду рад – если кто-то попробует и поделится своим вариантом, очень интересно, что получится, можно будет добавить в тот же репозиторий, получим «библиотечку» таких DIY интерактивных книжек.

View the original on Хабр →

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.