Я — инженер техподдержки, наши клиенты знают меня как Aleksandr_Khlebnikov. Одна из задач инженеров в нашей компании — тестировать новое оборудование. Мы как раз выпустили модуль расширения, добавляющий контроллеру выход HDMI.
Смотреть на веб-интерфейс во время тестирования скучно, и в голову пришла мысль: а что если попробовать запустить на контроллере Doom?
Doom, известный нам с 1993 года, сейчас запускают буквально на всем, что хоть как-то умеет выполнять код. Калькуляторы, банкоматы, продвинутые тесты на беременность, беговые дорожки и даже кубики LEGO — культовый шутер давно стал символом инженерного троллинга и «челленджа на минималках».
Мне стало интересно проверить, получится ли заставить ПЛК не просто показать игру, а позволить в нее реально поиграть. В железо я верил, в свои умения — чуть меньше. Все-таки контроллер «заточен» под специфические задачи, а лишняя функциональность в ОС отключена. Но раз внутри работает полноценный Linux — почему бы не попробовать?
Итак, эта история о том, как я подключил к ПЛК HDMI-монитор, как запустил Doom и что из этого вышло. А еще о том, как я сделал геймпад с интерфейсом Modbus RTU.
Немного о железе
Для эксперимента использовался контроллер, который обычно выполняет совсем другие задачи: управляет не только умными домами, но и котельными, насосными, вентустановками, микроклиматом серверных, а где-то даже помогает добывать нефть. В общем, Doom ему по регламенту явно не положен.
В него я воткнул WBE2-HDMI, подключил монитор и беспроводную мини-клавиатуру с тачпадом.
Характеристики получившейся системы (для тех, кому важны цифры):
CPU: ARM Cortex-A53, 4 ядра, 1.5 ГГц (Allwinner T507);
RAM: LPDDR4, 2 ГБ;
Хранилище: eMMC 16 ГБ;
ОС: Debian 11 (Bullseye).

Установка
Пошел стандартным путем: поднял графическую подсистему X11 и поверх нее поставил Chocolate Doom.
apt install wb-hdmi (если контроллер заказан сразу с HDMI, этот шаг пропустите)
apt install -y xserver-xorg xinit openbox \
chocolate-doom freedoom unclutter

С «ванильным» doom-wad-shareware в Bullseye не сложилось — его просто нет в репозитории. Поэтому я сразу взял Freedoom — свободные ресурсы, полностью совместимые с движком.
Проверил, что все на месте:
ls /usr/share/games/doom/
# freedoom1.wad и freedoom2.wad должны лежать здесь
Для запуска через X11 сделал минимальный ~/.xinitrc:
openbox &
/usr/games/chocolate-doom -iwad /usr/share/games/doom/freedoom1.wad

И дальше — просто:
startx

Первый запуск занял около десяти минут, но появившийся на экране знакомый коридор подтвердил успех.
Проблемы
Конечно, все пошло не идеально. Doom на контроллере — это не «apt install && play».
1. Автозапуск Firefox
HDMI-модуль в контроллере стартует через systemd-сервис xinit.service. По умолчанию он тянет скрипт /etc/X11/xinit/xinitrc.wb, который всегда запускает Firefox в режиме киоска. Получалось так: я жду Doom, а на экран упорно лезет браузер. Пришлось покопаться в конфиге и отключить этот автозапуск.
2. Звука нет
У контроллера нет аудиовыхода. ALSA честно ругалась на «no sound device». Для эксперимента не критично — ностальгия работает и в тишине.
3. Консольный режим не взлетел
Хотелось обойтись без X11 и запустить Doom через framebuffer. Но программа упиралась и требовала X-сервер. В итоге я смирился и оставил X11.
Результат
После всех доработок Doom запустился на HDMI-мониторе. И главное — шел плавно, без лагов. Можно было бегать, стрелять и словить ту самую ностальгию.
По замерам в htop:
CPU: все четыре ядра были загружены на 70–90%;
RAM: Doom потреблял около 132 МБ памяти;
Система в целом: занято ~440 МБ из 1.9 ГБ доступной оперативки.
При этом сервисные процессы контроллера (wb-rules, wb-mqtt-db, wb-metrics и другие) продолжали работать параллельно. Их нагрузка оставалась минимальной (1–3%). То есть даже в «игровом» сценарии контроллер не терял своей основной функциональности.
FPS субъективно ощущался «как в детстве» — примерно 20–25 кадров.

Геймпад с Modbus RTU
Аппетит приходит во время игры. Мне стало интересно: а можно ли управлять Doom прямо через «железо» контроллера? Например, подключить кнопки к нашему модулю дискретных входов WB-MCM8 и использовать его как настоящий геймпад.
На контроллере работает расширение протокола Modbus — Быстрый Modbus, обеспечивающее время отклика около 60 мс. Этого вполне достаточно, чтобы реакция была не хуже, чем у обычной клавиатуры.
Механизм простой:
нажатие кнопки → драйвер запрашивает события → модуль сообщает об изменении регистра → публикуется значение в MQTT → эмулируется нажатие клавиши виртуальной клавиатуры → Doom реагирует.
Чтобы это заработало, нужно научить контроллер генерировать нажатия виртуальных клавиш. Здесь в игру вступает драйвер uinput.
Подготовка: включаем поддержку uinput
Uinput — это интерфейс для создания виртуальных устройств ввода. По умолчанию в ядре WB8 (6.8.0-wb144) драйвер uinput отсутствует. Значит, нужно пересобрать ядро.
Сборка выполняется не на самом контроллере, а на ПК с Ubuntu или Debian (!). Чтобы вам было легче, вот уже собранный пакет.
1. Устанавливаем инструменты:
sudo apt update
sudo apt install build-essential libncurses5-dev fakeroot lzop bc git bison flex libssl-dev rsync gcc-aarch64-linux-gnu
2. Клонируем исходники ядра контроллера:
git clone --depth=1 --branch dev/v6.8 https://github.com/wirenboard/linux ~/linux
cd linux
git submodule update --init --recursive
3. Запускаем конфигуратор:
make KBUILD_OUTPUT=.build-wb8 ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- menuconfig
4. Включаем опцию:
Device Drivers → Input device support → Miscellaneous devices → User level driver support → [M]
5. Сохраняем .config и собираем deb-пакеты:
KERNEL_FLAVOUR=wb8 ./scripts/package/wb/do_build_deb.sh
Важно: на вопрос «Use defconfig instead?» отвечаем N.
После сборки появятся пакеты:
linux-image-wb8_6.8.0-wb144_arm64.deb
linux-headers-wb8_6.8.0-wb144_arm64.deb
Установка ядра на контроллер
1. Переносим собранный пакет ядра на контроллер:
scp linux-image-wb8_6.8.0-wb144_arm64.deb root@<WB_IP>:/root/
2. Устанавливаем нужные пакеты и перезагружаем:
apt install python3-evdev python3-uinput -y
dpkg -i /root/linux-image-wb8_6.8.0-wb144_arm64.deb
reboot
3. Проверяем после перезагрузки:
uname -a
lsmod | grep uinput || modprobe uinput
ls -l /dev/uinput
Если все сделано правильно, в системе появится /dev/uinput.
Python-скрипт: MQTT → клавиатура
Теперь свяжем кнопки модуля WB-MCM8 с клавишами Doom с помощью Python-скрипта.
import paho.mqtt.client as mqtt
import uinput
# Маппинг входов WB-MCM8 -> клавиши Doom
TOPIC_KEY_MAP = {
"/devices/wb-mcm8_32/controls/Input 1": uinput.KEY_UP, # Стрелка вверх
"/devices/wb-mcm8_32/controls/Input 2": uinput.KEY_DOWN, # Стрелка вниз
"/devices/wb-mcm8_32/controls/Input 3": uinput.KEY_LEFT, # Стрелка влево
"/devices/wb-mcm8_32/controls/Input 4": uinput.KEY_RIGHT, # Стрелка вправо
"/devices/wb-mcm8_32/controls/Input 5": uinput.KEY_ENTER, # Enter
"/devices/wb-mcm8_32/controls/Input 6": uinput.KEY_ESC, # Esc
"/devices/wb-mcm8_32/controls/Input 7": uinput.KEY_LEFTCTRL, # Ctrl (огонь)
"/devices/wb-mcm8_32/controls/Input 8": uinput.KEY_SPACE, # Space (дверь/прыжок)
}
device = uinput.Device(list(TOPIC_KEY_MAP.values()), name="Virtual Keyboard")
def on_connect(client, userdata, flags, rc):
print("Connected to MQTT with result code " + str(rc))
for topic in TOPIC_KEY_MAP.keys():
client.subscribe(topic)
def on_message(client, userdata, msg):
topic = msg.topic
payload = msg.payload.decode().strip()
if topic in TOPIC_KEY_MAP:
key = TOPIC_KEY_MAP[topic]
if payload == "1": # нажата кнопка
device.emit(key, 1) # KEY_DOWN
elif payload == "0": # отпущена кнопка
device.emit(key, 0) # KEY_UP
device.syn()
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect("localhost", 1883, 60)
client.loop_forever()
Запускаем скрипт:
python3 mqtt_keyboard.py
Проверка работы uinput
Чтобы убедиться, что виртуальная клавиатура доступна:
apt install evtest -y
evtest
В списке устройств должно появиться что-то вроде Virtual Keyboard. При нажатии кнопок будут видны события EV_KEY.

Теперь кнопки, подключенные к WB-MCM8, Doom воспринимает их как настоящие клавиши.
Например:
Input 1 → стрелка вверх
Input 7 → Ctrl (стрельба)
Input 8 → Space (открыть дверь)
Итоги и выводы
Я сделал это!
Конечно, Doom на контроллере в щите в реальной жизни никому не нужен. Этот контроллер создан для серьезных задач — автоматизации (в том числе домашней), диспетчеризации, контроля и учета. Но эксперимент показал: внутри ПЛК скрывается полноценный Linux-компьютер, который способен на большее, чем кажется на первый взгляд.
А конкретнее:
контроллер спокойно тянет X11 и легкие GUI-приложения;
HDMI-модуль — это не только «киоск с Firefox», но и основа для собственных графических интерфейсов;
даже посредством Modbus RTU можно добиться отклика не хуже, чем у стандартной клавиатуры.
Чего я добился:
Doom стал реально играбельным даже без внешней клавиатуры;
я глубже понял внутренности ядра и драйверов linux;
и главное — теперь у меня есть собственный «modbus-геймпад» :)
Эксперимент оказался и фаном, и ностальгией, а заодно помог лучше разобраться в системе.
Комментарии (8)
legustarasov
08.10.2025 08:17Устройство на минималках:
CPU: ARM Cortex-A53, 4 ядра, 1.5 ГГц (Allwinner T507);
RAM: LPDDR4, 2 ГБ;
Это все же чуть мощнее, чем 486 процессор с 16МБ оперативной памяти, на котором я залипал в DOOM :)))
NotebookKiller
08.10.2025 08:17И совсем чуточку побольше, чем 386 с 4МБ оперативки минимальных требований. Правда, по энергопотреблению это похоже существенно меньше, чем трёшка-четвёрка
taraant
08.10.2025 08:17Не ожидал такой прыти от быстрого Модбаса!
Всмастривался в видео (в левом-нижнем углу) и по ощущениям задержка точно меньше 100мс (может и еще меньше - уже не понимаю) - если честно, то я не вижу задержки между нажатиями на кнопки и реакцией на видео.
Там точно "джойстик" подключен через модуль по модбасу или может напрямую в контроллер?!... :)
NotebookKiller
Олдскулы сведены!