Игра на развитии памяти "Simon" теперь реализована на Arduino с помощью Trema Set Shield и новых Trema-модулей кнопок со светодиодами.
Правила игры:
Вы должны повторить последовательность цветов, нажимая кнопки в той же последовательности, в которой загорались светодиоды. На 1 уровне зажжется на пол секунды один из трех светодиодов кнопки. После того как он потухнет, нужно нажать кнопку с соответствующим светодиодом. На 2 уровне, зажжется тот же светодиод, а потом еще один из трех, нужно нажать кнопку с соответствующим первым светодиодом, а потом кнопу с други загоревшимся светодиодом. На уровне три последовательно зажгутся три светодиода и т. д. Если вы нажмёте не на ту кнопку, ошибетесь в последовательности, то на 1 секунду зажгутся все светодиоды и игра начнется с 1 уровня.
Нам понадобится:
- Arduino Uno х 1шт.
- Trema Set Shield х 1шт.
- Trema OLED-дисплей 128x64 х 1шт.
- Trema-модуль кнопка со светодиодом, синяя х 1шт.
- Trema-модуль кнопка со светодиодом, красная х 1шт.
- Trema-модуль кнопка со светодиодом, зеленая х 1шт.
Для реализации проекта нам необходимо установить следующие библиотеки:
- iarduino_OLED - графическая библиотека для работы с Trema OLED дисплеями.
О том как устанавливать библиотеки, Вы можете ознакомиться на странице Wiki - Установка библиотек в Arduino IDE.
Схема подключения:
Перед подключением модулей, закрепите винтами нейлоновые стойки в отверстиях секций 3 и 4 Trema Set Shield.- Установите Trema Set Shield на Arduino Uno.
- Устанавливаем Trema-модуль синюю кнопку со светодиодом в 1 посадочную площадку. 
- Установите Trema OLED-дисплей 128x64 в 3 посадочную площадку, в верхнюю I2C колодку. 
- Устанавливаем Trema-модуль красную кнопку со светодиодом в 4 посадочную площадку. 
- Устанавливаем Trema-модуль зеленую кнопку со светодиодом в 5 посадочную площадку. 
- Полученный результат представлен на рисунке ниже. 
Код программы:
#include <iarduino_OLED.h>                                  // Подключаем библиотеку iarduino_OLED.
iarduino_OLED myOLED(0x3C);                                 // Объявляем объект myOLED, указывая адрес дисплея на шине I2C: 0x3C.
extern uint8_t MediumFont[];                                // Подключаем шрифт MediumFont.
                                                            //
const uint8_t pinLed[3] = {1,A2, 5};                        // Создаем массив констант с № входов к которым подключены светодиоды.
const uint8_t pinKey[3] = {A0,2,A3};                        // Создаем массив констант с № входов к которым подключены кнопки.
                                                            //
uint8_t task[99];                                           // Создаем массив заданий (последовательность цветов).
uint8_t level   = 0;                                        // Создаем переменную для хранения № текущего уровня.
uint8_t numKey  = 0;                                        // Создаем переменную для хранения № нажатой клавиши.
uint8_t sumKey  = 0;                                        // Создаем переменную для подсчета количества нажатий клавиш.
bool    start   = 1;                                        // Создаем флаг старта.
                                                            //
void setup()                                                //
{                                                           //
  for(int i=0; i<3; i++)                                    // В цикле конфигурируем выводы и включаем светодиоды.
  {                                                         //
    pinMode(pinLed[i],OUTPUT);                              // Переводим выводы pinLed в режим выхода.
    digitalWrite(pinLed[i],LOW);                            // Выключаем светодиоды.
    pinMode(pinKey[i],INPUT);                               // Переводим выводы pinKey в режим выхода.
    randomSeed(analogRead(A1));                             // Назначаем случайное число со входа A0, для генератора random().
  }                                                         //
  myOLED.begin();                                           // Инициируем работу с дисплеем.
  myOLED.setFont(MediumFont);                               // Указываем шрифт который требуется использовать для вывода цифр и текста.
}                                                           //
void loop()                                                 //
{                                                           //
  numKey = 3;                                               // Присваиваем переменой № нажатой клавиши число 3.
  for(int i=0; i<3; i++)                                    // В цикле фиксируем нажатие одной из трех клавиш.
  {                                                         //
    if(digitalRead(pinKey[i]))                              // Если нажата клавиша.
    {                                                       //
      numKey = i; sumKey++;                                 // Сохраняем номер нажатой клавиши, увеличиваем количество нажатий клавиши.
    }                                                       //
  }                                                         //
  if(numKey<3)                                              // Если номер нажатой клавиши меньше 3.
  {                                                         //
    digitalWrite(pinLed[numKey],1);                         // Включаем светодиод нажатой клавиши.
    while(digitalRead(pinKey[numKey])){delay(50);}          // Ждем пока не отпустят кнопку.
    digitalWrite(pinLed[numKey],0);                         // Выключаем светодиод нажатой клавиши.
    if(task[sumKey-1] != numKey){level = 0; start = 1;}     // Если ошибка, то переходим на 0 уровень.
    if(!start && sumKey>level){level++; start = 1;}         // Если нет ошибок, то увеличиваем уровень.
  }                                                         //
  myOLED.print(level, OLED_C, OLED_C);                      // Выводим уровень на экран.
  if(start)                                                 // Если начат новый уровень.
  {                                                         //
    start = sumKey = 0;                                     // Запрещаем начинать новый уровень и обнуляем переменную подсчета количества нажатий клавиш.
    task[level] = random(0,3);                              // Придумываем последний цвет от 0 до 2.
    if(level == 0)                                          // Если начат нулевой уровень.
    {                                                       //
      for(int i=0; i<3; i++){digitalWrite(pinLed[i],1);}    // Включаем все светодиоды.
      delay(1000);                                          // Задержка 1 с.
      for(int i=0; i<3; i++){digitalWrite(pinLed[i],0);}    // Выключаем все светодиоды.
    }                                                       //
    delay(500);                                             // Задержка 500 мс.
    for(int i=0; i<=level; i++)                             // В цикле выводим всю последовательность цветов.
    {                                                       //
      delay(500); digitalWrite(pinLed[task[i]],1);          // Включаем очередной светодиод.
      delay(500); digitalWrite(pinLed[task[i]],0);          // Выключаем очередной светодиод.
    }                                                       //
  }                                                         //
}                                                           //
Алгоритм работы:
В начале скетча (до кода setup) выполняются следующие действия:
- Подключаем графическую библиотеку iarduino_OLED для работы с Trema OLED дисплеем.
- Объявляем объект myOLED указывая адрес дисплея на шине I2C, он должен совпадать с адресом установленным переключателем на обратной стороне платы OLED дисплея.
- Подключаем шрифты предустановленные в библиотеке myOLED.
- Объявляем пины для работы с Trema-модуль синей кнопкой со светодиодом, Trema-модуль красной кнопкой со светодиодом и Trema-модуль зеленой кнопкой со светодиодом, а так же пины для работы со светодиодами кнопок.
- Объявляем массив и переменные задействованные в скетче.
В коде setup выполняются следующие действия:
- Переводим все выводы pinKey в режим входа для кнопок, а все выводы pinLed в режим выхода для светодиодов кнопок.
- Гасим все светодиоды.
- Назначаем случайное число со входа A0, для генератора random().
- Инициируем OLED дисплей и указываем шрифт для работы.
В коде loop выполняются следующие действия:
- Присваиваем переменой № нажатой клавиши число 3.
- В цикле фиксируем нажатие одной из трех клавиш. Если нажата клавиша, то сохраняем номер нажатой клавиши, увеличиваем количество нажатий клавиши.
- Если номер нажатой клавиши меньше 3. Включаем светодиод нажатой клавиши. Ждем пока не отпустят кнопку. Выключаем светодиод нажатой клавиши.
- Если ошибка, то переходим на 0 уровень.
- Если нет ошибок, то увеличиваем уровень.
- Выводим уровень на экран.
- Если начат новый уровень.
- Придумываем последний цвет от 0 до 2.
- Если начат нулевой уровень. Включаем все светодиоды. Ждем одну секунду. Выключаем все светодиоды.
- В цикле выводим всю последовательность цветов, включаем и выключая очередной светодиод.

Обсуждение