Освой Arduino играючи
/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000
Попробуем измерить скорость реакции человека. В определённый момент будет включаться светодиод, а пользователю нужно как можно быстрее нажать на кнопку. Момент включения светодиода и нажатия кнопки фиксируется, разница между полученными результатами вычисляется и выводится в удобном виде.
Начнём с простой незамысловатой схемы. Нам понадобится кнопка и светодиод. Резисторы и провода являются вспомогательными деталями.
Кнопка будет подключена к питанию через нагрузочный резистор (pull-up) номиналом 10 кОм. Резистор одним выводом подключается к порту 3, другим - к источнику питания.
Светодиод подключаем к порту 13 через резистор номиналом 330 Ом или близким к нему.
Общий алгоритм кода:
int waitTime; // пауза разной величины перед включением светодиода
int startTime; // начало отсчёта
int reactionTime; // время реакции
const int ledPin = 13; // светодиод
const int buttonPin = 3; // кнопка
void setup()
{
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
}
void loop()
{
Serial.println("Когда загорится светодиод, нажмите кнопку!");
Serial.println("Наблюдайте за светодиодом. Готовы?");
waitTime = random(2000, 4000); // пауза в виде случайной величины от 2000 до 4000 мс
delay(waitTime); // делаем паузу
digitalWrite(ledPin, HIGH); // включаем светодиод
startTime = millis(); // запоминаем начальное время
while (digitalRead(buttonPin) == HIGH) { } // пустой цикл, выполняется пока не нажата кнопка
reactionTime = millis() - startTime; // вычисляем время реакции
digitalWrite(ledPin, LOW); // выключаем светодиод
// Выводим результат в последовательный монитор
Serial.print("Отлично справились! Ваше время реакции: ");
Serial.print(reactionTime);
Serial.println(" миллисекунд");
delay(1000); // небольшая пауза перед новым измерением реакции
}
После загрузки скетча следует открыть последовательный монитор. В нём выводится инструкция, подготавливающая игрока к началу испытаний. Затем включается светодиод. Задача игрока как можно быстрее среагировать и нажать кнопку. Результат записывается и выводится на экран. Затем всё повторяется снова. И так до бесконечности.
Цикл while блокирует исполнение кода, пока не будет нажата кнопка. Когда кнопка будет нажата, то условие цикла выполнится и скетч выполнит код, который идёт за циклом.
Вывод показаний в монитор порта обычно используют в прототипах для отладки. Когда вы убедились, что основная идея работает, то следует подумать о законченной реализации тренажёра. Вместо монитора порта можно использовать дополнительные светодиоды в качестве индикаторов. Если пользователь нажал кнопку быстрее определённого значения (в нашем случае 215 миллисекунд), то включим светодиод зелёного цвета, в противном случае будем включать красный светодиод. А для сигнального светодиода используйте какой-то другой цвет, например, синий.
Схему приводить не буду, просто добавьте два светодиода с резисторами. Это не должно вызвать у вас затруднений.
Изменения в коде будут небольшими. Добавим инициализацию новых светодиодов на портах 4 и 5 и в функции loop() добавим проверку на время реакции через if..else.
int waitTime; // пауза разной величины перед включением светодиода
int startTime; // начало отсчёта
int reactionTime; // время реакции
const int ledPin = 13; // светодиод для подачи сигнала
const int buttonPin = 3; // кнопка
const int quickLed = 4; // светодиод для быстрой реакции
const int slowLed = 5; // светодиод для медленной реакции
void setup()
{
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
pinMode(quickLed, OUTPUT);
pinMode(slowLed, OUTPUT);
}
void loop()
{
Serial.println("Когда загорится светодиод, нажмите кнопку!");
Serial.println("Наблюдайте за светодиодом. Готовы?");
waitTime = random(2000, 4000); // пауза в виде случайной величины от 2000 до 4000 мс
delay(waitTime); // делаем паузу
digitalWrite(ledPin, HIGH); // включаем светодиод
startTime = millis(); // запоминаем начальное время
while (digitalRead(buttonPin) == HIGH) { } // пустой цикл, выполняется пока не нажата кнопка
reactionTime = millis() - startTime; // вычисляем время реакции
digitalWrite(ledPin, LOW); // выключаем сигнальный светодиод
// если уложились в отведённое время, то включаем один светодиод и выключаем другой
if (reactionTime <= 215) {
digitalWrite(quickLed, HIGH);
digitalWrite(slowLed, LOW);
}
else {
digitalWrite(quickLed, LOW);
digitalWrite(slowLed, HIGH);
}
// Выводим результат в последовательный монитор
Serial.print("Отлично справились! Ваше время реакции: ");
Serial.print(reactionTime);
Serial.println(" миллисекунд");
delay(1000); // небольшая пауза перед новым измерением реакции
}
Осталось оформить тренажёр как законченное устройство. Уложите всю схему в коробку. В коробке следует сделать три отверстия под светодиоды и одно для кнопки.
Дальше всё зависит от вашей фантазии. Вы можете добавить больше светодиодов для показа различной степени реакции: отличная, хорошая, средняя, медленная. В этом случае нужно добавить больше условий в код.
Также можно добавить вторую кнопку для второго игрока. Игра станет интереснее.
Следующий этап усложнения - добавить ЖК-экран, использовать трёхцветный светодиод и звуковые эффекты. Пищалка будет отвлекать внимание, а реагировать нужно на определённый цвет светодиода.