- PVSM.RU - https://www.pvsm.ru -

Один из ярких воспоминаний детства — просмотр семьёй диафильмов. Выключался свет, и на самодельном экране из простыни мы смотрели сказки. Детское воображение дорисовывало детали, и картинки оживали.
Сейчас в эпоху интернета, мультимедиа и ИИ вроде бы как такой необходимости нет, но слишком сильное чувство ностальгии. Поэтому решил получить ностальгические воспоминания с использованием современных технологий, а заодно и попрактиковаться в использовании энкодеров, разработке программ на Си и настройке Linux на Raspberry Pi.
Фильмоскопа у меня уже давно нет, поэтому я решил его эмулировать при помощи Raspberry Pi Zero 2 W и дешёвого энкодера для макетной платы. Выход HDMI можно подключить к современному проектору или, что менее аутентично, к телевизору и попробовать освежить детские воспоминания.
У меня получилось устройство, фотографию которого вы видели в заголовке. Приведу ещё несколько фотографий:


А также видео работы фильмоскопа в действии:
Несмотря на то что устройство простое, оно позволяет оживить ностальгические воспоминания.
Мой эмулятор фильмоскопа состоит из:
Raspberry Pi Zero 2W с распаянной PLS-вилкой (with headers),
модуля энкодера,
шлейфа из 5-ти проводов с Dupont-коннекторами,
корпуса и ручки энкодера, распечатанных на 3D-принтере.
Если у вас нет 3D-принтера, то корпус можно попробовать сделать из подручных материалов, например, картона. Но придётся повозиться.
Для себя я понял, что 3D-принтер — сейчас обязательное устройство для DIY-проектов, позволяющее создавать завершённые устройства, дающее дополнительные возможности для реализации своих идей и экономящее время.
Задача создания фильмоскопа состоит из следующих шагов:
подключить к Raspberry энкодер,
написать небольшую программу, которая будет обрабатывать события от энкодера и выполнять прокрутку серии отсканированных кадров диафильма,
поставить программу для просмотра в автозагрузку,
поместить это несложное устройство в корпус.
Последние два пункта придают завершённости устройству, но даже без них всплывают детские воспоминания.
Я думаю, дело в ручке энкодера, которая гораздо больше похожа на ручку для прокрутки диафильмов, чем колёсико мышки или нажатие кнопок на клавиатуре, также дополнительный эффект добавляет прокрутка серии кадров единым целым.
Энкодер — это устройство, преобразующее механическое перемещение или вращение в цифровой сигнал для определения положения, направления и скорости движения.
Часто в статьях приводятся принципы работы энкодера и как обрабатывать его сигналы с GPIO-пинов или как использовать библиотеки для работы с энкодером.
Модуль энкодера подключается к GPIO-пинам Raspberry Pi Zero W 2. У меня следующая схема подключения.
В Linux не нужно погружаться в основы принципов работы энкодера, а просто использовать готовый драйвер, интегрируемый в систему ввода Linux.
Чтобы Linux распознал энкодер и мог с ним работать на встраиваемом устройстве, необходимо написать корректное Device Tree. В Raspbian можно сделать проще с использованием оверлея.
Для этого необходимо отредактировать файл /boot/firmware/config.txt. В конец файла добавить строку
dtoverlay=rotary-encoder, pin_a=2, pin_b=4,relative_axis=8
где:
dtoverlay=rotary-encoder — включение оверлея для драйвера роторного энкодера,
pin_a=2 — GPIO 2 используется как канал A энкодера,
pin_b=4 — GPIO 4 используется как канал B,
relative_axis=8 — указывается, какое событие Linux генерировать. Значение 8 — это числовой код Linux input subsystem — REL_WHEEL (прокрутка колеса мыши).
Драйвер сравнивает фазу A и B, чтобы понимать направление вращения: по часовой — одно направление, против часовой — другое.
Для того чтобы Linux узнал о наличии кнопки у энкодера, нужно подключить ещё один оверлей. В файл config.txt добавить
dtoverlay=gpio-key,gpio=3,keycode=28,label=encoder_button
где:
dtoverlay=gpio-key — включает оверлей драйвера кнопок GPIO,
gpio=3 — кнопка подключена к GPIO 3,
keycode=28 — задаёт код клавиши Linux input subsystem — KEY_ENTER (клавиша Enter),
label=encoder_button — имя (метка) кнопки.
Нажатие на кнопку энкодера будет равнозначно нажатию Enter на клавиатуре.
Модуль энкодера лучше покупать тот, где есть фиксирующие гайки, такой проще закрепить на корпусе.
Для работы с графикой удобно использовать OpenGL, а ещё удобнее и быстрее библиотеку SDL, которая представляет собой абстракции для построения графических приложений и игр.
Так как разработанный эмулятор фильмоскопа является прототипом, который можно повторить самому за несколько часов, у него минимальный функционал: можно только переключать диафильмы при помощи кнопки энкодера и прокручивать диафильмы вперёд-назад.
В FAT-раздел SD-карты в директорию diafilms помещаются директории с отсканированными диафильмами.
Чтобы не усложнять программный код, я не стал использовать сложные структуры данных и динамическое выделение памяти.
Интересный факт я обнаружил при разработке программы: события от кнопки энкодера будут приходить в SDL-приложение, а вот для поворотов энкодера нужно использовать библиотеку libevdev.
Привожу код главной функции приложения, остальное вы можете посмотреть в моём репозитории на GitHub [1].
int main(int argc, char *argv[]) {
init_encoder();
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
printf("SDL_Init failed: %sn", SDL_GetError());
return 1;
}
IMG_Init(IMG_INIT_PNG);
SDL_DisplayMode mode;
SDL_GetDesktopDisplayMode(0, &mode);
SDL_ShowCursor(SDL_DISABLE);
render_width = mode.w;
render_height = mode.h;
win = SDL_CreateWindow("Filmoscope", SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, render_width, render_height,
SDL_WINDOW_FULLSCREEN);
renderer = SDL_CreateRenderer(
win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
const char *dir = "resources";
if (argc > 1) {
dir = argv[1];
}
load_diafilm_list(dir);
if (diafilm_count == 0) {
printf("No diafilms foundn");
return 1;
}
load_diafilm(&d, diafilm_dirs[current_diafilm]);
load_initial_slides();
int running = 1;
SDL_Event e;
while (running) {
if (encoder) {
int rc = libevdev_next_event(encoder, LIBEVDEV_READ_FLAG_NORMAL, &ev);
if (rc == 0) {
if (ev.type == 2) {
scroll(ev.value * render_height / 12);
}
}
}
while (SDL_PollEvent(&e)) {
if (e.type == SDL_QUIT)
running = 0;
else if (e.type == SDL_KEYDOWN) {
if (e.key.keysym.sym == SDLK_ESCAPE)
running = 0;
else if (e.key.keysym.sym == SDLK_DOWN)
scroll(render_height / 12);
else if (e.key.keysym.sym == SDLK_UP)
scroll(-render_height / 12);
else if (e.key.keysym.sym == SDLK_RETURN)
switch_diafilm();
}
}
render();
SDL_Delay(16);
}
cleanup_graphics();
return 0;
}
Добавить функции и улучшить код можно всегда.
Вы можете установить приложение из исходных кодов, которые находятся на GitHub-репозитории.
Берём чистую microSD-карту и устанавливаем образ Raspbian Lite.
Вставляем microSD-карту в Raspberry Pi Zero 2 W и выполняем загрузку Raspbian.
Добавляем недостающие пакеты:
sudo apt install libsdl2-dev libevdev-dev
Клонируем репозиторий:
git clone
Собираем приложение:
make
Помещаем в директорию diafilms в FAT-разделе папки с отсканированными диафильмами. Если вы используете microSD-карту в Windows, то директория diafilms должна находиться в корне файловой системы, в Raspbian Lite — в директории /firmware.
Запускаем приложение:
./filmoscope
Как я уже говорил ранее, завершённости эмулятору фильмоскопа придают автозагрузка и полноценный корпус. Рассмотрим сначала автозагрузку.
Автозагрузку приложения в Linux можно сделать несколькими способами. Так же это зависит от того, какой используется дистрибутив — с графическим интерфейсом или без, какой установлен Desktop Environment.
Простой способ добавить приложение в автозагрузку в Raspbian Lite — добавить следующие строки в конец файла .profile в домашней директории:
cd ~/pi-zero-filmoscope
./filmoscope
Эти строчки будут выполняться при логине пользователя. Подразумевается, что приложение у вас находится в директории /home/pi/pi-zero-filmoscope. Чтобы не нужно было вводить пользователя и пароль при логине, необходимо настроить autologin.
В Raspbian это удобно сделать при помощи команды ‘raspi-config’.
Я разрабатывал корпус «по мотивам» советских фильмоскопов, чтобы он был похож на них, и им было более или менее удобно пользоваться.
Для начала я загрузил с сайта grabcad.com [2] 3D модели Raspberry Pi Zero 2 W [3] и модуля KY-040 [4], чтобы легче было определять габариты и расположение компонентов.
Проектирование корпуса, как я уже говорил в прошлых статьях, — процесс увлекательный и творческий.
В этот раз у меня корпус получился с первого раза, если не считать испорченную деталь по причине отключения электричества на 1 секунду. Урок на будущее — печатать только с использованием бесперебойника.
Корпус проектировался для сборки без шурупов, так как он проще в изготовлении, да просто хотелось попробовать изготовить такой корпус и проверить, как он будет себя вести в эксплуатации.
Недостатки в корпусе есть, но это оставим пытливому читателю.
Часть деталей делал в контексте сборки, как и прорези для mini-HDMI, micro-USB и microSD-карты.
3D-модели деталей корпуса в виде STEP-файлов, а также модели для Bambu Lab находятся в GitHub-репозитории.
После того как получил удовлетворение от работающего устройства, желательно провести работу над ошибками и определиться, что можно было улучшить в корпусе и программной части.
Например, я бы, наверное, сделал прорезь в крышке корпуса и вставил туда кусочек плёнки, для аутентичности.
Также можно добавить ножки для корпуса.
В программной части я бы сделал отдельный небольшой дистрибутив, который бы работал в режиме киоска.
В просмотрщик можно добавить межкадровые промежутки, чтобы ещё больше походило на прокрутку диафильма.
Интересная доработка, которая требует проверки, — попробовать использовать беспроводной вывод вместо HDMI.
В целом проект получился довольно простым и повторить его можно буквально за несколько часов, если не считать времени на печать корпуса.
Но самое интересное в нём — не Raspberry Pi, не энкодер и непрограммная часть. Когда крутишь ручку и кадры сменяются один за другим, появляются какие-то знакомые ощущения из детства.
Конечно, никакая электроника не вернёт те времена, но современные технологии иногда позволяют хотя бы ненадолго к ним прикоснуться. И наверное, ради таких небольших проектов всё это и затевается.
© 2026 ООО «МТ ФИНАНС»
Автор: artyomsoft
Источник [5]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/linux/452415
Ссылки в тексте:
[1] моём репозитории на GitHub: https://github.com/artyomsoft/pi-zero-filmoscope
[2] grabcad.com: https://grabcad.com/
[3] Raspberry Pi Zero 2 W: https://grabcad.com/library/raspberry-pi-zero-2-w-1
[4] модуля KY-040: https://grabcad.com/library/ky-040-enkoder-s-tlacitkem-1
[5] Источник: https://habr.com/ru/companies/ruvds/articles/1038476/?utm_source=habrahabr&utm_medium=rss&utm_campaign=1038476
Нажмите здесь для печати.