Кратко и по делу: план, компоненты, логика, пример кода (Arduino). Числа и параметры отмечены в KaTeX. 1) Идея и выбор механики - Тип цели: электронная (луч/фотоэлемент), контактная (микропереключатель), магнитная (датчик Холла) или визуальная (камерный распознаватель). Для ярмарки обычно берут безопасные пистолеты (нерф/воздушные шарики) и простые датчики прерывания луча. - Управление: микроконтроллер (Arduino Nano/Uno) для простоты или Raspberry Pi для камер/сложной логики. 2) Основные компоненты - Контроллер: Arduino Uno/Nano (питание 5V5\text{V}5V). - Датчики: инфракрасная барьера (break-beam) или фототранзистор; микропереключатели для механических целей. - Актуаторы: сервопривод для сброса/подъёма цели, светодиоды для индикации, зуммер. - Вывод: LCD 16×216\times216×2 или OLED для счета и таймера. - Источник питания: 5V5\text{V}5V (для Arduino/серв). Для соленоидов — отдельный блок, например 12V12\text{V}12V. - Кнопки: старт/рестарт, выбор режима, защитный выключатель. - Корпус/безопасность: экраны, фиксаторы пуль/стрел, предупреждающие таблички. 3) Логика игры (архитектура) - Режимы: свободный счет, игра на время (например 303030 с), жизнь/патроны (например 101010 выстрелов). - Состояния: IDLE → RUNNING → PAUSED → END. - Цели: каждая цель в состоянии {UP, DOWN, HIT_COOLDOWN}. После попадания цель уходит в DOWN и поднимается через таймер. - Дебаунс датчика: 505050 мс. - Счет: +??? очков за каждую цель (можно разные веса). 4) Алгоритм обработки удара (упрощённо) - При срабатывании датчика: проверить время от последнего срабатывания (дебаунс). - Если цель активна (UP): пометить HIT, добавить очки, зафиксировать время, опустить цель, обновить дисплей и звук. - Через время ресета (например 222 с) поднять цель. 5) Пример схемы подключения (одна цель) - Датчик break-beam: управление цифровому входу Arduino, подтяжка через внутренний pull-up. - Серво на PWM-пин. - Светодиод и зуммер на цифровые выходы (через резистор/транзистор). - Кнопка старт на отдельный вход (с подтяжкой). 6) Пример кода (Arduino) — одна цель с break-beam, серво, дисплеем и таймером (комментированно, минимально; в реале добавьте защиту питания и проверки). ```cpp #include
const int sensorPin = 2; // прерывание const int servoPin = 9; const int ledPin = 13; const int buzzerPin = 8; const int startButton = 3; volatile bool hitFlag = false; unsigned long lastHitTime = 0; const unsigned long debounceMs = 50; // текст: дебаунс = 505050 мс const unsigned long resetMs = 2000; // текст: ресет цели = 200020002000 мс = 222 с Servo targetServo; int score = 0; bool gameRunning = false; unsigned long gameStart = 0; const unsigned long gameDuration = 30000; // текст: игра = 300003000030000 мс = 303030 с void IRAM_ATTR sensorISR() { if (millis() - lastHitTime > debounceMs) { hitFlag = true; lastHitTime = millis(); } } void setup(){ pinMode(sensorPin, INPUT_PULLUP); pinMode(ledPin, OUTPUT); pinMode(buzzerPin, OUTPUT); pinMode(startButton, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(sensorPin), sensorISR, FALLING); targetServo.attach(servoPin); targetServo.write(0); // позиция "вверх" // init display if used... } void loop(){ if (!gameRunning) { if (digitalRead(startButton) == LOW) { // старт игры score = 0; gameRunning = true; gameStart = millis(); } else { return; } } // окончание игры по времени if (millis() - gameStart >= gameDuration) { gameRunning = false; // показать счет, звук tone(buzzerPin, 1000, 500); return; } if (hitFlag) { hitFlag = false; // обработка попадания score += 1; // можно менять вес digitalWrite(ledPin, HIGH); tone(buzzerPin, 2000, 100); targetServo.write(90); // опустить цель unsigned long hitMoment = millis(); // ждём ресета цели в неблокирующем стиле: while (millis() - hitMoment < resetMs) { // можно обновлять дисплей таймер/счет } targetServo.write(0); // поднять цель digitalWrite(ledPin, LOW); } // обновление дисплея: показываем оставшееся время и счет } ``` 7) Советы и доработки - Мультицели: используйте массивы датчиков/серво и присваивайте разный вес. - Используйте прерывания для датчиков (быстрое срабатывание) и millis() для таймеров (не delay()). - Безопасность: откалибруйте датчики, поставьте защиту от помех, изолируйте питание серво/соленоидов. - Логи и режимы: добавьте сохранение рекордов (EEPROM) и выбор сложности. - Для фотокамер/распознавания мишеней используйте Raspberry Pi + OpenCV (сложнее, но визуально круче). Если нужно, пришлите: сколько целей (111, 333, 555), какие датчики (break-beam/микровыключатель/камера), какой контроллер — пришлю конкретную схему и готовый скетч.
1) Идея и выбор механики
- Тип цели: электронная (луч/фотоэлемент), контактная (микропереключатель), магнитная (датчик Холла) или визуальная (камерный распознаватель). Для ярмарки обычно берут безопасные пистолеты (нерф/воздушные шарики) и простые датчики прерывания луча.
- Управление: микроконтроллер (Arduino Nano/Uno) для простоты или Raspberry Pi для камер/сложной логики.
2) Основные компоненты
- Контроллер: Arduino Uno/Nano (питание 5V5\text{V}5V).
- Датчики: инфракрасная барьера (break-beam) или фототранзистор; микропереключатели для механических целей.
- Актуаторы: сервопривод для сброса/подъёма цели, светодиоды для индикации, зуммер.
- Вывод: LCD 16×216\times216×2 или OLED для счета и таймера.
- Источник питания: 5V5\text{V}5V (для Arduino/серв). Для соленоидов — отдельный блок, например 12V12\text{V}12V.
- Кнопки: старт/рестарт, выбор режима, защитный выключатель.
- Корпус/безопасность: экраны, фиксаторы пуль/стрел, предупреждающие таблички.
3) Логика игры (архитектура)
- Режимы: свободный счет, игра на время (например 303030 с), жизнь/патроны (например 101010 выстрелов).
- Состояния: IDLE → RUNNING → PAUSED → END.
- Цели: каждая цель в состоянии {UP, DOWN, HIT_COOLDOWN}. После попадания цель уходит в DOWN и поднимается через таймер.
- Дебаунс датчика: 505050 мс.
- Счет: +??? очков за каждую цель (можно разные веса).
4) Алгоритм обработки удара (упрощённо)
- При срабатывании датчика: проверить время от последнего срабатывания (дебаунс).
- Если цель активна (UP): пометить HIT, добавить очки, зафиксировать время, опустить цель, обновить дисплей и звук.
- Через время ресета (например 222 с) поднять цель.
5) Пример схемы подключения (одна цель)
- Датчик break-beam: управление цифровому входу Arduino, подтяжка через внутренний pull-up.
- Серво на PWM-пин.
- Светодиод и зуммер на цифровые выходы (через резистор/транзистор).
- Кнопка старт на отдельный вход (с подтяжкой).
6) Пример кода (Arduino) — одна цель с break-beam, серво, дисплеем и таймером
(комментированно, минимально; в реале добавьте защиту питания и проверки).
```cpp
#include
const int sensorPin = 2; // прерывание
const int servoPin = 9;
const int ledPin = 13;
const int buzzerPin = 8;
const int startButton = 3;
volatile bool hitFlag = false;
unsigned long lastHitTime = 0;
const unsigned long debounceMs = 50; // текст: дебаунс = 505050 мс
const unsigned long resetMs = 2000; // текст: ресет цели = 200020002000 мс = 222 с
Servo targetServo;
int score = 0;
bool gameRunning = false;
unsigned long gameStart = 0;
const unsigned long gameDuration = 30000; // текст: игра = 300003000030000 мс = 303030 с
void IRAM_ATTR sensorISR() {
if (millis() - lastHitTime > debounceMs) {
hitFlag = true;
lastHitTime = millis();
}
}
void setup(){
pinMode(sensorPin, INPUT_PULLUP);
pinMode(ledPin, OUTPUT);
pinMode(buzzerPin, OUTPUT);
pinMode(startButton, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(sensorPin), sensorISR, FALLING);
targetServo.attach(servoPin);
targetServo.write(0); // позиция "вверх"
// init display if used...
}
void loop(){
if (!gameRunning) {
if (digitalRead(startButton) == LOW) {
// старт игры
score = 0;
gameRunning = true;
gameStart = millis();
} else {
return;
}
}
// окончание игры по времени
if (millis() - gameStart >= gameDuration) {
gameRunning = false;
// показать счет, звук
tone(buzzerPin, 1000, 500);
return;
}
if (hitFlag) {
hitFlag = false;
// обработка попадания
score += 1; // можно менять вес
digitalWrite(ledPin, HIGH);
tone(buzzerPin, 2000, 100);
targetServo.write(90); // опустить цель
unsigned long hitMoment = millis();
// ждём ресета цели в неблокирующем стиле:
while (millis() - hitMoment < resetMs) {
// можно обновлять дисплей таймер/счет
}
targetServo.write(0); // поднять цель
digitalWrite(ledPin, LOW);
}
// обновление дисплея: показываем оставшееся время и счет
}
```
7) Советы и доработки
- Мультицели: используйте массивы датчиков/серво и присваивайте разный вес.
- Используйте прерывания для датчиков (быстрое срабатывание) и millis() для таймеров (не delay()).
- Безопасность: откалибруйте датчики, поставьте защиту от помех, изолируйте питание серво/соленоидов.
- Логи и режимы: добавьте сохранение рекордов (EEPROM) и выбор сложности.
- Для фотокамер/распознавания мишеней используйте Raspberry Pi + OpenCV (сложнее, но визуально круче).
Если нужно, пришлите: сколько целей (111, 333, 555), какие датчики (break-beam/микровыключатель/камера), какой контроллер — пришлю конкретную схему и готовый скетч.