Саймон говорит - детская игра, популярная прежде всего в англоговорящих странах. В ней игроки должны выполнять приказы, которые отдает ведущий. Приказы начинаются со слов "Саймон говорит ...", как правило, это просты активные действия, например, "подпрыгни", "похлопай в ладоши" и т.п. Идея этой игры легла в основу электронной игрушки, весьма популярной в конце 1970-х и начала 1980-х годов. Задачей игрока было запомнить продемонстрированную ему последовательность вспышек и звуков и затем воспроизвести ее. Эта игрушка развивает зрительную и слуховую память, скорость реакции. Ее до сих пор можно найти в магазинах. Но, чем покупать, гораздо интереснее собрать такую игрушку самому. Этим мы сегодня и займемся.
Для сборки игры потребуются:
Собираем устройство по следующей схеме:
В классической игрушке использовались именно 4 кнопки и светодиода, но я при сборке своей решил отступить от этого правила и сократил их количество до трех, чтобы пятилетнему ребенку было попроще играть. В качестве корпуса можно использовать любую подходящую коробку или контейнер, мне, например, попалась под руку коробка от виртуального осциллографа. Для этого я проделал в ней отверстия для кнопок, светодиодов и выключателя. Светодиоды закрепил термоклеем, остальное отлично зафиксировалось штатными гайками. В итоге получилось вот что:
Когда устройство собрано остается только прошить Ардуино. Ниже приведен код, я снабдил его достаточным количеством комментариев. Думаю, кто захочет, сможет без труда в нем разобраться. Скачать данный скетч можно по ссылке.
И в заключение видео получившейся игрушки. Ребенку "коробочка" понравилась:)
Для сборки игры потребуются:
- Ардуино. Я использую Arduino Nano;
- 4 светодиода разных цветов;
- 4 кнопки;
- Динамик на 8 Ом. Можно обойтись и без него, но со звуком играть гораздо интереснее;
- Резисторы: 4 по 10 кОм для кнопок, 4 по 220 Ом для светодиодов и 1 резистор на 100 Ом для динамика;
- Ну и провода, чтобы всё это соединить.
Собираем устройство по следующей схеме:
В классической игрушке использовались именно 4 кнопки и светодиода, но я при сборке своей решил отступить от этого правила и сократил их количество до трех, чтобы пятилетнему ребенку было попроще играть. В качестве корпуса можно использовать любую подходящую коробку или контейнер, мне, например, попалась под руку коробка от виртуального осциллографа. Для этого я проделал в ней отверстия для кнопок, светодиодов и выключателя. Светодиоды закрепил термоклеем, остальное отлично зафиксировалось штатными гайками. В итоге получилось вот что:
Когда устройство собрано остается только прошить Ардуино. Ниже приведен код, я снабдил его достаточным количеством комментариев. Думаю, кто захочет, сможет без труда в нем разобраться. Скачать данный скетч можно по ссылке.
#define SequenceMaxLen 50 // Длина последовательности
#define ShowingTime 300 // Длительность отображения элемента последовательности (мс)
#define DelayBetweenLeds 200 // Задержка между отображением элементов (мс)
#define WaitingTime 10000 // Время ожидания ввода (мс)
#define RepeatRightSequence 1 // Нужно ли повторять правильную последовательность при проигрыше
byte Sequence[SequenceMaxLen]; // Последовательность включения светодиодов
byte CurrentLen; // Текущая длина последовательности
int CurrentIndex; // Номер обрабатываемого элемента последовательности
byte ButtonsNLeds[] = {2, 3, 4, 5}; // Номера выводов, к которым подключены кнопки и светодиоды
byte ButtonCount = sizeof(ButtonsNLeds) / sizeof(ButtonsNLeds[0]);
bool ButtonStillPressed;
enum eMode {mStartNewGame, mShowingSequence, mRepeatSequence, mWaitingForButtons};
eMode Mode; // Текущий режим: отображение последовательности/ожидание ввода
unsigned long tm; // Переменная для отслеживания временных интервалов
#define pin_Speaker 12 // Пин к которому подключен динамик
int Notes[] = {880, 988, 1047, 1175}; // Частоты нот для каждой из кнопок (A5, B5, C6, D6)
void SetPinMode(byte NewPinMode) {
for (byte i = 0; i < ButtonCount; i++)
pinMode(ButtonsNLeds[i], NewPinMode);
}
void Blink(int Count, int DelayTime) {
SetPinMode(OUTPUT);
for (byte t = 0; t < Count; t++) {
for (byte i = 0; i < ButtonCount; i++)
digitalWrite(ButtonsNLeds[i], 1);
delay(DelayTime);
for (byte i = 0; i < ButtonCount; i++)
digitalWrite(ButtonsNLeds[i], 0);
delay(DelayTime);
}
}
void Win() {
tone(pin_Speaker, 2637, 125);
delay(162);
tone(pin_Speaker, 2093, 500);
SetPinMode(OUTPUT);
for (byte t = 0; t < 5; t++) {
for (byte i = 0; i < ButtonCount; i++) {
digitalWrite(ButtonsNLeds[i], 1);
delay(50);
digitalWrite(ButtonsNLeds[i], 0);
delay(20);
}
}
}
void setup() {
Serial.begin(9600);
randomSeed(analogRead(0));
Mode = mStartNewGame;
}
void loop() {
switch (Mode) {
case mStartNewGame: { // Новая игра
Serial.println("Mode = mStartNewGame");
for (byte i = 0; i < SequenceMaxLen; i++) // Создаем последовательность
Sequence[i] = random(ButtonCount);
SetPinMode(OUTPUT);
Blink(3, 800);
delay(DelayBetweenLeds); // Пауза перед включением первого светодиода
Mode = mShowingSequence;
Serial.println("Mode = mShowingSequence");
CurrentIndex = -1;
CurrentLen = 1;
return;
}
case mRepeatSequence:
if (RepeatRightSequence == 0) {
Mode = mStartNewGame;
return;
}
case mShowingSequence: { // Показываем последовательность
if (CurrentIndex == -1) {
CurrentIndex = 0;
Serial.print("Sequence: ");
Serial.print(Sequence[CurrentIndex]);
digitalWrite(ButtonsNLeds[Sequence[0]], HIGH);
tone(pin_Speaker, Notes[Sequence[0]], ShowingTime);
tm = millis() + ShowingTime;
return;
}
if (millis() >= tm) {
digitalWrite(ButtonsNLeds[Sequence[CurrentIndex]], LOW); // Гасим светодиод
CurrentIndex++;
if (CurrentIndex < CurrentLen) { // Если показана еще не вся последовательность
delay(DelayBetweenLeds);
Serial.print(", ");
Serial.print(Sequence[CurrentIndex]);
digitalWrite(ButtonsNLeds[Sequence[CurrentIndex]], HIGH); // то включаем следующий светодиод
tone(pin_Speaker, Notes[Sequence[CurrentIndex]], ShowingTime);
tm = millis() + ShowingTime;
}
else {
Serial.println();
if (Mode == mRepeatSequence) {
Mode = mStartNewGame; // Начинаем новую игру
delay(1000);
}
else {
Mode = mWaitingForButtons; // Иначе переключаемся в режим ввода
Serial.println("Mode = mWaitingForButtons");
SetPinMode(INPUT);
CurrentIndex = 0;
tm = millis() + WaitingTime;
}
}
}
return;
}
case mWaitingForButtons: { // Ожидаем ввода последовательности
if (millis() > tm) { // Время вышло. Game over
tone(pin_Speaker, 110, 800);
Blink(10, 50);
Mode = mRepeatSequence; // Показываем правильную последовательность
CurrentIndex = -1;
return;
}
for (byte i = 0; i < ButtonCount; i++) {
if (digitalRead(ButtonsNLeds[i]) == HIGH) { // Если кнопка нажата
delay(50);
if (ButtonStillPressed) return; // Кнопка все еще нажата, прерываем обработку
ButtonStillPressed = 1;
Serial.print("Button pressed: ");
Serial.print(i);
tone(12, Notes[i], 300);
if (i == Sequence[CurrentIndex]) { // Нажата верная кнопка
Serial.println(" - Right!");
CurrentIndex++;
if (CurrentIndex < CurrentLen) // Если введена еще не вся последовательность
tm = millis() + WaitingTime; // то ожидаем следующую кнопку
else { // Иначе (введена вся последовательность)
delay(500);
if (CurrentLen == SequenceMaxLen) { // Конец игры
Win();
delay(500);
Mode = mStartNewGame; // Начинаем новую игру
return;
}
delay(800);
CurrentLen++; // увеличиваем ее длину
Mode = mShowingSequence; // и переключаем режим
SetPinMode(OUTPUT);
CurrentIndex = -1;
Serial.println("Mode = mShowingSequence");
return;
}
}
else { // Если нажата неверная кнопка
Serial.println(" - Wrong!");
tone(pin_Speaker, 110, 800);
SetPinMode(OUTPUT);
for (int t = 0; t < 10; t++) {
digitalWrite(ButtonsNLeds[i], HIGH);
delay(50);
digitalWrite(ButtonsNLeds[i], LOW);
delay(50);
}
Mode = mRepeatSequence; // Показываем правильную последовательность
CurrentIndex = -1;
Serial.println("Mode = mRepeatSequence");
return;
}
return;
}
}
ButtonStillPressed = 0;
return;
}
}
}
И в заключение видео получившейся игрушки. Ребенку "коробочка" понравилась:)
Здравствуйте, возникли вопросы по вашему проекту. горят первые два диода как надо , остальные два очень тускло и с случайной периодичностью мигают. в чем может быть проблема?
ОтветитьУдалитьДобрый день!
УдалитьСоединили все как на схеме или что-то меняли?
все по схеме. можно ли с вами связаться(почта,вк)?
УдалитьVladimirTsibrov@yandex.ru
Удалитьу меня точно такая-же проблема, можете помочь пожалуйста?
Удалитьпочта: danya134@yandex.ru
вы не могли бы фотографию схемы добавить,никак не грузит
ОтветитьУдалитьДобрый день!
УдалитьСсылка на схему: https://yadi.sk/i/lO_zrTZnSYcrmA
и внутренности коробки: https://yadi.sk/i/6yONcvaiMcBrPQ
Здравствуйте, очень понравился ваш проект, но вы не могли бы объяснить, как сделать все без макетной платы с пайкой,если вам не сложно, я лишь начинающий и хотел попробовать так
ОтветитьУдалитьДобрый вечер.
УдалитьМогу нарисовать электрическую принципиальную схему, с ней будет понятнее? А в чем сложность чтения схемы, сделанной в fritzing?
В сборке написана ардуино нано, а по факту на рисунке уно, извините уж за беспокойство, просто я собрал 2 проекта и все я паял без плат, так было бы более ясно, если вам не сложно конечно.
УдалитьИли нужно использовать уно, просто ни одна картинка на сайте не открывается у меня к союалению
Fritzing это отлично, просто насторожило uno и макетная плата,если бы без макетной и с нано была бы в zritzing я был ооооочень благодарен
УдалитьНано, уно, про мини - нет никакой разницы. В них используется один и тот же микроконтроллер.
УдалитьПроблему отображения картинок буду решать. Видимо, придется менять платформу...
Скажите пожалуйста ,я хочу подключить дисплей мэлт 8 на 2 ,когда пишешь lcd.begin..... и другое выдает ошибку
ОтветитьУдалитьА к чему вы подключаете дисплей? Вот к этому проекту и этому скетчу? Библиотеку в скетч добавили? Идущие с ней примеры пробовали?
УдалитьЭтот комментарий был удален автором.
ОтветитьУдалить