Прерывания. Урок 11. Ардуино

Прерывания
Программирование прерывания в Ардуино
Программирование прерывания в Ардуино

Привет! Наверное, вы помните, как в уроках про мультинажание на кнопку нам нужно было решить проблему подсчета количества нажатий в одной серии. Тогда мы использовали функцию delay() и задерживали выполнение программы. Но что, если делать такую паузу нельзя, а необходимо получать данные с датчиков постоянно. Но при этом управлять программой с помощью кнопок или других датчиков. Для этого в Ардуино существуют прерывания.

В одном из последних обзоров датчиков, мы рассматривали датчик препятствий KY-033. Посмотрите тот обзор если вы пропустили или уже забыли, потому что в этом уроке мы будем его использовать.

Инфракрасный датчик препятствий KY-033

Итак, прерывания. Они позволяют выполнять программу асинхронно. При наступлении определенного события — нажатия на кнопку, сигнала от датчика, они дают возможность остановить ход текущей программы, выполнить код прерывания, а затем вернуться к прерванной задаче.

Для того, чтобы выполнить этот урок нам понадобиться.

  • Ардуино UNO
  • Макетная плата
  • Перемычки
  • Датчик KY-033
  • 3 светодиода разного цвета
  • 3 резистора 220 Ом
  • Кабель USB

Прерывания

Аппаратные прерывания — это альтернатива постоянного сканирования состояния контактов в цикле loop(). Они не лучше и не хуже, вы всегда можете выбрать тот способ, который будет лучше работать в вашем проекте.

С аппаратной точки зрения, опрос контактов в цикле и прерывание абсолютно одинаковы. Однако, существуют моменты, когда использовать прерывания будет невозможно.

Например, устранение дребезга. Внутри прерывания не может быть использована функция delay(), а это значит, что программы подтверждающие состояние датчика должны быть спроектированы по-другому.

Программа

Проблему дребезга кнопки можно решить аппаратно. Мы сделаем это в другом уроке, а пока займемся работой с прерываниями.

В этом проекте мы хотим использовать бесконечный цикл в главном цикле loop() и использовать прерывание для запуска дополнительной подпрограммы, которая вмешается в работу цикла.

Кроме того, используем датчик препятствий из последнего обзора, он будет выполнять функцию бесконтактной кнопки.

Соберем на макетной плате схему. Используем уже знакомую схему подключения датчика препятствий, но добавим в нее три светодиода.

Принципиальная схема подключения датчика
Принципиальная схема подключения датчика

В цикле loop() будем бесконечно изменять яркость одного светодиода с помощью шим. А при срабатывании прерывания от датчика будем заменять один светодиод на другой, при этом яркость изменяться не будет.

volatile

В первую очередь нам нужно будет объявить переменную, которая отвечает за контакт активного светодиода. Она будет изменяться в процессе программы, а значит ее следует объявить как volatile.

volatile int selectedLED = 9;

attachInterrupt

Далее создадим 0 прерывание. 0 прерывание связано с пином 2 на плате Ардуино Uno, поэтому датчик препятствий подключен именно ко 2 контакту.

void setup(){
  attachInterrupt(0, swap, RISING);
}

Теперь напишем функцию swap(), чтобы вызвать ее по прерыванию. Она будет переключать активный светодиод.

void swap(){
  analogWrite(selectedLED, 0);
  if (selectedLED == GREEN)
  selectedLED = RED;
  else if (selectedLED == RED)
  selectedLED = YELLOW;
  else if (selectedLED == YELLOW)
  selectedLED = GREEN;
}

И в конце осталось только написать бесконечный цикл в основном цикле программы. Он будет изменять яркость светодиодов.

void loop(){
  for (int i = 0; i<256; i++){
    analogWrite(selectedLED, i);
    delay(10);
  }
  for (int i = 255; i>= 0; i--){
    analogWrite(selectedLED, i);
    delay(10);
  }
}
Результат работы программы прерывания
Результат работы программы прерывания

Полный текст программы

const int RED=9;
const int YELLOW=10;
const int GREEN=11;

volatile int selectedLED = RED;

void setup(){
  pinMode (RED, OUTPUT);
  pinMode (GREEN, OUTPUT);
  pinMode (YELLOW, OUTPUT);
  
  attachInterrupt(0, swap, RISING);
}

void swap(){
  analogWrite(selectedLED, 0);
  if (selectedLED == GREEN)
  selectedLED = RED;
  else if (selectedLED == RED)
  selectedLED = YELLOW;
  else if (selectedLED == YELLOW)
  selectedLED = GREEN;
}

void loop(){
  for (int i = 0; i<256; i++){
    analogWrite(selectedLED, i);
    delay(10);
  }
  for (int i = 255; i>= 0; i--){
    analogWrite(selectedLED, i);
    delay(10);
  }
}

Заключение

Мы рассмотрели прерывания в Ардуино. Это одна из сложных тем в изучении Ардуино, но она поможет нам создавать сложные устройства с несколькими датчиками и большие программы отвечающие за несколько устройств сразу.

Добавить комментарий

Ваш адрес email не будет опубликован.