Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Manufacturing Technology >> Производственный процесс

Эффективное управление 10 кнопками с помощью одного прерывания на Arduino UNO

Компоненты и материалы

Необходимые инструменты и сервисы

О проекте

Введение

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

Представьте, что у вас есть пользовательский интерфейс, например пульт управления, работающий от батареи. Желательно переводить Arduino (или отдельный чип ATmega) в режим глубокого сна для экономии энергии. В этом режиме пробудить микроконтроллер можно только внешним прерыванием. Чип ATmega328P, используемый в Arduino Uno, имеет всего два внешних пина прерываний (INT0 и INT1 на пинах 2 и 3). Если в интерфейсе больше двух кнопок — возникает проблема.

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

Эффективное управление 10 кнопками с помощью одного прерывания на Arduino UNO

Помимо внешних прерываний, ATmega328P поддерживает прерывания по изменению состояния пина (Pin Change Interrupts). Существуют библиотеки для работы с ними, и они хорошо решают эту задачу.

Однако во время программистского соревнования я нашел способ использовать стандартные внешние прерывания без дополнительных электронных компонентов.

Схема подключения

Эффективное управление 10 кнопками с помощью одного прерывания на Arduino UNO
Эффективное управление 10 кнопками с помощью одного прерывания на Arduino UNO
Эффективное управление 10 кнопками с помощью одного прерывания на Arduino UNO

Используется 10 кнопок, которые идеально поместились на макетной плате. Можно подключить одну кнопку на пин — до 20 на Uno и до 70 на Mega! (Если действительно нужно 70 кнопок, лучше использовать мультиплексирование, не обязательно покупать Mega.)

Одна сторона каждой кнопки подключена к произвольному пину (в данном случае 4–13). Вторые контакты всех кнопок соединены вместе и подключены к одному пину, поддерживающему прерывания (пин 2).

Эффективное управление 10 кнопками с помощью одного прерывания на Arduino UNO

Программный код

Код приведен ниже. Загрузите его в плату, откройте монитор порта. При нажатии кнопки выводится её номер. Обратите внимание: функция loop() не используется.

Эффективное управление 10 кнопками с помощью одного прерывания на Arduino UNO

Принцип работы

Используется прерывание на пине 2, настроенное на спад (FALLING).

Чтобы обойтись без диодов, Arduino динамически переключает конфигурацию пинов. Существует два режима: Общий режим (Common mode) и Раздельный режим (Distinct mode).

Общий режим

Большинство времени схема находится в общем режиме. Пин прерывания настроен как INPUT_PULLUP, остальные пины — как OUTPUT и установлены в LOW.

Эффективное управление 10 кнопками с помощью одного прерывания на Arduino UNO
void configureCommon() {
  pinMode(commonPin, INPUT_PULLUP);
  for (int i = 0; i < sizeof(buttonPins) / sizeof(int); i++) {
    pinMode(buttonPins[i], OUTPUT);
    digitalWrite(buttonPins[i], LOW);
  }
}

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

Раздельный режим

После срабатывания прерывания быстро переключаемся в раздельный режим.

Это зеркальная конфигурация: пин прерывания становится OUTPUT и LOW, а пины кнопок — INPUT_PULLUP.

Эффективное управление 10 кнопками с помощью одного прерывания на Arduino UNO
void configureDistinct() {
  pinMode(commonPin, OUTPUT);
  digitalWrite(commonPin, LOW);
  for (int i = 0; i < sizeof(buttonPins) / sizeof(int); i++) {
    pinMode(buttonPins[i], INPUT_PULLUP);
  }
}

В разделенном режиме только пины, соответствующие нажатым кнопкам, будут притянуты к земле. Легко опросить все пины и определить, какая кнопка вызвала прерывание.

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

Более сложный пример: сервопривод с режимом сна

Подключим сервопривод и назначим каждой кнопке угол поворота (1=0°, 2=20°… 10=120°). Питание Arduino — от батареек.

Эффективное управление 10 кнопками с помощью одного прерывания на Arduino UNO
Эффективное управление 10 кнопками с помощью одного прерывания на Arduino UNO
Эффективное управление 10 кнопками с помощью одного прерывания на Arduino UNO

В этом примере Arduino уходит в режим глубокого сна через 5 секунд неактивности. Сервопривод питание через транзистор, чтобы отключать его когда не используется.

Код для этого примера также приведен ниже.

Исходный код

Простой логгер в Serial

const int commonPin = 2;
const int buttonPins[] = {4,5,6,7,8,9,10,11,12,13};
unsigned long lastFire = 0;

void setup() {
  configureCommon();
  attachInterrupt(digitalPinToInterrupt(commonPin), pressInterrupt, FALLING);
  Serial.begin(9600);
}

void loop() {
  // Пусто!
}

void pressInterrupt() {
  if (millis() - lastFire < 200) return; // Антидребезг
  lastFire = millis();
  configureDistinct();
  for (int i = 0; i < sizeof(buttonPins) / sizeof(int); i++) {
    if (!digitalRead(buttonPins[i])) {
      press(i);
    }
  }
  configureCommon();
}

void configureCommon() {
  pinMode(commonPin, INPUT_PULLUP);
  for (int i = 0; i < sizeof(buttonPins) / sizeof(int); i++) {
    pinMode(buttonPins[i], OUTPUT);
    digitalWrite(buttonPins[i], LOW);
  }
}

void configureDistinct() {
  pinMode(commonPin, OUTPUT);
  digitalWrite(commonPin, LOW);
  for (int i = 0; i < sizeof(buttonPins) / sizeof(int); i++) {
    pinMode(buttonPins[i], INPUT_PULLUP);
  }
}

void press(int button) {
  Serial.println(button + 1);
}

Сервопривод с режимом сна

#include 
#include 
#include 

const int commonPin = 2;
const int buttonPins[] = {4,5,6,7,8,9,10,11,12,13};
const int servoEnablePin = A1;
const int servoPin = A0;
Servo servo;
unsigned long lastFire = 0;
int status = 0;

void setup() {
  pinMode(commonPin, INPUT_PULLUP);
  configureCommon();
  attachInterrupt(digitalPinToInterrupt(commonPin), pressInterrupt, FALLING);
  servo.attach(servoPin);
  pinMode(servoEnablePin, OUTPUT);
}

void loop() {
  if (millis() - lastFire > 5000) {
    digitalWrite(servoEnablePin, LOW);
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
    sleep_enable();
    sleep_mode();
  }
  delay(10);
}

void pressInterrupt() {
  sleep_disable();
  power_all_enable();
  if (millis() - lastFire < 200) return;
  lastFire = millis();
  configureDistinct();
  for (int i = 0; i < sizeof(buttonPins) / sizeof(int); i++) {
    if (!digitalRead(buttonPins[i])) {
      press(i);
    }
  }
  configureCommon();
}

void configureCommon() {
  pinMode(commonPin, INPUT_PULLUP);
  for (int i = 0; i < sizeof(buttonPins) / sizeof(int); i++) {
    pinMode(buttonPins[i], OUTPUT);
    digitalWrite(buttonPins[i], LOW);
  }
}

void configureDistinct() {
  pinMode(commonPin, OUTPUT);
  digitalWrite(commonPin, LOW);
  for (int i = 0; i < sizeof(buttonPins) / sizeof(int); i++) {
    pinMode(buttonPins[i], INPUT_PULLUP);
  }
}

void press(int button) {
  digitalWrite(servoEnablePin, HIGH);
  servo.write(map(button, 0, 9, 0, 180));
}

Схемы

Эффективное управление 10 кнопками с помощью одного прерывания на Arduino UNO
Эффективное управление 10 кнопками с помощью одного прерывания на Arduino UNO

Файлы схем для Fritzing: multiinterrupt_hoF76Oc4T5.fzz, servo_with_sleep_u9ZqxF0jhY.fzz

Производственный процесс

  1. Создание DTMF-декодера на Arduino без внешних микросхем
  2. Создание потрясающей системы Ambilight для монитора на Arduino
  3. Создание ультразвукового левитатора на Arduino: пошаговое руководство
  4. Умный вольтметр на Arduino и смартфоне — простое DIY-проект
  5. IoT-монитор пульса в реальном времени на Arduino и MAX30100
  6. Веб-сервер на Arduino Uno WiFi: управление LED через браузер
  7. Умный счетчик парковки: Отслеживание машин в реальном времени (Arduino, Processing, PHP)
  8. Автоматизация игры «Динозавр» в Chrome на Arduino и LDR с Python
  9. Сборка компактного FM-радио на Arduino Nano и RDA5807M
  10. Беспроводная прошивка Arduino через Bluetooth HC-05: щит без USB-кабеля