Реклама ⓘ
Главная » Arduino
Призовой фонд
на апрель 2024 г.
1. 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А)
МиниПК MK809V - 4 ядра, Android 4.4.2 Сатфайндер
вверх