Главная » Arduino
Призовой фонд
на октябрь 2021 г.
1. Рюкзак Mean Well
Компэл
2. Инвертор авто Mean Well 150 Ватт
Компэл
3. Термос MeanWell
Компэл
4. 100 руб.
От пользователей

Игрушка на Arduino: Саймон сказал

Хотите чем-либо занять ребёнка? Машинки и куклы надоели, хочется что-нибудь по-веселее? Предлагаю сделать простую электронную игрушку своими руками. В магазинах есть интересная игра под названием: "Саймон сказал":

Суть игры заключается в том, чтобы игрок повторил код, который показал компьютер. Нечто подобное мы и будем собирать сегодня сами.

Для начала разберёмся с основными частями проекта:

  • 4 кнопки и 4 светодиода - это основа. Посредством светодиодов компьютер будет показывать код, а с помощью кнопок игрок будет его повторять.
  • Динамик будет озвучивать нажатие на кнопки и включение лампочек.
  • Семисегментный индикатор с драйвером 74HC595. Будет отображать текущий уровень сложности.
  • Фоторезистор. Для генератора случайных чисел. (Позже объясню).

Подключаем к Arduino по такой схеме:

  • Светодиоды подключены к 8, 6, 4, 2 выходам Arduino через резисторы по 220 Ом (номинал можно изменить от 150 до 330 Ом);
  • Кнопки к 9, 7, 5, 3 выходам со стягивающими резисторами 10 кОм (номинал не важен, важно его наличие);
  • Динамик(Я взял пассивный) подключен напрямую к 10 пину (поддерживает ШИМ);
  • Контакты семисегмента (через резистор) идут к выходам регистра.
  • Сам регистр подключен к 13-му, 12-му и 11-му контакту (такт, данные и защёлка); Подробнее в этой статье.
  • Ну, и фоторезистор к аналоговому входу 1;

Я всё сделал на Breadboard. Получилось так:

В дальнейшем планирую сделать печатную плату, добавить питание от USB и поместить в какой-либо корпус. Плату уже нарисовал (скачать можно внизу). Там 2 платы. 1-я - это верхняя(лицевая) часть с кнопками, светодиодами, индикатором и. т. д.. А 2-я (нижняя) - это микроконтроллер с обвязкой (вместо неё можно использовать Arduino);

Теперь о коде: (Скачать код полностью можно внизу по ссылке)

В первую очередь пишем глобальные переменные:

#define CLOCK 13
#define DATA 12
#define LATCH 11

- это выходы регистра;

#define buzzer 10
const int leds[4] = {8, 6, 4, 2};
const int buttons[4] = {9, 7, 5, 3};

- выходы динамика (пищалки), светодиодов и входы кнопок.

const int notes[4] = {262, 330, 392, 523};

- а в это массиве хранятся ноты, которые будут проигрываться при нажатии кнопок. При желании их можно сделать одинаковыми. Я их брал из файла pitches.h. Откройте пример Digital > toneMelody. К нему прикреплён это файл:

В setup-е назначаем пины регистра, динамика и светодиодов выходами, а кнопки входами; ставим высокий уровень на защёлку.

pinMode(CLOCK, OUTPUT);
pinMode(DATA, OUTPUT);
pinMode(LATCH, OUTPUT);
pinMode(buzzer, OUTPUT);
for(int i=0; i<4; i++)
  pinMode(leds[i], OUTPUT),
  pinMode(buttons[i], INPUT);

digitalWrite(LATCH, HIGH);

Теперь разберём функции:

  • для семисегмента я сначала написал 2 функции. 1-я будет выводить на него цифры (от 0 до 9. 10 - это 9 с точкой):
void segWrite(int number){
  byte numbers[11] = {0b11111100,0b01100000,0b11011010,
    0b11110010,0b01100110,0b10110110,0b10111110,
    0b11100000,0b11111110,0b11110110,0b11110111};
  digitalWrite(LATCH, LOW);
  shiftOut(DATA, CLOCK, LSBFIRST, numbers[number]);
  digitalWrite(LATCH, HIGH);
}

А 2-я будет выключать индикатор:

void segOff(){
  digitalWrite(LATCH, LOW);
  shiftOut(DATA, CLOCK, LSBFIRST, 0);
  digitalWrite(LATCH, HIGH);
}
  • Потом решил добавить 3-ю, которая будет показывать небольшую анимацию перед началом игры:
void animation(){
  byte add = 1;
  byte value = 0;
  for(int i=0; i<6; i++){
    value+=add;
    digitalWrite(LATCH, LOW);
    shiftOut(DATA, CLOCK, MSBFIRST, value);
    digitalWrite(LATCH, HIGH);
    add*=2;
    delay(100);
  }
}
  • Следующая называется showled. Она будет показывать код игроку:
void showled(int count){
  tone(buzzer, notes[count]);
  digitalWrite(leds[count], HIGH);
  delay(300);
  digitalWrite(leds[count], LOW);
  noTone(buzzer);
  delay(300);
}
  • Следующие 2 функции противоположны друг-другу. Одна будет исполнятся, когда игрок выиграл:
void soundwin(){
  //262, 294, 330, 392; 330, 392;
  tone(buzzer, 262);
  digitalWrite(leds[0], HIGH);
  delay(100);
  tone(buzzer, 294);
  digitalWrite(leds[1], HIGH);
  delay(100);
  tone(buzzer, 330);
  digitalWrite(leds[2], HIGH);
  delay(100);
  tone(buzzer, 392);
  digitalWrite(leds[3], HIGH);
  delay(100);
  noTone(buzzer);
  for(int i=0; i<4; i++) digitalWrite(leds[i], LOW);
  delay(100);
  tone(buzzer, 330);
  delay(100);
  tone(buzzer, 392);
  for(int i=0; i<4; i++) digitalWrite(leds[i], HIGH);
  delay(500);
  noTone(buzzer);
  for(int i=0; i<4; i++) digitalWrite(leds[i], LOW);
}

(ноты брал из того же файла);

Другая - когда проиграл:

void soundlose(){
  tone(buzzer, 1480);
  for(int i=0; i<4; i++) digitalWrite(leds[i], HIGH);
  delay(350);
  for(int i=0; i<4; i++) digitalWrite(leds[i], LOW);
  tone(buzzer, 1047);
  delay(350);
  tone(buzzer, 1480);
  for(int i=0; i<4; i++) digitalWrite(leds[i], HIGH);
  delay(500);
  noTone(buzzer);
  for(int i=0; i<4; i++) digitalWrite(leds[i], LOW);
}
  • Функции для работы с кнопками: button() - будет ожидать нажатия любой кнопки и возвращать её номер.
int button(){
  int pressed = -1;
  do{
    for(int i=0; i<4; i++){
      if(digitalRead(buttons[i])==HIGH){
        pressed = i;
        break;
      }
    }
  } while(pressed<0);
  return pressed;
}

readButton() - а эта будет проверять, правильная ли кнопка нажата и, соответственно, возвращать: да или нет.

boolean readbutton(int count){
  int pressed = button();
  delay(5);
  tone(buzzer, notes[pressed]);
  digitalWrite(leds[pressed], HIGH);
  delay(100);
  while(digitalRead(buttons[pressed])!=LOW);
  noTone(buzzer);
  digitalWrite(leds[pressed], LOW);
  delay(100);
  if(pressed==count) return true;
  else return false;
}

(И, кстати, данная функция не будет ничего возвращать, пока человек не отпустит кнопку. Таким образом, последнее состояние кнопки будет всегда LOW, потому для борьбы с дребезгом мы ограничимся только задержкой на 5 мс).

  • И последняя функция (самая интересная) будет делать случайные числа максимально случайными :)
void setRandom(){
  int analog = analogRead(0);
  int light = analogRead(1);
  unsigned long time = millis();
  unsigned long results = analog * light * time;
  do results = results / 10;
  while(results>=1000);
  results+=random(0, 300);
  randomSeed(results);
}

Всё что она делает - это формирует число, зависящее от освещённости (для этого и нужен фоторезистор), показаний с пустого аналог. входа и времени. А потом отправляет его в randomSeed();

Теперь сам цикл. (Для меня это было самым сложным, т. к. пришлось использовать метки)

- Вначале стоят 4 переменные, отвечающие за кол-во жизней, длину кода, текущий уровень и сам код.

int lives = 2;
int codelength = 10;
int level = 0;
int code[codelength];

(обращу ваше внимание, что Arduino будет показывать игроку сначала одну цифру кода, потом первую + вторую, + 3-ю, 4-ю и. т. д. Поэтому весь код надо разбивать на части, а лучше сразу сделать массив переменных, как это сделал я);

- Затем показываем анимацию и ожидаем нажатия любой кнопки для начала игры. Ну, и чуть-чуть ждём:

  animation();
  button();
  delay(1000);

- Кода игра началась, сразу заполняем ячейки кода random-ом:

for(int i=0; i<codelength; i++){
    setRandom();
    code[i] = random(4);
  }

- Вся игра будет крутиться в цикле, пока игрок не пройдёт все уровни, либо пока жизни не закончатся. Поэтому заводим цикл for():

for(level=0; level < codelength; level++){

- В цикле ставим метку show, отображаем на индикаторе текущий уровень и проверяем, не закончились ли жизни:

show:
segWrite(level+1);
if(lives==0) break;

- Потом крутим ячейки нашего кода и показываем их игроку (кол-во таких ячеек должно быть равно текущему уровню):

 //показываем код(одно за другим)
    for(int count=0; count<=level; count++) showled(code[count]);

- Затем заводим ещё один цикл for(), в котором выводим на сегмент количество кнопок, которое ещё необходимо нажать, и проверяем нажатие кнопок. Если нажата не та кнопка, то играем печальную мелодию о проигрыше и переходим в начало первого цикла (заново показываем код):

   //проверяем код(одно за другим)
    for(int count=0; count<=level; count++){
      segWrite(level+1-count);
      // если правильно - идём дальше
      // если неправильно, уменьшаем жизни
      if(!readbutton(code[count])){
        segOff();
        soundlose();
        delay(1000);
        lives--;
        goto show;
      }
    }

- И, если данный цикл пройден, значит игрок нажал всё правильно. Поздравляем его и переходим на следующий уровень:

segWrite(0);
delay(100);
soundwin();
delay(1000);

Надеюсь, я понятно объяснил. Если есть вопросы - пишите в комментариях. Буду рад ответить.

Список радиоэлементов

Обозначение Тип Номинал Количество ПримечаниеМагазинМой блокнот
Arduino или ATmega8 с обвязкой
МК AVR 8-бит
ATmega8
1 Поиск в магазине ОтронВ блокнот
Кварцевый резонатор16 МГц1 Поиск в магазине ОтронВ блокнот
Конденсатор22 пФ2 Поиск в магазине ОтронВ блокнот
Конденсатор100 мФ1 Поиск в магазине ОтронВ блокнот
Светодиод1 ONПоиск в магазине ОтронВ блокнот
Резистор
220 Ом
1 Поиск в магазине ОтронВ блокнот
Тактовая кнопка1 RESETПоиск в магазине ОтронВ блокнот
Резистор1 - 10 КОм1 Поиск в магазине ОтронВ блокнот
РазъёмUSB1 Поиск в магазине ОтронВ блокнот
Периферия
IC1 Сдвиговый регистр
CD74HC595
1 Поиск в магазине ОтронВ блокнот
SEG1 Семисегмент1 Поиск в магазине ОтронВ блокнот
LED1-LED4 Светодиод4 У меня 2 красных и 2 жёлтыхПоиск в магазине ОтронВ блокнот
R1-8, R13-16 Резистор
220 Ом
12 Поиск в магазине ОтронВ блокнот
R9-12 Резистор1 - 10 КОм4 Поиск в магазине ОтронВ блокнот
S1-S4 Тактовая кнопка4 Поиск в магазине ОтронВ блокнот
SP1 Динамик (пищалка)активный/пассивный1 Поиск в магазине ОтронВ блокнот
PH1 Фоторезистор1 Поиск в магазине ОтронВ блокнот
Добавить все

Скачать список элементов (PDF)

Прикрепленные файлы:

Теги:

Опубликована: Изменена: 17.11.2016 0 3
Я собрал 1 1
x

Оценить статью

  • Техническая грамотность
  • Актуальность материала
  • Изложение материала
  • Полезность устройства
  • Повторяемость устройства
  • Орфография
0

Средний балл статьи: 4.8 Проголосовало: 1 чел.

Комментарии (3) | Я собрал (0) | Подписаться

+1

[Автор]
vmik7 #
Игра очень простая, но играться довольно весело. (Брат до сих пор рубится)
Для начинающих могу выложить подробную версию схемы на бредборде.
Ответить
0
Demaniyak #
Я хотел бы увидеть подробную схемку!
Ответить
0
Chik #
Дай пж подробную схему, очень нужна
Ответить
Добавить комментарий
Имя:
E-mail:
не публикуется
Текст:
Защита от спама:
В чем измеряется электрическая мощность?
Файлы:
 
Для выбора нескольких файлов использйте CTRL

Модуль измерения тока на ACS712 (30А)
Модуль измерения тока на ACS712 (30А)
Лазерный модуль 650нм 5мВт Конструктор регулируемого преобразователя напряжения LM317
вверх