Привет! Этот проект стал для меня важным шагом в мир : первое устройство с полностью собственной печатной платой, спроектированной с нуля в KiCad. Ранее я экспериментировал с готовыми модулями Arduino и макетными платами, но захотелось перейти к компактному, автономному решению на «голом» микроконтроллере.
Я новичок в проектировании PCB-устройств, так что могу ошибаться в некоторых нюансах. Хотя у меня уже есть большой опыт в электротехнике, с хорошим знанием схемотехники и прочего, если заметите неточности или улучшения — не стесняйтесь, указывайте в комментариях, буду рад конструктивной критике!
Получилась миниатюрная игра на реакцию для двух игроков на базе ATmega328P. Устройство питается от одной батарейки CR2032 (3 В), работает на внутреннем RC-генераторе 8 МГц и не требует внешнего кварца или стабилизатора напряжения. Проект доступен на GitHub.
В этой статье я разберу механику игры, выбор компонентов, разработку прошивки (с кодом), прототипирование, проектирование PCB и сборку. Давайте разберёмся по шагам.

Правила игры
Игра предназначена для двух игроков. У каждого — своя кнопка и индикаторный светодиод. Центральный светодиод сигнализирует о старте раунда.
Подготовка: Центральный LED мигает три раза коротко — сигнал готовности.
Задержка: Случайная пауза от 1 до 5 секунд (генерируется с помощью
random()на основе аналогового шума).Старт: Загорается центральный LED — игроки должны как можно быстрее нажать свою кнопку. Первый, кто успел, получает очко; его индикатор загорается на 1 секунду.
Анти-чит: Если во время ожидания игрок нажимает кнопку более двух раз, он блокируется на текущий раунд (чтобы избежать "спама").
Продолжительность раунда: 5 секунд на реакцию после сигнала.
Матч: Игра идёт до 3 очков. Победа отмечается пятью быстрыми миганиями индикатора победителя.
Сброс: После матча счёт автоматически сбрасыва��тся, и игра готова к новому раунду.
Механика простая — требует хорошей реакции и внимания. В версии 2.0 (в разработке) добавлены по три LED на игрока для визуализации счёта (загораются последовательно и остаются гореть до конца матча).

Выбор компонентов
Я стремился к минимализму: низкое потребление энергии, компактность и дешевизна. Питание от CR2032 (3 В) идеально подходит — ATmega328P стабильно работает на этой напруге с внутренним тактированием 8 МГц (без внешнего кварца, чтобы сэкономить место и ток).
Компоненты для версии 1.0:
ATmega328P — 1 шт.
Тактовые кнопки 6×6 мм — 2 шт.
Светодиоды 0805 — 3 шт.
Резисторы 330 Ом (для ограничения тока LED) — 3 шт.
Резистор 10 кОм (pull-up для кнопок или сброса) — 1 шт.
Конденсатор 1 мкФ (для фильтрации питания) — 1 шт.
Держатель батарейки CR2032 — 1 шт.
Миниатюрный выключатель питания — 1 шт. (опционально, для удобства).
Стоимость комплекта — около 350–450 рублей. Для версии 2.0 добавляются дополнительные LED (по 3 на игрока) и резисторы (всего 7 шт. 330 Ом).
В схеме использованы минимальные внешние компоненты: нет регуляторов напряжения, нет внешнего reset'а (используется внутренний pull-up). Кнопки подключены с debounce в коде.

Шаг 1: Разработка прошивки и программирование
Прошивка написана в Arduino IDE на C++ (используются только базовые функции, без библиотек). Это позволило быстро прототипировать логику, а затем скомпилировать в чистый HEX для "голого" AVR.
Ключевые особенности кода:
Рандомизация задержки:
random(1000, 5000)с сидом от аналогового пина.Debounce кнопок: простая задержка в 20 мс.
Анти-чит: счётчик ложных нажатий.
Энергосбережение: использование
sleep_mode()в будущем (в v1.0 не реализовано полностью).Fuse-биты: Low = 0xE2 (внутренний 8 МГц, без делителя).
Полный код для v1.0 (из GitHub: /src/v1/reaction_game_v1.ino):
// reaction_game_v1.ino #define LED_CENTER 13 // Центральный LED (PB5) #define LED_P1 12 // LED Player 1 (PB4) #define LED_P2 11 // LED Player 2 (PB3) #define BTN_P1 2 // Кнопка Player 1 (PD2) #define BTN_P2 3 // Кнопка Player 2 (PD3) int scoreP1 = 0; int scoreP2 = 0; int falsePressP1 = 0; int falsePressP2 = 0; bool blockedP1 = false; bool blockedP2 = false; void setup() { pinMode(LED_CENTER, OUTPUT); pinMode(LED_P1, OUTPUT); pinMode(LED_P2, OUTPUT); pinMode(BTN_P1, INPUT_PULLUP); pinMode(BTN_P2, INPUT_PULLUP); randomSeed(analogRead(0)); // Сид для рандома } void loop() { resetRound(); // Сброс раунда // Сигнал готовности: 3 мигания for (int i = 0; i < 3; i++) { digitalWrite(LED_CENTER, HIGH); delay(200); digitalWrite(LED_CENTER, LOW); delay(200); } // Случайная задержка delay(random(1000, 5000)); // Старт: зажигаем центр digitalWrite(LED_CENTER, HIGH); unsigned long startTime = millis(); while (millis() - startTime < 5000) { // 5 сек на реакцию checkFalsePresses(); // Проверка анти-чита if (!blockedP1 && digitalRead(BTN_P1) == LOW) { scoreP1++; digitalWrite(LED_P1, HIGH); delay(1000); digitalWrite(LED_P1, LOW); checkWin(); break; } if (!blockedP2 && digitalRead(BTN_P2) == LOW) { scoreP2++; digitalWrite(LED_P2, HIGH); delay(1000); digitalWrite(LED_P2, LOW); checkWin(); break; } delay(20); // Debounce } digitalWrite(LED_CENTER, LOW); } void resetRound() { falsePressP1 = 0; falsePressP2 = 0; blockedP1 = false; blockedP2 = false; } void checkFalsePresses() { if (digitalRead(BTN_P1) == LOW) { falsePressP1++; if (falsePressP1 > 2) blockedP1 = true; delay(20); } if (digitalRead(BTN_P2) == LOW) { falsePressP2++; if (falsePressP2 > 2) blockedP2 = true; delay(20); } } void checkWin() { if (scoreP1 >= 3) { for (int i = 0; i < 5; i++) { digitalWrite(LED_P1, HIGH); delay(100); digitalWrite(LED_P1, LOW); delay(100); } scoreP1 = 0; scoreP2 = 0; } else if (scoreP2 >= 3) { for (int i = 0; i < 5; i++) { digitalWrite(LED_P2, HIGH); delay(100); digitalWrite(LED_P2, LOW); delay(100); } scoreP1 = 0; scoreP2 = 0; } }
Процесс прошивки:
Скомпилировать в Arduino IDE → получить .hex.
Использовать программатор T48 .
Записать HEX и fuse-биты.

Шаг 2: Прототипирование на макетной плате
С прошитым чипом собрал схему на breadboard: ATmega в панельке, кнопки и LED по пинам, питание от CR2032 или лабораторного БП (3 В).
Тестировал:
Стабильность на 3 В (ток в idle ~1 мА).
Рандомизацию (без повторяющихся паттернов).
Анти-чит и debounce (чтобы избежать ложных срабатываний).
После отладки — переход к PCB.

Шаг 3: Проектирование платы в KiCad
Первый опыт полноценного дизайна в KiCad. Шаги:
Eeschema: Нарисовал схему (простая: MCU + LED + кнопки + пассивка).
Pcbnew: Разводка трасс (2 слоя, минимальные зазоры 0.25 мм). Учитывал компактность.
3D-viewer: Визуализация для проверки (см. рендер на GitHub: images/v1/3D Model.png).
Генерация Gerber-файлов.
Схема (из GitHub: images/v1/Schematic.png):
Шаг 4: Заказ плат и сборка
Gerber загрузил на PCBWay: 2 слоя, чёрная маска, HASL, 1.6 мм, 5 ш��. Стоимость с доставкой ~2160 руб. (пришли через 2,5 месяца).

Пайка: Ручная, SMD .

Первый опыт — не идеально, но плата заработала почти с первого раза.

Итог и планы
Проект дал опыт полного цикла: от идеи до готового устройства. Узнал нюансы AVR, KiCad, пайки SMD. Теперь увереннее в embedded.
В v2.0: Три LED на игрока для счёта, улучшенная шелкография. Есть один нюанс, который я не исправил : неправильное расположение кнопок на PCB — футпринт оказался перевернутым.
Если статья полезна — лайкните, подпишитесь или оставьте комментарий. Вопросы по коду или схеме — в issues репозитория. Удачи в ваших проектах! 🚀
