Espruino:Примеры/Использование кнопки BTN1 на Espruino для включения светодиода
Использование кнопки BTN1 на Espruino для включения светодиода[1]
Плата Espruino, помимо прочего, оснащена кнопкой BTN1. И в этом руководстве мы расскажем, как использовать её для включения светодиода, а также о нескольких подводных камнях, с которыми можно столкнуться при использовании этой кнопки.
Подсоединение
Мы воспользуемся встроенными светодиодами и кнопкой Espruino, так что ничего подключать не нужно.
Код
Давайте начнём с самого простого – с включения светодиода LED1:
LED1.write(1);
Далее давайте создадим функцию, которая будет менять состояние светодиода LED1 с «вкл» на «выкл» и наоборот:
var next_state = 1;
function swap() {
LED1.write(next_state);
next_state = !next_state;
}
Теперь мы можем просто написать swap() и светодиод включится, если был выключен, и выключится, если был включен. Следующий шаг – организовать «слежку» за кнопкой, чтобы узнать, нажали на неё или нет. Для этого мы воспользуемся функцией setWatch(). Но она будет срабатывать дважды – когда пользователь будет нажимать на кнопку и когда будет её отпускать. Но нам нужно, чтобы состояние светодиода менялось только при нажатии на кнопку, поэтому нам нужна ещё одна функция:
function swap_on_down() {
if (digitalRead(BTN1) == 1) swap();
}
Это очень простая функция – она лишь проверяет, нажата кнопка BTN1 или нет. Поэтому она не будет вызывать функцию swap(), когда пользователь/пользовательница уберёт свой палец от кнопки. Как раз то, что нам нужно! Теперь мы можем воспользоваться setWatch(), чтобы с её помощью вызывать swap_on_down():
setWatch(swap_on_down, BTN1, true);
Последним аргументом в функции выше стоит true – благодаря этому setWatch() будет вызывать swap_on_down() при каждом нажатии на кнопку, а не только в первый раз. Попробуйте ввести эту функцию – в результате красный светодиод будет включаться и выключаться каждый раз, когда вы будете нажимать на кнопку.
Кроме того, мы можем поиграться с разными цветами. Идея в том, чтобы при первом нажатии на кнопку загорался красный светодиод, при втором – зелёный, при третьем – синий, а при четвёртом – снова красный и так далее. Мы также добавим код, благодаря которому все светодиоды выключатся, если пользователь перестанет нажимать на кнопку в течение 5 секунд.
// Здесь будет храниться индикатор светодиода:
var next_LED = 1;
// ID таймаута (см. ниже):
var timeout_ID = 0;
function swap() {
// Удаляем таймаут для выключения светодиодов,
// когда пользователь нажимает на кнопку:
clearTimeout(timeout_ID);
// Определяем, какой светодиод включить/выключить:
switch(next_LED) {
case 1:
LED1.write(1);
LED3.write(0);
break;
case 2:
LED2.write(1);
LED1.write(0);
break;
case 3:
LED3.write(1);
LED2.write(0);
break;
}
// Определяем, какой светодиод нужно включить следующим:
next_LED = Math.wrap(next_LED, 3) + 1;
// Обнуляем таймаут для выключения всех светодиодов,
// чтобы его можно было использовать
// при следующем вызове этой функции:
timeout_ID = setTimeout(function () { LED1.write(0); LED2.write(0); LED3.write(0); }, 5000);
}
Как видите, всё работает как и задумывалось, но иногда возвращает ошибку ERROR: Unknown Timeout (когда все светодиоды выключены). Это отличный повод поизучать наш код и немного его улучшить. Давайте начнём с ошибки.
Исправить её можно, написав var timeout_ID = undefined вместо var timeout_ID = 0. Кроме того, мы можем сделать так, чтобы таймаут удалялся, только если его значением будет undefined:
if (timeout_ID !== undefined) {
clearTimeout(timeout_ID);
}
Для сравнения с undefined важно использовать именно !==, а не !=. Код выше работает, потому что ID, сгенерированный при установке таймаута, может быть «0», но никогда не будет задан как undefined. В принципе, мы можем ещё сильнее упростить код и просто написать var timeout_ID;, т.к. эта переменная всё равно будет инициализирована со значением undefined. Но мы ещё не закончили. Нам надо отредактировать функцию setTimeout(), чтобы после истечения таймаута, его значение было задано на undefined. В результате это...
timeout_ID = setTimeout(function () { LED1.write(0); LED2.write(0); LED3.write(0); }, 5000);
``
...станет этим:
timeout_ID = setTimeout(function () { LED1.write(0); LED2.write(0); LED3.write(0); timeout_ID = undefined; }, 5000); ``
Наконец, в языке Espruino есть функция, позволяющая задать прерывание только на возрастающем сигнале. Это как раз то, что нам нужно, и даже избавит нас от необходимости использовать функцию swap_on_down(). Мы можем просто написать следующее:
setWatch(swap, BTN1, {repeat:true, edge:"rising"});
То есть нам теперь не нужно вызывать функцию swap_on_down() – мы просто напрямую вызовем функцию swap(). Весь код полностью в итоге выглядит вот так:
// Здесь будет храниться индикатор светодиода:
var next_LED = 1;
// ID таймаута (см. ниже):
var timeout_ID;
function swap() {
// Удаляем таймаут для выключения светодиодов,
// когда пользователь нажимает на кнопку:
if (timeout_ID !== undefined) {
clearTimeout(timeout_ID);
}
// Определяем, какой светодиод включить/выключить:
switch(next_LED) {
case 1:
LED1.write(1);
LED3.write(0);
break;
case 2:
LED2.write(1);
LED1.write(0);
break;
case 3:
LED3.write(1);
LED2.write(0);
break;
}
// Определяем, какой светодиод нужно включить следующим:
next_LED = Math.wrap(next_LED, 3) + 1;
// Обнуляем таймаут для выключения всех светодиодов,
// чтобы его можно было использовать
// при следующем вызове этой функции:
timeout_ID = setTimeout(function () { LED1.write(0); LED2.write(0); LED3.write(0); timeout_ID = undefined; }, 5000);
}
См.также
Внешние ссылки