← Светильник, управляемый по USB | Оглавление | Конец первой серии экспериментов!
В этом эксперименте мы создаем еще одну игру, на этот раз нужно быстрее соперника нажать кнопку 20 раз.
В старой версии блокнота хакера по ошибке были указаны резисторы на 100 кОм, которых нет в наборе. На самом деле в уроке смело можно и нужно использовать резисторы на 10 кОм из комплекта.
#define BUZZER_PIN 0 #define FIRST_BAR_PIN 4 #define BAR_COUNT 10 #define MAX_SCORE 20 // глобальные переменные, используемые в прерываниях (см. далее) // должны быть отмечены как нестабильные (англ. volatile) volatile int score = 0; void setup() { for (int i = 0; i < BAR_COUNT; ++i) pinMode(i + FIRST_BAR_PIN, OUTPUT); pinMode(BUZZER_PIN, OUTPUT); // Прерывание (англ. interrupt) приостанавливает основную // программу, выполняет заданную функцию, а затем возобновляет // основную программу. Нам нужно прерывание на нажатие кнопки, // т.е. при смене сигнала с высокого на низкий, т.е. на // нисходящем (англ. falling) фронте attachInterrupt(INT1, pushP1, FALLING); // INT1 — это 3-й пин attachInterrupt(INT0, pushP2, FALLING); // INT0 — это 2-й пин } void pushP1() { ++score; } // функция-прерывание 1-го игрока void pushP2() { --score; } // функция-прерывание 2-го игрока void loop() { tone(BUZZER_PIN, 2000, 1000); // даём сигнал к старту. // пока никто из игроков не выиграл, обновляем «канат» while (abs(score) < MAX_SCORE) { int bound = map(score, -MAX_SCORE, MAX_SCORE, 0, BAR_COUNT); int left = min(bound, BAR_COUNT / 2 - 1); int right = max(bound, BAR_COUNT / 2); for (int i = 0; i < BAR_COUNT; ++i) digitalWrite(i + FIRST_BAR_PIN, i >= left && i <= right); } tone(BUZZER_PIN, 4000, 1000); // даём сигнал победы while (true) {} // «подвешиваем» плату до перезагрузки }
setup() прописывается инструкция attachInterrupt(interrupt, action, event), гдеinterrupt может принимать значения INT0 или INT1 для портов 2 и 3 соответственно. Можно задать эти значения и с помощью функции digitalPinToInterrupt(pin), где вместо pin указать номер пина.action — имя функции, которая будет вызываться при наступлении событияevent — событие, которое мы отслеживаем. Может принимать значение RISING (изменение от низкого уровня сигнала к высокому, от 0 к 1), FALLING (от высокого уровня к низкому, от 1 к 0), CHANGE (от 0 к 1 или от 1 к 0), LOW (при низком уровне сигнала).volatile, как в данном эксперименте volatile int score = 0.delay().abs(value) возвращает абсолютное значение value (значение по модулю). Обратите внимание, что функция может сработать некорректно, если передавать ей выражение, которое еще не вычислено, например abs(++a), лучше передавать ей просто переменную.min(val1, val2) вернет меньшее из val1 и val2.max(val1, val2) вернет большее из val1 и val2.digitalWrite()&&). Нередко нужен оператор «логическое «или»: ||. Он возвращает «истину», если хотя бы один из операндов имеет значение «истина». false || false вернет false, а true || true, true || false и false || true вернут true.while(true){} для того, чтобы loop() остановился после того, как кто-то выиграл: у while всегда истинное условие и он бесконечно ничего не выполняет!← Светильник, управляемый по USB | Оглавление | Конец первой серии экспериментов!