DIY LED-рулетка — собираем одноигровой аркадный автомат на Arduino Nano
Компоненты и материалы
| Светодиоды (общие) | 6 красных, 2 жёлтых, 1 зелёный | ×9 |
| Тактильная кнопка 12 мм (SparkFun) | ×1 | |
| Arduino Nano R3 | ×1 | |
| Женский заголовок 8 позиций 1 ряд (0.1") | ×1 | |
| DC Barrel Jack (разъем питания) | ×1 |
Необходимые инструменты и станки
- CNC-фрезер
Приложения и онлайн-сервисы
- Arduino IDE
О проекте
Видео
Обзор
Давно хотел сделать простую, но веселую игру для одного игрока. Она очень проста — нужен только один Arduino Nano. Это LED-рулетка. Цель — остановить свет на зелёном LED, избегая красных и жёлтых. Играть и делать легко.

Шаг 1
Сначала спроектировал устройство в Fusion 360. Передняя панель: 9 LED (6 красных, 2 жёлтых, 1 зелёный) и место для тактовой кнопки снизу. Детали вырезал на своём CNC-станке Millright.



Шаг 2
Игровая логика: свет «бегает» туда-сюда между краями и останавливается при нажатии кнопки. Для мгновенной реакции использовано прерывание. Каждый LED соответствует индексу в массиве, который циклически перебирается. Текущий индекс LED хранится в переменной. Есть задержка между шагами — это сложность. При включении игрок выбирает сложность, нажимая кнопку для уменьшения задержки. После попадания на зелёный LED можно дважды кликнуть, чтобы зафиксировать победу.
Шаг 3

Наждачной бумагой дал приятную фактуру и скругления фанерным деталям. Собрал на горячем клее.
Заключение

Теперь когда захочется поиграть в простую игру — в дороге или просто отдохнуть от экрана — это устройство даёт отличный передышку. Можно сделать многопользовательским: каждый LED, кроме зелёного, даёт определённые очки, выигрывает тот, кто набрал меньше очков.
Код
Код (C/C++)
/* Используйте пины 2-10
Библиотека TTBOUNCE: https://github.com/TOLDOTECHNIK/TTBOUNCE */
#include <TTBOUNCE.h>
int delay_time = 0;
const uint8_t led_array[9] = {4,3,5,6,7,8,9,10,11};
const uint8_t button = 2;
uint8_t difficulty = 0;
uint8_t current_led = 0;
bool dir_flag = true; // true — вправо, false — влево
bool game_ended = false;
bool is_win = false;
bool is_finished_selecting = false;
TTBOUNCE b = TTBOUNCE(button);
void doubleClick(){
Serial.println("double click");
is_finished_selecting = true;
delay_time = floor(500/(difficulty+1)); // Формула: задержка (мс) = 500 / (сложность + 1)
Serial.println("difficulty: " + String(delay_time));
sweep();
}
void click(){
Serial.print("Click | ");
digitalWrite(led_array[difficulty], LOW);
difficulty++;
if(difficulty > 8){ difficulty = 0; }
digitalWrite(led_array[difficulty], HIGH);
Serial.println("Difficulty is: " + String(difficulty));
delay(100);
}
void setup() {
Serial.begin(9600);
b.attachDoubleClick(doubleClick);
b.attachClick(click);
b.setActiveLow();
b.enablePullup();
for(int i=0; i<9; i++){ pinMode(led_array[i], OUTPUT); }
sweep();
pulse();
difficulty = 0;
digitalWrite(led_array[difficulty], HIGH);
while(!is_finished_selecting){ b.update(); }
b.update();
pinMode(button, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(button), button_pressed, FALLING);
delay(1000);
}
void loop() {
if(game_ended == false){
move_led();
delay(delay_time);
} else if(game_ended){
Serial.println(game_ended);
Serial.println("Game over");
if(is_win){
Serial.println("you won");
for(int i=0; i<5; i++){ pulse(); delay(100); }
}
sweep();
game_ended = false;
is_win = false;
delay(2000);
}
}
void move_led() {
digitalWrite(led_array[current_led], LOW);
if(current_led == 8){ dir_flag = false; current_led -= 1; }
else if(current_led == 0){ dir_flag = true; current_led += 1; }
else if(dir_flag){ current_led += 1; }
else if(!dir_flag){ current_led -= 1; }
digitalWrite(led_array[current_led], HIGH);
}
void pulse(){
for(int i=0; i<9; i++){ digitalWrite(led_array[i], HIGH); }
delay(100);
for(int i=0; i<9; i++){ digitalWrite(led_array[i], LOW); }
}
void sweep(){
for(int i=0; i<9; i++){ digitalWrite(led_array[i], HIGH); delay(50); digitalWrite(led_array[i], LOW); }
for(int i=8; i>=0; i--){ digitalWrite(led_array[i], HIGH); delay(50); digitalWrite(led_array[i], LOW); }
}
void button_pressed(){
Serial.println("Button pressed on LED: " + String(current_led));
game_ended = true;
if(current_led == 4){ is_win = true; }
else if(current_led != 4){ is_win = false; }
current_led = 0;
delay(500);
}
Схемы

Производственный процесс
- Создание игры в реальном времени на Arduino Nano с гироскопом MPU-6050 и OLED-дисплеем
- Цифровые кости на Arduino: генератор случайных чисел с LCD-дисплеем и кнопкой
- Создание рулетки на 37 светодиодов с Arduino Nano
- DIY USB-геймпад на Arduino: собственный высокопроизводительный контроллер
- Tetris на Arduino Nano: самостоятельная сборка 16×8 LED-матрицы на 74HC595
- Управление светодиодом по Bluetooth с Arduino: простой DIY-гид
- Пошаговое руководство: сборка умного четырёхногого робота на Arduino
- Pixel Chaser: игра на один тап с NeoPixel Ring и Arduino Nano
- Бесшовное управление яркостью светодиодов с помощью Bolt IoT и Arduino UNO
- Arduino Flip Clock на матрице 8×8 LED — DIY проект реального времени