Espruino:Примеры/Использование кнопки BTN1 на Espruino для включения светодиода: различия между версиями
Myagkij (обсуждение | вклад) Нет описания правки |
Myagkij (обсуждение | вклад) Нет описания правки |
||
Строка 5: | Строка 5: | ||
=Использование кнопки BTN1 на Espruino для включения светодиода<ref>[https://www.espruino.com/Control+LED+with+Button www.espruino.com - Using BTN1 to turn on an LED]</ref>= | =Использование кнопки BTN1 на Espruino для включения светодиода<ref>[https://www.espruino.com/Control+LED+with+Button www.espruino.com - Using BTN1 to turn on an LED]</ref>= | ||
Плата Espruino, помимо прочего, оснащена кнопкой BTN1. И в этом руководстве мы расскажем, как использовать её для включения светодиода, а также о нескольких подводных камнях, с которыми можно столкнуться при использовании этой кнопки. | Плата [[Espruino]], помимо прочего, оснащена кнопкой '''BTN1'''. И в этом руководстве мы расскажем, как использовать её для включения светодиода, а также о нескольких подводных камнях, с которыми можно столкнуться при использовании этой кнопки. | ||
== Подсоединение == | == Подсоединение == | ||
Мы воспользуемся встроенными светодиодами и кнопкой Espruino, так что ничего подключать не нужно. | Мы воспользуемся встроенными светодиодами и кнопкой [[Espruino]], так что ничего подключать не нужно. | ||
== Код == | == Код == | ||
Давайте начнём с самого простого – с включения светодиода LED1: | Давайте начнём с самого простого – с включения светодиода '''LED1''': | ||
<syntaxhighlight lang="javascript" enclose="div"> | <syntaxhighlight lang="javascript" enclose="div"> | ||
Строка 19: | Строка 19: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Далее давайте создадим функцию, которая будет менять состояние светодиода LED1 с «вкл» на «выкл» и наоборот: | Далее давайте создадим функцию, которая будет менять состояние светодиода '''LED1''' с ''«вкл»'' на ''«выкл»'' и наоборот: | ||
<syntaxhighlight lang="javascript" enclose="div"> | <syntaxhighlight lang="javascript" enclose="div"> | ||
Строка 29: | Строка 29: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Теперь мы можем просто написать swap() и светодиод включится, если был выключен, и выключится, если был включен. Следующий шаг – организовать «слежку» за кнопкой, чтобы узнать, нажали на неё или нет. Для этого мы воспользуемся функцией setWatch(). Но она будет срабатывать дважды – когда пользователь будет нажимать на кнопку и когда будет её отпускать. Но нам нужно, чтобы состояние светодиода менялось только при нажатии на кнопку, поэтому нам нужна ещё одна функция: | Теперь мы можем просто написать swap() и [[светодиод]] включится, если был выключен, и выключится, если был включен. Следующий шаг – организовать ''«слежку»'' за кнопкой, чтобы узнать, нажали на неё или нет. Для этого мы воспользуемся функцией [[setWatch()]]. Но она будет срабатывать дважды – когда пользователь будет нажимать на кнопку и когда будет её отпускать. Но нам нужно, чтобы состояние светодиода менялось только при нажатии на кнопку, поэтому нам нужна ещё одна функция: | ||
<syntaxhighlight lang="javascript" enclose="div"> | <syntaxhighlight lang="javascript" enclose="div"> | ||
Строка 37: | Строка 37: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Это очень простая функция – она лишь проверяет, нажата кнопка BTN1 или нет. Поэтому она не будет вызывать функцию swap(), когда пользователь/пользовательница уберёт свой палец от кнопки. Как раз то, что нам нужно! Теперь мы можем воспользоваться setWatch(), чтобы с её помощью вызывать swap_on_down(): | Это очень простая функция – она лишь проверяет, нажата кнопка '''BTN1''' или нет. Поэтому она не будет вызывать функцию swap(), когда пользователь/пользовательница уберёт свой палец от кнопки. Как раз то, что нам нужно! Теперь мы можем воспользоваться [[setWatch()]], чтобы с её помощью вызывать '''swap_on_down()''': | ||
<syntaxhighlight lang="javascript" enclose="div"> | <syntaxhighlight lang="javascript" enclose="div"> | ||
Строка 43: | Строка 43: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Последним аргументом в функции выше стоит true – благодаря этому setWatch() будет вызывать swap_on_down() при каждом нажатии на кнопку, а не только в первый раз. Попробуйте ввести эту функцию – в результате красный светодиод будет включаться и выключаться каждый раз, когда вы будете нажимать на кнопку. | Последним аргументом в функции выше стоит '''true''' – благодаря этому [[setWatch()]] будет вызывать '''swap_on_down()''' при каждом нажатии на кнопку, а не только в первый раз. Попробуйте ввести эту функцию – в результате красный [[светодиод]] будет включаться и выключаться каждый раз, когда вы будете нажимать на кнопку. | ||
Кроме того, мы можем поиграться с разными цветами. Идея в том, чтобы при первом нажатии на кнопку загорался красный светодиод, при втором – зелёный, при третьем – синий, а при четвёртом – снова красный и так далее. Мы также добавим код, благодаря которому все светодиоды выключатся, если пользователь перестанет нажимать на кнопку в течение 5 секунд. | Кроме того, мы можем поиграться с разными цветами. Идея в том, чтобы при первом нажатии на кнопку загорался красный светодиод, при втором – зелёный, при третьем – синий, а при четвёртом – снова красный и так далее. Мы также добавим код, благодаря которому все светодиоды выключатся, если пользователь перестанет нажимать на кнопку в течение 5 секунд. | ||
Строка 80: | Строка 80: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Как видите, всё работает как и задумывалось, но иногда возвращает ошибку ERROR: Unknown Timeout (когда все | Как видите, всё работает как и задумывалось, но иногда возвращает ошибку '''ERROR: Unknown Timeout''' (когда все [[светодиод]]ы выключены). Это отличный повод поизучать наш код и немного его улучшить. Давайте начнём с ошибки. | ||
Исправить её можно, написав var timeout_ID = undefined вместо var timeout_ID = 0. Кроме того, мы можем сделать так, чтобы таймаут удалялся, только если его значением будет undefined: | Исправить её можно, написав '''var timeout_ID = undefined''' вместо '''var timeout_ID = 0'''. Кроме того, мы можем сделать так, чтобы таймаут удалялся, только если его значением будет [[undefined]]: | ||
<syntaxhighlight lang="javascript" enclose="div"> | <syntaxhighlight lang="javascript" enclose="div"> | ||
Строка 90: | Строка 90: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Для сравнения с undefined важно использовать именно !==, а не !=. Код выше работает, потому что ID, сгенерированный при установке таймаута, может быть «0», но никогда не будет задан как undefined. В принципе, мы можем ещё сильнее упростить код и просто написать var timeout_ID;, т.к. эта переменная всё равно будет инициализирована со значением undefined. Но мы ещё не закончили. Нам надо отредактировать функцию setTimeout(), чтобы после истечения таймаута, его значение было задано на undefined. В результате это... | Для сравнения с [[undefined]] важно использовать именно '''!==''', а не '''!='''. Код выше работает, потому что '''ID''', сгенерированный при установке таймаута, может быть «0», но никогда не будет задан как [[undefined]]. В принципе, мы можем ещё сильнее упростить код и просто написать '''var timeout_ID;''', т.к. эта переменная всё равно будет инициализирована со значением [[undefined]]. Но мы ещё не закончили. Нам надо отредактировать функцию [[setTimeout()]], чтобы после истечения таймаута, его значение было задано на [[undefined]]. В результате это... | ||
<syntaxhighlight lang="javascript" enclose="div"> | <syntaxhighlight lang="javascript" enclose="div"> | ||
Строка 103: | Строка 103: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Наконец, в языке Espruino есть функция, позволяющая задать прерывание только на возрастающем сигнале. Это как раз то, что нам нужно, и даже избавит нас от необходимости использовать функцию swap_on_down(). Мы можем просто написать следующее: | Наконец, в языке [[Espruino]] есть функция, позволяющая задать прерывание только на возрастающем сигнале. Это как раз то, что нам нужно, и даже избавит нас от необходимости использовать функцию '''swap_on_down()'''. Мы можем просто написать следующее: | ||
<syntaxhighlight lang="javascript" enclose="div"> | <syntaxhighlight lang="javascript" enclose="div"> | ||
Строка 109: | Строка 109: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
То есть нам теперь не нужно вызывать функцию swap_on_down() – мы просто напрямую вызовем функцию swap(). Весь код полностью в итоге выглядит вот так: | То есть нам теперь не нужно вызывать функцию '''swap_on_down()''' – мы просто напрямую вызовем функцию '''swap()'''. Весь код полностью в итоге выглядит вот так: | ||
<syntaxhighlight lang="javascript" enclose="div"> | <syntaxhighlight lang="javascript" enclose="div"> |
Версия от 18:28, 17 июля 2021
Использование кнопки 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);
}
См.также
Внешние ссылки