Espruino:Примеры/Использование кнопки BTN1 на Espruino для включения светодиода: различия между версиями

Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску
Нет описания правки
Нет описания правки
 
Строка 15: Строка 15:
Давайте начнём с самого простого – с включения [[светодиод]]а '''LED1''':
Давайте начнём с самого простого – с включения [[светодиод]]а '''LED1''':


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
LED1.write(1);
LED1.write(1);
</syntaxhighlight>
</syntaxhighlight>
Строка 21: Строка 21:
Далее давайте создадим функцию, которая будет менять состояние [[светодиод]]а '''LED1''' с ''«вкл»'' на ''«выкл»'' и наоборот:
Далее давайте создадим функцию, которая будет менять состояние [[светодиод]]а '''LED1''' с ''«вкл»'' на ''«выкл»'' и наоборот:


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
var next_state = 1;
var next_state = 1;
function swap() {
function swap() {
Строка 31: Строка 31:
Теперь мы можем просто написать swap() и [[светодиод]] включится, если был выключен, и выключится, если был включен. Следующий шаг – организовать ''«слежку»'' за кнопкой, чтобы узнать, нажали на неё или нет. Для этого мы воспользуемся функцией [[setWatch()]]. Но она будет срабатывать дважды – когда пользователь будет нажимать на кнопку и когда будет её отпускать. Но нам нужно, чтобы состояние светодиода менялось только при нажатии на кнопку, поэтому нам нужна ещё одна функция:
Теперь мы можем просто написать swap() и [[светодиод]] включится, если был выключен, и выключится, если был включен. Следующий шаг – организовать ''«слежку»'' за кнопкой, чтобы узнать, нажали на неё или нет. Для этого мы воспользуемся функцией [[setWatch()]]. Но она будет срабатывать дважды – когда пользователь будет нажимать на кнопку и когда будет её отпускать. Но нам нужно, чтобы состояние светодиода менялось только при нажатии на кнопку, поэтому нам нужна ещё одна функция:


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
function swap_on_down() {
function swap_on_down() {
   if (digitalRead(BTN1) == 1) swap();
   if (digitalRead(BTN1) == 1) swap();
Строка 39: Строка 39:
Это очень простая функция – она лишь проверяет, нажата кнопка '''BTN1''' или нет. Поэтому она не будет вызывать функцию swap(), когда пользователь/пользовательница уберёт свой палец от кнопки. Как раз то, что нам нужно! Теперь мы можем воспользоваться [[setWatch()]], чтобы с её помощью вызывать '''swap_on_down()''':
Это очень простая функция – она лишь проверяет, нажата кнопка '''BTN1''' или нет. Поэтому она не будет вызывать функцию swap(), когда пользователь/пользовательница уберёт свой палец от кнопки. Как раз то, что нам нужно! Теперь мы можем воспользоваться [[setWatch()]], чтобы с её помощью вызывать '''swap_on_down()''':


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
setWatch(swap_on_down, BTN1, true);
setWatch(swap_on_down, BTN1, true);
</syntaxhighlight>
</syntaxhighlight>
Строка 47: Строка 47:
Кроме того, мы можем поиграться с разными цветами. Идея в том, чтобы при первом нажатии на кнопку загорался красный светодиод, при втором – зелёный, при третьем – синий, а при четвёртом – снова красный и так далее. Мы также добавим код, благодаря которому все светодиоды выключатся, если пользователь перестанет нажимать на кнопку в течение 5 секунд.
Кроме того, мы можем поиграться с разными цветами. Идея в том, чтобы при первом нажатии на кнопку загорался красный светодиод, при втором – зелёный, при третьем – синий, а при четвёртом – снова красный и так далее. Мы также добавим код, благодаря которому все светодиоды выключатся, если пользователь перестанет нажимать на кнопку в течение 5 секунд.


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
// Здесь будет храниться индикатор светодиода:
// Здесь будет храниться индикатор светодиода:
var next_LED = 1;
var next_LED = 1;
Строка 84: Строка 84:
Исправить её можно, написав '''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">
   if (timeout_ID !== undefined) {
   if (timeout_ID !== undefined) {
     clearTimeout(timeout_ID);
     clearTimeout(timeout_ID);
Строка 92: Строка 92:
Для сравнения с [[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">
   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); }, 5000);
``
``
Строка 99: Строка 99:
...станет этим:
...станет этим:


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
timeout_ID = setTimeout(function () { LED1.write(0); LED2.write(0); LED3.write(0); timeout_ID = undefined; }, 5000); ``
timeout_ID = setTimeout(function () { LED1.write(0); LED2.write(0); LED3.write(0); timeout_ID = undefined; }, 5000); ``
</syntaxhighlight>
</syntaxhighlight>
Строка 105: Строка 105:
Наконец, в языке [[Espruino]] есть функция, позволяющая задать прерывание только на возрастающем сигнале. Это как раз то, что нам нужно, и даже избавит нас от необходимости использовать функцию '''swap_on_down()'''. Мы можем просто написать следующее:
Наконец, в языке [[Espruino]] есть функция, позволяющая задать прерывание только на возрастающем сигнале. Это как раз то, что нам нужно, и даже избавит нас от необходимости использовать функцию '''swap_on_down()'''. Мы можем просто написать следующее:


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
setWatch(swap, BTN1, {repeat:true, edge:"rising"});
setWatch(swap, BTN1, {repeat:true, edge:"rising"});
</syntaxhighlight>
</syntaxhighlight>
Строка 111: Строка 111:
То есть нам теперь не нужно вызывать функцию '''swap_on_down()''' – мы просто напрямую вызовем функцию '''swap()'''. Весь код полностью в итоге выглядит вот так:
То есть нам теперь не нужно вызывать функцию '''swap_on_down()''' – мы просто напрямую вызовем функцию '''swap()'''. Весь код полностью в итоге выглядит вот так:


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
// Здесь будет храниться индикатор светодиода:
// Здесь будет храниться индикатор светодиода:
var next_LED = 1;
var next_LED = 1;

Текущая версия от 19:55, 23 мая 2023

Перевод: Максим Кузьмин
Проверка/Оформление/Редактирование: Мякишев Е.А.


Использование кнопки 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);
}

См.также

Внешние ссылки