Освой Arduino играючи

Сайт Александра Климова

Шкодим

/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000

Шар судьбы

Если вы смотрели фильм "Трасса 60", то видели, как действует шар судьбы. Нужно задать вопрос, потрясти шар и получить ответ. Такой шар также можно купить в магазинах. Мы сделаем электронную версию.

На момент создания проекта у меня на макетной плате была схема от Игры на реакцию. Для начала я решил в качестве отладочного материала использовать готовую схему в упрощённом виде. Нам понадобится кнопка и светодиод. Резисторы и провода являются вспомогательными деталями.

Кнопка будет подключена к питанию через нагрузочный резистор (pull-up) номиналом 10 кОм. Резистор одним выводом подключается к порту 3, другим - к источнику питания.

Светодиод подключаем к порту 13 через резистор номиналом 330 Ом или близким к нему.

Reaction schema

Общий алгоритм кода:

  • Устанавливаем паузу перед включением светодиода, чтобы предотвратить нажатие кнопки игроком до начала измерения. Паузу варьируем, чтобы игрок не приспособился
  • Запускаем таймер и ждём нажатие кнопки
  • Если кнопка нажата, то случайным образом выбираем ответ из списка
  • Выводим результат игроку

int reply;

int waitTime; // пауза разной величины перед включением светодиода
const int ledPin = 13;
const int buttonPin = 3; // кнопка

void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT);
  Serial.println("Шар судьбы");
}

void loop() {
  Serial.println("Когда загорится светодиод, задай вопрос и нажми кнопку");
  waitTime = random(2000, 4000); // пауза в виде случайной величины от 2000 до 4000 мс
  delay(waitTime); // делаем паузу
  digitalWrite(ledPin, HIGH); // включаем светодиод

  while (digitalRead(buttonPin) == HIGH) {  } // пустой цикл, выполняется пока не нажата кнопка

  digitalWrite(ledPin, LOW); // выключаем светодиод

  reply = random(8);
  switch (reply) {
    case 0:
      Serial.println("Yes");
      break;
    case 1:
      Serial.println("Probably");
      break;
    case 2:
      Serial.println("Definitely");
      break;
    case 3:
      Serial.println("Don't be silly");
      break;
    case 4:
      Serial.println("Of course");
      break;
    case 5:
      Serial.println("Ask again");
      break;
    case 6:
      Serial.println("Doubtful");
      break;
    case 7:
      Serial.println("No");
      break;
  }
  delay(1000); // небольшая пауза перед новым ответом
}

После загрузки скетча следует открыть монитор порта. В нём выводится инструкция, подготавливающая игрока к началу испытаний. Затем включается светодиод. Задавайте вопрос и нажимайте кнопку. Результат записывается и выводится на экран. Затем всё повторяется снова. И так до бесконечности.

Serial Monitor Magic Ball

Цикл while блокирует исполнение кода, пока не будет нажата кнопка. Когда кнопка будет нажата, то условие цикла выполнится и скетч выполнит код, который идёт за циклом.

Убедившись, что задумка работает, можно переходить к следующему этапу - подключать дисплей (ЖК-экран) и любой подходящий датчик (датчик наклона, акселерометр и т.п.).

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

Игра на ЖК-экране

Похожий скетч в чуть упрощённом варианте. Подключение экрана смотреть на странице Библиотека LiquidCrystal. Кнопка подключена к выводу 7 в режиме INPUT_PULLUP. Ответы немного поменял, не забывайте, что у экрана меньше места для текста.


// Подключаем стандартную библиотеку LiquidCrystal
#include <LiquidCrystal.h>

// Инициализируем объект-экран, передаём использованные
// для подключения контакты на Arduino в порядке:
// RS, E, D4, D5, D6, D7
LiquidCrystal lcd(4, 5, 10, 11, 12, 13);

const int switchPin = 7;
int switchState = 0;
int prevSwitchState = 0;
int reply;


void setup()
{
  pinMode(switchPin, INPUT_PULLUP);
  lcd.begin(16, 2);
  lcd.print("Ask the ");
  lcd.setCursor(0, 1);
  lcd.print("Magic 8 Ball!");
}

void loop()
{
  switchState = digitalRead(switchPin);
  if (switchState != prevSwitchState) {
    if (switchState == LOW) {
      reply = random(8); //pick a number from 0 to 7

      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("The ball says: ");
      lcd.setCursor(0, 1 );

      switch (reply) {
        case 0: lcd.print("Yes");
          break;
        case 1: lcd.print("Most likely");
          break;
        case 2: lcd.print("Definitely");
          break;
        case 3: lcd.print("Outlook good");
          break;
        case 4: lcd.print("Try again");
          break;
        case 5: lcd.print("Ask again");
          break;
        case 6: lcd.print("Doubtful");
          break;
        case 7: lcd.print("My replay is no");
          break;
      } //end of switch
    } //end of nested if()
  } //end of outer if()
  //update the tilt switch status
  prevSwitchState = switchState;
}

Magic 8 Ball

Magic 8 Ball
Реклама