
Рано или поздно любой ардуинщик приходит к идее автоматизировать управление домашним медиацентром или кондиционером. И здесь начинаются грабли: один протокол шлет повторы, другой требует тройной отправки, третий — инверсии контрольного бита.
Разбираемся с библиотекой IRremote — мощным инструментом, который берет на себя всю низкоуровневую магию NEC, Sony SIRC и Philips RC5/6 и прочих, да еще оставляет пространство для тюнинга. От захвата «сырых» данных до эмуляции редких или «безымянных» пультов — создаем по‑настоящему обучаемый контроллер.
Содержание
→ Как отправить
→ Как получить
→ Настройка
→ Коротко о структуре ИК‑команд
→ Работа с «сырыми» данными
→ Считываем коды нашего пульта
→ Как работает прием
→ Как работает отправка
→ Добавление новых протоколов
→ Поиск неисправностей
→ В заключение
Для работы проще всего воспользоваться менеджером библиотек Arduino IDE. Исходники лежат на GitHub. Код не модифицировался много лет, но продолжает поддерживаться автором — он просит сообщать о проблемах.
Как отправить
Архитектура библиотеки разделена на две части: IRsend отвечает за передачу ИК‑пакетов, а IRrecv берет на себя прием и декодирование сообщений. Передатчик использует ИК‑светодиод, подключенный к третьему пину. Чтобы отправить команду, достаточно вызвать метод send для выбранного протокола, указав сами данные и их разрядность. Самый простой пример такой отправки — в examples/IRsendDemo:
#include <IRremote.h> IRsend irsend; void setup() { Serial.begin(9600); } void loop() { if (Serial.read() != -1) { for (int i = 0; i < 3; i++) { irsend.sendSony(0xa90, 12); // Код управления питанием телевизора Sony задержка(100); } } }
Здесь Arduino превращается в пульт управления: стоит отправить любой символ в последовательный порт — и микроконтроллер отреагирует ИК‑кодом включения или выключения телевизора Sony. Учтите нюанс протокола: для Sony команды необходимо передавать трижды, иначе устройство их просто проигнорирует.
Как получить
Для приема сигналов IRrecv задействует ИК‑детектор, который можно подключить к любому цифровому пину. Схема соединения и базовый принцип работы с входящими кодами наглядно разобраны в примере examples/IRrecvDemo:
#include <IRremote.h> int RECV_PIN = 11; IRrecv irrecv(RECV_PIN); decode_results результаты; void setup() { Serial.begin(9600); irrecv.enableIRIn(); // Запуск приемника } void loop() { if (irrecv.decode(&results)) { Serial.println(results.value, HEX); irrecv.resume(); // Получить следующее значение } }
IRrecv инициализируется командой enableIRIn() и берет на себя все заботы по декодированию. Чтобы проверить, пришел ли новый сигнал, используется метод decode(). Если ИК‑пакет успешно принят, функция вернет ненулевое значение и сохранит данные в структуре decode_results — ее подробное устройство можно изучить в examples/IRrecvDump.
Важный момент: после обработки каждого кода надо обязательно вызывать resume(), иначе приемник «зависнет» и перестанет реагировать на новые команды. При этом decode() не блокирует выполнение программы — коды принимаются обработчиком прерывания. Пока он «слушает эфир», могут спокойно выполняться любые другие задачи.
Настройка
Для работы подойдет любой цифровой пин Arduino, способный принять сигнал от ИК‑приемника на 38 кГц. Библиотека отлично себя показала с модулями Radio Shack 276‑640 и Panasonic PNA4602. Подключение стандартное: первый контакт — к питанию, второй — к земле, а третий (выход) — к цифровому входу, например, к 11‑му пину.
Важно
Обычные фотодиоды или фототранзисторы здесь не справятся. Нужен именно специализированный приемник. Он сам фильтрует помехи и выдает на выходе чистый демодулированный сигнал в инвертированной логике. Такие детекторы видят на приличном расстоянии и уверенно покрывают всю комнату.

Для вывода сигнала ИК‑светодиод подключается через токоограничивающий резистор к третьему пину (PWM). Важно не перепутать полярность: длинная ножка светодиода — это анод. В тестовой сборке с ИК‑диодом NTE 3027 и резистором на 100 Ом дальность передачи составила около 4,5 метров. Если этого мало и нужно «пробивать» дальше, придется усилить сигнал, добавив выходной каскад с транзистором.
Коротко о структуре ИК‑команд
ИК‑пульт передает команды, включая и выключая светодиод в строго определенной последовательности. Чтобы солнечный свет или комнатные лампы не создавали помех, сигнал модулируют — светодиод вспыхивает не постоянно, а с высокой частотой (обычно 36, 38 или 40 кГц). Состояние, когда идет модулированный сигнал, называют «меткой», а период бездействия светодиода — «паузой».
При нажатии кнопки пульт передает уникальный код длиной от 12 до 32 бит. Если удерживать клавишу, большинство пультов просто повторяют эту посылку. Однако протокол NEC работает иначе: вместо дублирования основного кода он транслирует короткую специальную метку повтора. В пультах Philips RC5 и RC6 используется другой механизм — контрольный бит, который меняет состояние при каждом новом нажатии. Так приемник понимает, держит ли пользователь кнопку или нажал на нее несколько раз подряд.
Для тех, кто хочет глубже зарыться в теорию и изучить структуру ИК‑кодов разных производителей, пригодится база знаний SB IR — лучший справочник из всех, что попадались.
Приемник демодулирует входящий поток и превращает его в обычный логический сигнал: есть несущая частота — на выходе «единица», нет — «ноль». В идеале частоты передатчика и детектора должны совпадать, но на практике небольшое расхождение не критично.
Работа с «сырыми» данными
Библиотека умеет работать с «сырыми» данными, просто опираясь на длительность передаваемых и принимаемых импульсов. В первую очередь это нужно для отладки, но пригодится и в других случаях — например, если нужный протокол не поддерживается или нужен вообще уникальный.
Измеряется длительность меток и пауз с шагом в 50 мкс. Отсчет начинается с первой паузы — промежутка перед началом передачи, а завершается финальной меткой.
Для отправки ИК‑сигнала в сыром формате используются значения длительности меток и пауз, выраженные напрямую в микросекундах. Массив данных открывается первой меткой и завершается последней.
Форматы буферов для приема и отправки различаются в двух деталях. При отправке используются микросекунды, а для приема — такты по 50 мкс. Кроме того, буфер отправки открывается первой «меткой», тогда как буфер приема фиксирует еще и паузу перед началом сигнала.
Разница в точности обоснована технически. При чтении для уверенного декодирования вполне достаточно шага в 50 мкс. Заодно промежутки защищены от переполнения. А вот при передаче погрешность может запросто превысить 10%, что критично для многих устройств. По этой причине для исходящих сигналов выбрана микросекундная точность.
Считываем коды нашего пульта
Простейший способ получить рабочие коды — заставить саму библиотеку считать и расшифровать сигналы с пульта.
В сети полно баз ИК‑кодов, но многие из них закрыты или используют проприетарные форматы. Если нужно открытое решение, то пригодится проект LIRC (Linux Infrared Remote Control) — там собраны описания команд для сотен устройств. Если какой‑то конкретной модели нет в списке, то не страшно — производители часто используют одну и ту же систему кодирования для всей линейки своих продуктов.
Нужно иметь в виду: разные справочники могут трактовать одни и те же протоколы по‑своему. Кто‑то меняет порядок бит, кто‑то инвертирует логические уровни, а кто‑то по‑разному учитывает стартовые и стоповые биты. Если данные из библиотеки не совпадают со значениями из других источников — причина, скорее всего, именно в этих тонкостях интерпретации.
Как работает прием
IRrecv, приемная часть библиотеки, работает в два этапа. Сначала прерывание каждые 50 мкс измеряет длительность «меток» и «пауз», аккуратно складывает результаты в буфер. В какой‑то момент пользователь вызывает подпрограмму декодирования. Она берет накопленные замеры и превращает их в готовое число — тот самый код длиной от 11 до 32 бит.
Алгоритм поочередно прогоняет сигнал через декодеры разных протоколов и останавливается, как только находит подходящий. На выходе получается структура данных, в которой хранятся:
«сырые» данные,
итоговый декодированный код,
его разрядность,
название взятого протокола.
Для декодирования используется макрос MATCH. Он проверяет, укладывается ли измеренная длительность «метки» или «паузы» в допустимый диапазон ожидаемого времени.
Декодирование RC5/6 устроено иначе. Значение бита определяет не длительность импульса, а последовательность «метка + пауза» или «пауза + метка». Чтобы разобраться с такой логикой, используется вспомогательный метод getRClevel — он анализирует временны́е интервалы и определяет логический уровень сигнала для каждого конкретного такта.
При удержании кнопки декодер будет раз за разом выдавать одно и то же значение. Исключение — протокол NEC, который вместо дублирования основного кода отправляет короткую специфическую метку. В этом случае процедура декодирования вернет константу REPEAT.
Немного технических подробностей
Обработчик прерываний срабатывает каждый раз, когда переполняется таймер
TIMER1, настроенный на интервал в 50 мкс. При каждом таком «тике» система проверяет состояние входного пина и инкрементирует счетчик.Задача подпрограммы — измерить чистую длительность «меток» (когда идет модулированный сигнал) и «пауз» (когда сигнала нет), после чего сохранить эти значения в буфер.
Запись всегда начинается с предварительной паузы перед пакетом данных, а далее следуют чередующиеся замеры импульсов и промежутков. Все данные в буфере хранятся не в секундах, а в количестве тех самых 50‑микросекундных «тиков».
Обработчик прерываний реализован как конечный автомат. В режиме ожидания он находится в состоянии STATE_IDLE. Как только фиксируется первая «метка», система переключается в STATE_MARK для замера ее длительности. Далее автомат циклично переходит между STATE_MARK и STATE_SPACE, фиксируя каждый импульс и промежуток. Если же пауза затягивается и превышает установленный порог, активируется состояние STATE_STOP — сигнал о том, что пакет данных принят полностью. В этом режиме прерывание продолжает отсчитывать время, но новые данные в буфер не записываются до сброса флага.
Флаг STATE_STOP служит сигналом для декодера: «Пакет принят полностью, можно обрабатывать». Как только работа с данными окончена, необходимо вызвать метод resume() — он вернет систему в состояние STATE_IDLE, разрешая прерыванию записывать следующую команду.
Стоит учесть пару важных моментов:
Подсчет пауз. Даже в состояниях
STOPиIDLEтаймер продолжает тикать — что позволяет библиотеке точно измерять интервалы между отдельными посылками.Защита буфера. Если не вызвать
resume()вовремя, новая передача будет просто проигнорирована. Такая логика «стоп‑старт» гарантирует, что буфер не перезапишется прямо посреди процесса декодирования — без этого отладка превратилась бы в кошмар из‑за постоянно меняющихся данных.
Как работает отправка
Логика отправки устроена довольно просто. Чтобы добиться точной несущей частоты и правильной скважности, используется аппаратный ШИМ‑таймер, а не обычные программные задержки.
На низком уровне это работает так.
Функция
enableIROutнастраивает таймер для генерации ШИМ‑сигнала на 3‑м пине с нужной частотой (обычно 38 кГц).Метод
mark()формирует «метку»: он включает ШИМ‑выход и удерживает его активным заданное время.Метод
space()формирует «паузу»: он просто отключает ШИМ на указанный интервал.
IRremote работает с популярными протоколами, учитывая их специфику.
NEC — передает 32 бита, начиная со старшего (MSB).[описание]
Sony — обычно использует 12 или 20 бит (MSB). Стоит учесть, что в официальной документации Sony принят обратный порядок — младшим битом вперед (LSB), но библиотека приводит их к стандартному виду.[описание, объяснение]
RC5 — передает от 12 бит (MSB). Сообщение всегда открывается двумя стартовыми битами, которые не включаются в итоговое значение кода.[описание]
RC6 — стандартно передает 20 бит (MSB). Посылка начинается с ведущего импульса и стартового бита. Особенность протокола — четвертый бит (контрольный), который в два раза шире остальных.[описание]
Для протоколов Sony и RC5/6 стандарт требует троекратного повторения каждой посылки. Обратите внимание: библиотека не управляет «битом переключения» в автоматическом режиме — логику его изменения при каждом новом нажатии нужно реализовать в основном коде программы.
Добавление новых протоколов
Существует огромное количество протоколов, и библиотека поддерживает лишь часть из них. Однако архитектура позволяет легко добавить новый формат, опираясь на готовые примеры в коде.
Вот несколько советов по «реверс‑инжинирингу»:
ищите документацию — намного проще работать с готовым описанием таймингов, чем пытаться восстановить их с нуля по осциллограммам;
делайте поправку на физику — реальные замеры часто показывают «метки» чуть длиннее, а «паузы» — короче, чем указано в спецификации.
внимание к финалу — легко ошибиться в последнем бите: завершающая пауза часто бывает неявной и не фиксируется библиотекой как отдельное событие.
Поиск неисправностей
Для упрощения поиска ошибок в ИК‑связи в библиотеку встроен режим отладки. Чтобы его активировать, нужно поместить строку #define DEBUG в самое начало скетча — тогда подробная техническая информация будет выводиться прямо в консоль.
Важно
После добавления этой директивы может потребоваться принудительная перекомпиляция. Для этого должны быть удалены объектные файлы из папки сборки или перезапущена среда разработки.
Проблемы с передачей
Если передача не работает, первым делом надо проверить: а излучает ли что‑то ИК‑светодиод? Человеческий глаз не воспринимает инфракрасную часть спектра, но большинство камер мобильных телефонов видят ее отлично. Достаточно посмотреть на светодиод через экран смартфона — тот должен мигать фиолетовым или белым светом.
Также стоит попробовать поднести светодиод вплотную к приемнику. Без использования транзисторного усилителя дальность сигнала будет минимальной, так что для тестов «на столе» дистанция имеет решающее значение.
Другая распространенная проблема — приемник «не узнает» передатчик из‑за неверных данных или ошибки в выборе протокола. Самый надежный способ проверить это — взять оригинальный пульт от устройства и с помощью этой же библиотеки посмотреть, какие именно коды и в каком формате тот отправляет на самом деле.
Осциллограф — лучший способ наглядно увидеть, что именно передает Arduino или пульт. Чтобы поймать сигнал, подойдет обычный ИК‑фотодиод, подключенный напрямую к щупам осциллографа — его надо вплотную поднести к передатчику.
Если профессионального прибора под рукой нет — не беда. Можно воспользоваться программным осциллографом, работающим через звуковую карту компьютера — например, xoscope.
Выше уже отмечалось, что протоколы Sony и RC5/6 требуют, чтобы каждая команда отправлялась трижды. На практике же приемники часто игнорируют одиночную посылку, но срабатывают уже со второго раза.
Особое внимание — биту переключения в протоколах RC5/6. Его значение нужно менять программно при каждом новом нажатии кнопки. Если этого не делать, устройство решит, что вы просто удерживаете клавишу, и выполнит команду лишь один раз.
И последнее: в библиотеке все же могут встречаться ошибки. В частности, это касается протоколов RC5 и RC6 — на момент написания под рукой не нашлось подходящего приемника, чтобы протестировать их в реальных условиях.
Проблемы с приемом
Если прием сигнала не работает, первым надо проверить: видит ли Arduino хоть какой‑то входящий трафик. В библиотеку встроена простая индикация: при каждом получении ИК‑импульса должен мигать штатный светодиод на 13‑м пине. Если при нажатии кнопок на пульте он остается безжизненным, то, скорее всего, проблема в аппаратном подключении или неисправности самого ИК‑приемника.
Если библиотека видит сигнал, но не может его распознать, надо выяснить: входит ли протокол пульта в список поддерживаемых. Если декодирование все равно не срабатывает, скорее всего, реальные тайминги сигнала выходят за рамки 20%‑ной погрешности, заложенной в алгоритм.
Чтобы во всем разобраться, можно вывести в консоль ожидаемые минимальные и максимальные значения для конкретного протокола и сравнить их с «сырыми» замерами, которые выдает приемник.
Скетч‑пример examples/IRrecvDump выводит детальный отчет о каждом принятом сигнале. Заслуживает внимания формат: библиотека автоматически пересчитывает «тики» в микросекунды, а для наглядности добавляет знак минуса перед каждым значением паузы. Благодаря этому в консоли сразу видно, где был активный импульс, а где — пустой промежуток.
Обычно ИК‑датчики вносят свои искажения. «Метки» на выходе кажутся длиннее, чем они есть на самом деле, а «паузы» между ними — короче. Для исправления библиотека автоматически вносит поправку — вычитает из каждой метки 100 мкс (константа MARK_EXCESS). Если какой‑то датчик работает слишком специфично, может потребоваться вручную подправить ожидаемые значения или расширить допуски в настройках.
Одновременный обмен в обе стороны не поддерживается. Как только начинается передача сигнала — прием автоматически отключается.
В заключение
Библиотека уже нашла применение в самых разных проектах — от простых игрушек до систем автоматизации.
Управление пешеходным знаком с помощью пульта дистанционного управления.
Расширение для использования произвольных пультов ДУ .
Управление стереосистемой через интернет.
Реализация «универсального пульта дистанционного управления» для записи и воспроизведения ИК‑кодов.
Управление с пульта в проекте по созданию мыльных пузырей с помощью инфракрасного излучения.
Переосмысление пульта ДУ — использование ультразвукового датчика для управления телевизором взмахом руки.
История создания библиотеки началась с вдохновения статьей «Создание универсального пульта дистанционного управления на Arduino». Хотя тот проект не претендовал на полную универсальность, он содержал важный теоретический базис.
Ключевым технологическим донором стала библиотека NECIRrcv — именно ее код послужил фундаментом для реализации обработчика прерываний.

