«Умное» мигание светодиодом в Ардуино

1000Эта статья будет о программировании. О простом и сложном одновременно — мигании светодиодом.

Зачем все это?

Бывает при программирование какого-нибудь устройства не хватает портов ввода-вывода микроконтроллера. Или из экономических соображений, а может нехватки места в корпусе, не хочется устанавливать дисплей, а как то сигнализировать о режимах работы устройства очень хотелось бы. Часто достаточно сигнализировать о этих режимах горением или миганием светодиода. А если режимов много?

На мысль меня навела автомобильная сигнализация, в которой я как то программировал режим автозапуска. Там, чтобы установить 14-й бит определенного регистра нужно было после входа в режим программирования этого регистра 14 раз нажать на определенную кнопку брелка, а потом дождаться 14-ти коротких сигналов (или мигания поворотников). Затем нажать кнопку в подтверждения и услышать длинный сигнал.

А почему бы это же самое ни использовать в моих прошивках микроконтроллеров:

Режим 1 — мигаем светодиодом один раз в секунду, режим 2 — два раза и так далее …

Как это работает

Рассмотрим мигание светодиодом, подключенным к 13 порту на  Ардуино. Это первая программа которую осваивают при изучении Ардуино. Во многих контроллерах, которые мне попадались в последнее время, эта программа зашита на заводе, видимо для тех кто не осилил и это. 🙂

Казалось бы чего проще

Чередование высокого и низкого уровня на выводе 13 каждые 0.5 секунды.

Мигание светодиодом

Можно было установить и два мигания в секунду и три. Но при этом контроллер целиком занят миганием светодиода. Функция delay() подразумевает, что долгие 500 мс больше ничего не происходит (ну разве что обрабатываются прерывания).

Обработка события с использованием millis()

Несложный код, выполняемый в основном цикле делает тоже самое.

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

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

Обработка битовой матрицы состояния светодиода

Уменьшаем время срабатывания события до 1/8 секунды и в 1 байте кодируем 8 бит состояний, отображаемых последовательно.

 

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

4-й режим. Короткая вспышка 1 раз в секунду

Blink_sl_2

5-й режим. Две короткие вспышки в секунду

Blink_sl_3

6-й режим. Три вспышки.

Blink_sl_4

Ну и постоянная череда коротких вспышек

Blink_sl_5

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

Что если 8 бит состояний светодиодов мало?

Можно использовать несколько байт. Например, для кодирования сигнала SOS азбукой Морзе я использовал 4 байта, которые используются последовательно

Получаем циклический сигнал SOS — три коротких, три длинных и снова три коротких сигнала светодиодом, повторяемый каждые 4 секунды

Blink_sl_6

Для тех, кто считает, что программировать микроконтроллеры в цикле loop() это не по Фен шую 😉 Несмотря на то, что millis() использует прерывание по первому таймеру

Только хардкор. Только прерывания!

Берем 16-ти битный Таймер 1. Устанавливаем прерывание на переполнение за 125мс

Подробно по программированию таймера можно почитать здесь. При этом delay() на 5 секунд в Loop() совершенно не мешают управлению нашим светодиодом.

Недостаток такого метода в том, что не будут работать некоторые функции и библиотеки, использующие таймер 1. Например, ШИМ.

Если с программированием регистров сложно, а прерывание по таймеру использовать интересно —

Прерывание по таймеру с «человеческим лицом»

Добрые люди написали программный интерфейс к таймеру в виде библиотеки TimerOne

Библиотеку с таймером TimerOne можно скачать здесь

Ну, и напоследок, код для тех, кто как и я «грызет» программирование WiFi модулей ESP8266 в среде Arduino IDE.

Прерывание по таймеру в ESP8266

Там другие добрые люди прямо в ядро ESP для Arduino встроили библиотеку Ticker

Использовать прерывания в ESP следует осторожно, так как очень часто это вызывает срабатывание злобного сторожевого таймера WDT, который считает,  что на обработку встроенных WiFi функций выделяется слишком мало времени.

Надеюсь, эта статья будет немного полезной для любителей помигать светодиодами )))

2002

Вы можете оставить отзыв или трекбек со своего сайта.

6 комментариев на ««Умное» мигание светодиодом в Ардуино»

  1. Владимир:

    Отличная статья! За библиотеку для работы с таймером отдельное спасибо!

  2. Евгений:

    Огромное спасибо за изложенный материал!
    Мне очень помогла данная статья. Искал пример реализации прерывания по таймеру для esp8266 и наткнулся на вашу статью.
    🙂

  3. Zeddy:

    Спасибо за статью, полезная.

    Подумалось, что для индикации режимов можно использовать RGB светодиод, поскольку человеческий глаз различает достаточное количество цветов и оттенков (навскидку, основных цветов + оттенков, различимых всеми, думаю, 255 наберется). Конечно, нужны еще 3 пина, но можно их подключить через микросхему сдвига (будем задействован 1 пин).
    В случае RGB светодиода можно завязать интенсивность цвета на какой-то из параметров. Например, температура: бледно светим синим при низкой температуре, интенсивнее при повышении, при переходе определенной границы, начинаем светить бледным красным. Светим ярко-красным когда горячо.

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

  4. Андрей:

    Всё хорошо, но что за типы данных uint8_t, uint16_t и uint32_t? В описании по программированию ардуино такого не нашёл…

    • Alexey Alexey:

      uint8_t = unsigned short int; — 1 байт
      uint16_t = unsigned int; — 2 байта
      uint32_t = unsigned long int; — 4 байта

Ваш отзыв