Классическая змейка на адресных светодиодах в формате игровой консоли
Привет, Хабр! Хочу рассказать об одном из своих любимых DIY проектов, который я реализовал еще пару лет назад. Данным проектом я хотел закрыть две цели: во-первых, подготовить подарок на день рождения своей племяннице (Ксюша, привет!), во-вторых, переползти с микроконтроллеров Atmel на ST. Также хотел получить опыт в использовании С++ во embedded устройствах.
Итак, подробнее о девайсе. Устройство представляет собой портативную игровую консоль с (пока что) одной игрой на борту - Змейка. Основные правила игры не отличаются от тех, что мы видели на первых кнопочных телефонах. С помощью джойстика направляем наше пресмыкающееся в сторону еды, кнопкой "speed" изменяем скорость передвижения в любой момент игры. "Бесшовное" игровое поле: змейка не разбивается о край, а появляется на противоположной стороне экрана. Цель - съесть как можно больше, стараясь не перекусить собственный хвост.
Микроконтроллер
В качестве микроконтроллера(далее - МК) выбрал STM32F103C8T6. Так как в наличие была отладочная плата Blue Pill + отдельно лежали камни, которые я мог пустить в ход при работе над своей платой. На тот момент времени заполучить этот МК за приемлемую цену не было проблемой(минутка ностальгии?) . МК обладает всей необходимой периферией для работы с остальными блоками устройства.
Экран
Физически игровое поле представляет собой матрицу адресных светодиодов WS2812B размерностью 16х16 штук. В каждом светодиоде имеется встроенный контроллер, который декодирует полученный цифровой сигнал и преобразует его значение в уровень яркости для каждого из трех основных цветов. Яркость кодируется следующим образом:
Необходимо передать на вход 24 бита, по 8 бит на каждый цвет в формате G->R->B. Об окончании пакета сигнализирует пауза в передачи данных. Логические уровни удобнее всего генерировать с помощью широтно-импульсной модуляции(PWM), изменяя скважность сигнала. Использовал для этого аппаратный таймер МК. Для того чтобы обновление кадров на экране происходило "на фоне" других задач использовал так блок Direct Memory Access(DMA). Это по сути контроллер внутри МК, который может самостоятельно, без участия процессора, перемещать данные из памяти в периферию.
Управление
По сути джойстик представляет собой два переменных резистора. При наклоне ручки по любой из двух взаимно перпендикулярных осей, происходит изменение напряжения на соответствующем выходе. По этим значениям можно найти положение ручки относительно центра. Для измерения напряжений с выходов джойстика использовал встроенный в МК аналого-цифровой преобразователь(АЦП). В основной программе запускается таймер, затем по его переполнении с блока АЦП фиксируется текущее цифровое значение аналогового сигнала на входе. Таким образом, косвенно определяется положение джойстика и соответственно направление движения змейки.
Питание
Как говорят: если хочешь что-то получить, ты должен отдать взамен нечто равноценное. Так вот, чтобы достать элемент питания пришлось принести в жертву одну из своих китайских безделушек. Добытый литиевый аккумулятор оказался без маркировки емкости. Однако судя по габаритам, прикинул, что как минимум на полтора часа работы должно хватить. В реальности автономность устройства оказалась даже больше. Аккумулятор подключал через модуль на TP4056.
Это плата контроля заряда. Помимо этого защищает аккумулятор от переразряда и короткого замыкания. Максимальная сила тока, заряжающего батарею, устанавливается резистором R3. Чтобы не допустить перегрева аккумулятора установил практически минимальный ток. Также модуль имеет индикацию: пока идет заряд светит красный светодиод, а когда батарея полностью зарядится вместо красного загорится синий\зеленый светодиод. Чтобы вынести эту информацию на поверхность корпуса пришлось выпаять родные светодиоды и поставить свои, закрепив их в держатели.
На основной плате управления расположил батарейку CR2032 для обеспечения работы часов реального времени(RTC) при отсутствии основного питания. Блок RTC здесь выступает как источник энтропии для генерации случайного числа, которое в свою очередь используется для создания параметров(координаты, цвет) съедобного пикселя для нашей змейки.
Корпус
Так сложилось, что первым моим CADом для 3D моделирования стал OnShape, который я благополучно использовал для всех своих DIY проектов. Это замечательный тул, для тех кто не хочет устанавливать какое-либо ПО, а работать прямо из браузера. Но самое большое преимущество, по крайней мере для меня, это то, что я обладал учебной лицензией:) Потом, в 2022 году так вышло, что аккаунт вместе с десятком моих моделей деактивировали. Это вынудило меня пересесть на SolidWorks, о чем я нисколько не жалею.
Самая большая сложность в работе над корпусом это было перенести его из виртуального мира в физический. Большая площадь и изгибы поверхности девайса доставляли неудобства при настройке 3D принтера на печать. ABS пластик норовил отклеится от стола, а обилие поддержек давало большой перерасход материала. Делить деталь и печатать по частям я не хотел, по той причине, что потом после склейки будут видны стыки и швы.
В дальнейшем планирую расширить список доступных игр на консоли. Вполне получится добавить тетрис. Это не потребует изменений в органах управления.
С помощью данной статьи хотел поделиться своим опытом создания DIY девайсов, послушать критику и рекомендации. Все файлы проекта доступны на GitHub, чтобы каждый мог разобраться в деталях и использовать это в своих проектах.