Модуль ИК Приемника в связке и ИК пультом дистанционного управления позволит легко реализовать дистанционное управление платой Arduino.

Он представляет из себя не что иное, как ИК приемник VS1838B с установленной на плате рекомендуемой производителем обвязкой.

Для работы с данным модулем "из коробки" необходим ПДУ с частотой 38 кГц.

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

Основные технические характеристики:

Напряжение питания: 2.7 - 5.5В

Частота модуляции: 38кГц

Диапазон температур: - 20 ... + 80°C

Интерфейс: Цифровой

Подключение к Arduino

Модуль оборудован трехпиновым разъемом стандарта 2.54мм

: подключается к выводу GND

: подключается к выводу +5V

: подключается к цифровому выводу (в примере D2)

Пример работы в среде Arduino

Для работы с данным модулем необходимо установить библиотеку IRRemote

Скачиваем, распаковываем и закидываем в папку libraries в папке Arduino. В случае, если на момент добавления библиотеки, Arduino IDE была открытой, перезагружаем среду.

Считывание показаний кнопок ПДУ

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

В качестве примера будем использовать пульт, как на картинке, т.к. пульт такого типа идет в наборе

Про отличия в логике работы различных пультов можно прочитать в статье-оригинале от члена нашего сообщества под ником

Пример программного кода:

#include int RECV_PIN = 2; IRrecv irrecv(RECV_PIN); //Создаем объект получения сигнала с определенного порта decode_results results; //Переменная, хранящая результат void setup () { Serial // Начинаем прием } void loop () { if (irrecv.decode(&results)) //При получении сигнала... { Serial .println (results.value); //…выводим его значение в последовательный порт irrecv.resume(); } }

В мониторе порта должны увидеть слудущее:

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

Управление платой Arduino c ПДУ

Заставим светодиод на плате Arduino (D13) загораться при получении кодировки первой кнопки и выключаться при получении кодировки второй.

Пример программного кода:

// Тестировалось на Arduino IDE 1.0.3 #include int RECV_PIN = 2; int LED = 13; IRrecv irrecv(RECV_PIN); decode_results results; void setup () { Serial .begin (9600); irrecv.enableIRIn(); // Запуск приемника pinMode (LED, OUTPUT ); } void loop () { if (irrecv.decode(&results)) { Serial .println (results.value); if (results.value == 16769565) // При получении кодировки 1 { digitalWrite (LED, HIGH ); // Включаем светодиод } if (results.value == 16761405) // При получении кодировки 2 { digitalWrite (LED, LOW ); // Выключаем светодиод } irrecv.resume(); // Получаем следующее значение } }
  • Tutorial

Устройства с управлением от инфракрасного пульта тесно вошли в нашу жизнь. Иногда пульт от телевизора или древней аудиосистемы теряется, а купить новый за давностью лет уже невозможно. Заказать новый пульт не всегда возможно, изготовить клон тоже, но обладая донором или информацией о нём можно изготовить конвертер. Такой транскодер будет принимать команды одного пульта и транслировать их в формат другого.

Для Arduino существует прекрасная библиотека IRemote которая делает построение разнообразных ИК систем управления очень простым. Но при решении даже такой простой задачи как транскодер обязательно находятся проблемы которые интересно решать.
Итак для начала нам необходим интегральный ИК приёмник типа TSOP312 или соответствующий шилд для Arduino. Не стоит забывать что ИК приёмников существует очень много и цоколёвка у них меняется случайным образом. Например я использовал некий безымянный элемент по цоколёвке совпадающий с TSOP382 но в уменьшенном корпусе и без разделительного ключа.

Собранная схема нужна нам для получения кодов команд от обеих пультов, к несчастью снять команды с устройства для которого пульт утерян несколько сложнее. Вы можете всё-таки найти пульт донор, воспользоваться универсальным пультом подобрав код (а зачем тогда вам тогда транскодер, раз уж пульт подошёл?) или попытавшись воспользоваться данными из интернет баз по IR кодам. Самым простым для меня оказалось воспользоваться приложением под андроид, эмулирующий нужный мне пульт.
Для чтения данных используем пример IRrecvDumpV2 из поставки IRremote, если ваш пульт относится к распознаваемым библиотекой то сырой результат сканирования вам не понадобится, хотя например пульт от LG у меня ложно распознавался как Samsung и не заработал при попытке отправлять команды через sendLG.

Пример полученных данных под спойлером:

Encoding: SAMSUNG
Code: 34346897 (32 bits)
Timing:
+4450, -4350 + 600, - 500 + 600, - 500 + 600, -1600

+ 600, - 500 + 600, - 500 + 600, - 500 + 600, -1600
+ 600, -1600 + 600, - 500 + 600, -1600 + 600, - 500
+ 600, - 500 + 600, - 500 + 600, -1600 + 600, -1600
+ 600, - 500 + 600, -1600 + 600, - 500 + 600, - 500
+ 600, - 500 + 550, -1650 + 550, - 550 + 550, - 550
+ 550, -1650 + 550, - 550 + 550, -1650 + 550, -1600
+ 600, -1600 + 600
unsigned int rawData = {4450,4350, 600,500, 600,500, 600,1600, 600,1600, 600,500, 600,1600, 600,500, 600,500, 600,500, 600,500, 600,1600, 600,1600, 600,500, 600,1600, 600,500, 600,500, 600,500, 600,1600, 600,1600, 600,500, 600,1600, 600,500, 600,500, 600,500, 550,1650, 550,550, 550,550, 550,1650, 550,550, 550,1650, 550,1600, 600,1600, 600}; // SAMSUNG 34346897
unsigned int data = 0x34346897;


В случае если захват выдаёт сообщение “IR code too long. Edit IRremoteInt.h and increase RAWLEN” библиотеку придётся немного исправить - увеличив размер буфера для команд. Для пульта которым планируется управлять достаточно знать 32 битный код команды, стоит обратить внимание что на некоторых пультах код зажатой клавиши отличается от той же кнопки в режиме нажал и отпустил. Такие кнопки потребуют двух значений. Сводим полученные коды в удобную для вас таблицу. В ту же таблицу сохраняем коды для пульта донора в сыром виде.
Подключаем к Arduino инфракрасный светодиод и пишем простейшую программу которая получает инфракрасный сигнал с заданным кодом и отправляет другой код через светодиод. Резистор на 82 выбран из соображений того что валялось под рукой. Для встраиваемого устройства его можно смело увеличивать до 200 Ом а если передатчик должен быть дальнобойным то придётся дополнить его нехитрым транзисторным каскадом, иначе тока от Arduino обязательно не хватит.


При наличии кодов команд от обеих пультов код транскодера приобретает следующий вид

Void loop() { if (irrecv.decode(&results)) { switch(results.value){ case(0x845E5420):{ irsend.sendRaw(irSignal, sizeof(irSignal) / sizeof(irSignal), khz); }break; } } irrecv.resume(); irrecv.enableIRIn(); }
Запускаем скетч, заливаем в Arduino. Как ни странно после запуска одна команда проходит, после чего все последующие устройством игнорируются. Чтобы не связываться с отладкой добавляем в цикл мигалку на 13 пине и видим что после первой попытки отправить команду плата зависает. Что же, значит не всё так гладко в одновременном использовании передачи и приёма ИК сигнала в одном проекте. Немного покопавшись в используемых таймерах выясняется что так как и отправка и приём использует общий таймер то после начала отправки код должен подождать пока отправка не закончится. Можно эмпирически добавить задержку в пол секунды (delay(500))и всё будет работать, но зная что сырые данные у нас представляют собой отсчёты времени в миллисекундах то можно просто добавить функцию отправки с задержкой. В модуле Irsend есть даже подходящая функция custom_delay_usec, которой я изначально воспользовался неправильно, забыв домножить величину задержки на множитель USECPERTICK из библиотеки (50 мс).

Void sendDelayed(unsigned int array){ irsend.sendRaw(array, sizeof(array) / sizeof(array), khz); int array_size = sizeof(array) / sizeof(array); for(int i=0;i Такой код отлично работает, в switch теперь достаточно вписать нужное число case для кнопок и всё будет работать. Но не тут то было. Коды rawData записываются в виде массива int а у нас платформа на микроконтроллере. Память для переменных будет съедена уже пятью командами длиной по 100 элементов. А ведь на пультах бывает и по 25 кнопок.
Проблемы нет если не пользоваться сырым представлением данных, для этого в библиотеке есть возможность слать команды известными протоколами, например для пультов совместимых с Sony это sendSony. В библиотеке уже реализованы пульты известных производителей, но с ходу разобраться с моим пультом у меня не получилось. Поэтому переходим к более примитивным способам экономии памяти которые помогут тем у кого пульты совсем уж нестандартные.
Первое что приходит в голову это задавать rawData не в виде int, а перейти на байт. Все значения в этом массиве это результат чтения ИК сигнала таймером с периодом 50 миллисекунд, а так как эти данные кратны 50, то разделив их на 50 мы ничего не потеряем. Верхний предел будет ограничен значением 50*255=12750, а это 12 секунд, чего будет достаточно даже для декодирования неспешной азбуки Морзе - если такая необходимость возникнет.
В библиотеку был добавлен метод принимающий на вход байты, что сократило потребления памяти вдвое

IRsend::sendRaw (byte buf, unsigned int len, unsigned int hz)
Только вот памяти под переменные у Arduino всего два килобайта а это максимом 40 команд по 50 байтов. Нам необходимо больше памяти. И эту память мы извлечём из сегмента команд. Достаточно зарезервировать один массив достаточного размера и набивать его перед отправкой чередой присваиваний. Итого из кодового сегмента на одну команду будет тратиться около 100 байт, но ведь и места для кода у нас не меньше десяти килобайт. Так что на средний пульт со ста кнопками нам уже хватит.
Дабы не набивать руками присваивания в библиотеку был добавлен пример IRrecvDumpRawByte который выводит сырые данные не только в форме байтов но и в виде блока присваиваний

Пример под спойлером

rawData=87;rawData=87;rawData=10;rawData=9;rawData=10;rawData=9;rawData=10;rawData=10;rawData=10;rawData=9;rawData=10;rawData=9;rawData=10;rawData=29;rawData=10;rawData=9;rawData=10;rawData=9;rawData=10;rawData=10;rawData=10;rawData=9;rawData=10;rawData=9;rawData=10;rawData=10;rawData=10;rawData=9;rawData=10;rawData=9;rawData=10;rawData=10;rawData=10;rawData=9;rawData=10;rawData=86;rawData=10;rawData=9;rawData=11;rawData=9;rawData=10;rawData=9;rawData=10;rawData=9;rawData=10;rawData=28;rawData=10;rawData=29;rawData=10;rawData=28;rawData=10;rawData=9;rawData=10;rawData=28;rawData=10;rawData=10;rawData=10;rawData=9;rawData=10;rawData=28;rawData=10;rawData=10;rawData=10;rawData=9;rawData=10;rawData=9;rawData=10;rawData=28;rawData=10;rawData=9;rawData=11;rawData=27;rawData=10;rawData=29;rawData=10;rawData=9;rawData=10;


Пример уже написанного скетча который позволяет управлять Samsung DVD HR-755 при помощи пульта Daewoo R40A01 находится в примерах под именем DaewooR40A01toDVDHR755Transcoder. Pull request на добавление примеров в общую ветку пока никто не принял поэтому скачать модифицированную библиотеку можно с форка .

Много фото с переделанным рекордером





















Под катом находятся фотографии интеграции Arduino Nano внутрь этого DVD рекордера, Arduino Mini конечно занимает ощутимо меньше места, но под рукой была только Nano. Питание я взял с панели управления. Сигнал со встроенного приёмника был подключен к Arduino а параллельно ему был напаян ещё один ИК приёмник, расположенный с противоположной стороны от первого. Тем же навесным монтажом на него был напаян ИК светодиод. В принципе этого повторения можно было бы избежать - но сигнал с ИК приёмника инвертирован - поэтому напрямую завести ТТЛ сигнал на устройство не получится - а городить инвертор на логике или транзисторе я уже не стал.

Несмотря на то, что в моём случае сырые данные отлично работали, эксперименты с остальным домашним оборудованием показали что далеко не все захваченные сигналы корректно работали при попытке управления конкретным устройством. Команда включения кондиционера так и не заработала, хотя если он был уже включён смена режимов работала корректно. Колонка от LG тоже отказалась воспринимать сырые команды, но отлично реагировала на отправку кодов через sendSamsung. При этом пять собранных по знакомых телевизора отлично реагировали на сырые данные. Вариант с разной частотой сигнала я опробовал - это никак не помогло. Возможно проблема лежит в частоте дискретизации сигнала в 50 мс. Судя по работоспособности команд формата Samsung на технике LG, протокол стоит формализовать в виде отдельного модуль по аналогии с ir_LG.cpp ir_JVC.cpp ir_Dish.cpp, подобрав для конкретного устройства заголовок и параметры кодирования нулей и единиц. Наверное разбор написания такого протокола послужит неплохой темой для статьи.

Ну и в дополнение, вторая большая ИК библиотека для Arduino это

Рассмотрим на этом занятии подключение ИК приемника к Ардуино. Расскажем какую библиотеку следует использовать для IR приемника, продемонстрируем скетч для тестирования работы инфракрасного приемника от пульта дистанционного управления и разберем команды в языке C++ для получения сигнала. Сразу отметим, что IR датчик Ардуино подходит не к каждому пульту, частота сигнала может отличаться.

Устройство ИК приемника. Принцип работы

Приемники инфракрасного излучения получили сегодня широкое применение в бытовой технике, благодаря доступной цене, простоте и удобству в использовании. Эти устройства позволяют управлять приборами с помощью пульта дистанционного управления и их можно встретить практически в любом виде техники. Но, несмотря на это, постепенно Bluetooth модуль набирает все большую популярность.

Принцип работы IR ресивера. Обработка сигнала от пульта ДУ

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

Под действием инфракрасного излучения в фотодиоде, у которого между p и n областями создана дополнительная область из полупроводника (i -область), начинает течь ток. Сигнал поступает на усилитель и далее на полосовой фильтр, который настроен на фиксированную частоту: 30; 33; 36; 38; 40 и 56 килогерц и защищает приемник от помех. Помехи могут создавать любые бытовые приборы.

Чтобы сигнал от пульта ДУ принимался ИК приемником Ардуино, пульт должен быть с той же частотой, на которую настроен фильтр в IR приемнике. Поэтому не каждый пульт дистанционного управления подойдет для работы. Следует подбирать IR приемник и IR передатчик с одной частотой. После фильтра сигнал поступает на амплитудный детектор, интегрирующий фильтр и выходной транзистор.

Как подключить ИК приемник к Ардуино

Корпуса инфракрасных приемников содержат оптический фильтр для защиты прибора от внешних электромагнитных полей, изготавливаются они специальной формы для фокусировки принимаемого излучения на фотодиоде. Для подключения IR приемника к Arduino UNO используют три ножки, которые соединяют с — GND, 5V и A0. Советуем для начала использовать 3,3 Вольта, чтобы не сжечь ИК датчик при настройке.

Для занятия нам понадобятся следующие детали:

  • плата Arduino Uno / Arduino Nano / Arduino Mega;
  • макетная плата;
  • IR приемник;
  • пульт ДУ;
  • 1 светодиод и резистор 220 Ом;
  • провода «папа-папа» и «папа-мама».


Схема подключения ИК приемника к аналоговому порту Ардуино

Подключите IR приемник по схеме, представленной выше, и подключите светодиоды к 12 и 13 пину. Перед загрузкой программы, вам потребуется установить библиотеку IRremote.h, если она не была еще установлена. Данная библиотека не относится к стандартным библиотекам среды программирования Arduino IDE. Скачать библиотеку IRremote.h и готовый скетч можно одним архивом с Google Диск по ссылке .

Скетч для ИК приемника Arduino:

#include // подключаем библиотеку для IR приемника IRrecv irrecv(A0); // указываем пин, к которому подключен IR приемник decode_results results; void setup () // процедура setup { irrecv.enableIRIn (); // запускаем прием инфракрасного сигнала pinMode (13, OUTPUT ); // пин 13 будет выходом (англ. «output») pinMode (12, OUTPUT ); // пин 12 будет выходом (англ. «output») pinMode (A0, INPUT ); // пин A0 будет входом (англ. «intput») Serial .begin (9600); // подключаем монитор порта } void loop () // процедура loop { if (irrecv.decode (&results)) // если данные пришли выполняем команды { Serial .println (results.value); // отправляем полученные данные на порт // включаем и выключаем светодиоды, в зависимости от полученного сигнала if (results.value == 16754775) { digitalWrite (13, HIGH ); } if (results.value == 16769055) { digitalWrite (13, LOW ); } if (results.value == 16718055) { digitalWrite (12, HIGH ); } if (results.value == 16724175) { digitalWrite (12, LOW ); } irrecv.resume (); // принимаем следующий сигнал на ИК приемнике } }

Пояснения к коду:

  1. Библиотека IRremote.h содержит набор команд и позволяет упростить скетч;
  2. Оператор decode_results присваивает получаемым сигналам от пульта дистанционного управления имя переменной results .

ИК датчик можно применять во многих устройствах на микроконтроллере Ардуино, в том числе, можно сделать дистанционное управление сервоприводом на Ардуино от ИК приемника. При настройке следует включить монитор порта Arduino IDE и узнать какой сигнал отправляет та или иная кнопка на пульте ДУ. Полученные коды следует использовать в скетче после знака двойного равенства в условиях if () .

Записи по этой теме:


  • Входное напряжение: 2,7 ... 5,5 В
  • Потребляемый ток: 0,65 … 1,05 мА (при Vсс = 5В) номинально 0,9 мА
  • Несущая частота: 38 кГц
  • Длинна световой волны: 850 … 1050 нм (пропускаемая фильтром более 80%)
  • Чувствительность: 0,17… 30000 мW/м2 (к мощности светового потока)
  • Расстояние приёма: до 45 м
  • Рабочая температура: -25 … 85 °C
  • Угол направленности: ±45°

Все модули линейки "Trema" выполнены в одном формате

Подключение:

Модуль подключается к любому цифровому выводу arduino. В комплекте имеется кабель для быстрого и удобного подключения к Trema Shield .

Модуль удобно подключать 3 способами, в зависимости от ситуации:

Способ - 1: Используя проводной шлейф и Piranha UNO


Библиотека использует второй аппаратный таймер,

НЕ ВЫВОДИТЕ СИГНАЛЫ ШИМ НА 3 ИЛИ 11 ВЫВОД!

Подробнее про установку библиотеки читайте в нашей ..

Дополнительная информация по работе с модулем:

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

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

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

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

Длительность пауз между пакетами: обычно не превышает 200мс.

Протоколы передачи данных: определяют следующие, основные, параметры:

  • несущую частоту;
  • способ кодирования информации, длительность импульсов и пауз передаваемых битов;
  • количество информационных пакетов:
  • состав информационного пакета и пакетов повторов;
  • длительность пауз между пакетами;
  • наличие и форму сигналов Start, Stop и Toggle;

Несущая частота: у большинства пультов равна 38 кГц, именно на эту частоту настроен Trema ИК-приёмник .

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

  • кодирование длиной импульсов - сначала передаётся импульс, длина которого зависит от значения передаваемого бита, затем следует пауза, длина которой не зависит от значения бита. Например: в протоколе SIRC (Sony), длина импульса для бита «1» = 1200мкс, а для бита «0» = 600мкс, длина пауз всегда равна 600мкс. Таким образом можно отличить «1» от «0» по длине импульса.
  • кодирование длинной пауз - сначала передаётся импульс, длина которого не зависит от значения передаваемого бита, затем следует пауза, длина которой зависит от значения бита. Например: в протоколе NEC, длина паузы для бита «1» = 1687,5мкс, а для бита «0» = 562,5мкс, длина импульсов всегда равна 562,5мкс. Таким образом можно отличить «1» от «0» по длине паузы.
  • бифазное кодирование - длина импульса равна длине паузы, а их последовательность определяет тип передаваемого бита. Например: в протоколе RS5 (Philips), для бита «1» импульс следует за паузой, а для бита «0» пауза следует за импульсом. Для протокола NRC (Nokia), наоборот, для бита «1» пауза следует за импульсом, а для бита «0» импульс следует за паузой.

Сигналы Start, Stop и Toggle: по своему названию располагаются в начале, конце или середине пакета.

Stop: При кодировании длинной паузы, нельзя определить значение последнего бита в пакете, так как после пакета следует большая пауза, и последний бит будет всегда определяться как «1», поэтому в пакет добавляется сигнал Stop представляющий из себя импульс не несущий никакой информации.

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

Toggle: Это бит, который меняет своё значение при каждом новом нажатии на кнопку, используется в протоколах RS5, RS5X, RS6 (Philips), где пакеты повторов полностью повторяют данные информационного пакета. Таким образом принимающее устройство может отличить удержание кнопки от её повторного нажатия.

Примеры:

Проверка наличия данных поступивших с ИК-пульта , осуществляется функцией check(). Эта функция реагирует на нажатие кнопок ИК-пульта , но если её вызывать с параметром true , то она будет реагировать и на удержание кнопок.

Чтение данных с любого пульта, реагируем только на нажатие кнопок:

#include // Подключаем библиотеку для работы с ИК-приёмником iarduino_IR_RX IR(7); // Объявляем объект IR, с указанием вывода к которому подключён ИК-приёмник void setup(){ Serial.begin(9600); // Инициируем передачу данных в монитор последовательного порта, на скорости 9600 бит/сек IR.begin(); // Инициируем работу с ИК-приёмником } void loop(){ if(IR.check()){ // Если в буфере имеются данные, принятые с пульта (была нажата кнопка) Serial.println(IR.data, HEX); // Выводим код нажатой кнопки Serial.println(IR.length); // Выводим количество бит в коде } }

В данном скетче функция check() вызывается без аргументов, значит и реагирует она только на нажатия кнопок ИК-пульта .

Чтение данных с любого пульта, реагируем на удержание кнопок:

#include // Подключаем библиотеку для работы с ИК-приёмником iarduino_IR_RX IR(6); // Объявляем объект IR, с указанием вывода к которому подключён ИК-приёмник void setup(){ Serial.begin(9600); // Инициируем передачу данных в монитор последовательного порта, на скорости 9600 бит/сек IR.begin(); // Инициируем работу с ИК-приёмником } void loop(){ if(IR.check(true)){ // Если в буфере имеются данные, принятые с пульта (удерживается кнопка) Serial.println(IR.data, HEX); // Выводим код нажатой кнопки Serial.println(IR.length); // Выводим количество бит в коде } }

В данном скетче функция check() вызывается с параметром true , значит и реагирует она как на нажатия, так и на удержания кнопок ИК-пульта .

Чтение данных с любого пульта, с указанием как реагировать на какие кнопки.

#include // Подключаем библиотеку для работы с ИК-приёмником iarduino_IR_RX IR(6); // Объявляем объект IR, с указанием вывода к которому подключён ИК-приёмник // bool flgKey1 = false; uint32_t codKey1 = 0xFF30CF; // Определяем флаг нажатия и код кнопки 1 bool flgKey2 = false; uint32_t codKey2 = 0xFF18E7; // Определяем флаг нажатия и код кнопки 2 bool flgKey3 = false; uint32_t codKey3 = 0xFF7A85; // Определяем флаг нажатия и код кнопки 3 bool flgKey = false; uint32_t tmrKey = 0; // Определяем флаг разрещающий вывод данных в монитор и время последнего нажатия кнопки. // void setup(){ // Serial.begin(9600); // Инициируем передачу данных в монитор последовательного порта, на скорости 9600 бит/сек IR.begin(); // Инициируем работу с ИК-приёмником } // // void loop(){ // if(IR.check(true)){ // Если в буфере имеются данные, принятые с пульта (удерживается кнопка), то... if(millis()-200 > tmrKey){ // Если с последней поступившей команды прошло более 200 мс, то flgKey1=false; // Считаем что кнопка 1 не удерживается flgKey2=false; // Считаем что кнопка 2 не удерживается flgKey3=false; // Считаем что кнопка 3 не удерживается } tmrKey = millis(); flgKey=true; // Сохраняем время последней реакции на пульт и азрешаем вывод данных if(IR.data==codKey1){ if(flgKey1){flgKey=false;} flgKey1=true; }else{flgKey1=false;} // Запрещаем вывод данных кнопки 1 при её удержании if(IR.data==codKey2){ if(flgKey2){flgKey=false;} flgKey2=true; }else{flgKey2=false;} // Запрещаем вывод данных кнопки 2 при её удержании if(IR.data==codKey3){ if(flgKey3){flgKey=false;} flgKey3=true; }else{flgKey3=false;} // Запрещаем вывод данных кнопки 3 при её удержании if(flgKey){ // Если вывод данных разрешен, то... Serial.println(IR.data, HEX); // Выводим код нажатой кнопки Serial.println(IR.length); // Выводим количество бит в коде } // } // } //

В данном скетче функция check() вызывается с параметром true , значит она реагирует как на нажатия, так и на удержания кнопок ИК-пульта . Но вывод данных в монитор последовательного порта осуществляется только при установленном флаге flgKey , который сбрасывается при удержании кнопок с кодами 0xFF30CF , 0xFF18E7 и 0xFF7A85 . Получается что на 3 кнопки скетч реагирует только при нажатии, а на остальные кнопки, как на нажатие, так и на удержание.

Чтение данных только с тех пультов, которые работают по указанному протоколу:

#include // Подключаем библиотеку для работы с ИК-приёмником iarduino_IR_RX IR(5); // Объявляем объект IR, с указанием вывода к которому подключён ИК-приёмник void setup(){ Serial.begin(9600); // Инициируем передачу данных в монитор последовательного порта, на скорости 9600 бит/сек IR.begin(); // Инициируем работу с ИК-приёмником IR.protocol("Ae`` `|LJ` @@@@BPBp"); // Указываем протокол передачи данных, на который следует реагировать } void loop(){ if(IR.check(true)){ // Если в буфере имеются данные, принятые с пульта (удерживается кнопка) Serial.println(IR.data, HEX); // Выводим код нажатой кнопки Serial.println(IR.length); // Выводим количество бит в коде } }

В данном скетче, в коде setup(), указан протокол передачи данных, который редко совпадает у разных производителей ИК-пультов . Значит функция check() в коде loop() будет реагировать только на те ИК-пульты , которые поддерживают указанный протокол.

Получение протокола передачи данных и типа кодировки:

#include // Подключаем библиотеку для работы с ИК-приёмником iarduino_IR_RX IR(4); // Объявляем объект IR, с указанием вывода к которому подключён ИК-приёмник void setup(){ Serial.begin(9600); // Инициируем передачу данных в монитор последовательного порта, на скорости 9600 бит/сек IR.begin(); // Инициируем работу с ИК-приёмником } void loop(){ if(IR.check()){ // Если в буфере имеются данные, принятые с пульта (была нажата кнопка) Serial.println(IR.protocol()); // Выводим строку протокола передачи данных } }

В данном примере описано как получить протокол передачи данных ИК-пультов . В статье , описано, как передавать коды кнопок по указанному протоколу.

Таким образом, можно создать скетч ИК-передатчика для имитации сигналов различных ИК-пультов . В результате, устройства будут реагировать на ИК-передатчик , как на собственный ИК-пульт .

Описание основных функций библиотеки:

Подключение библиотеки:

#include // Подключаем библиотеку, для работы с ИК-приёмником. iarduino_IR_RX IR(№_ВЫВОДА [, ИНВЕРСИЯ]); // Объявляем объект IR, с указанием номера вывода, к которому подключён ИК-приёмник. // Вторым параметром, типа bool, можно указать, что данные с приёмника являются инверсными.

Функция begin();

  • Назначение: инициализация работы с ИК-приёмником
  • Синтаксис: begin();
  • Параметры: Нет.
  • Возвращаемые значения: Нет.
  • Примечание: Вызывается 1 раз в коде setup.
  • Пример:
IR.begin(); // Инициируем работу с ИК-приёмником

Функция check();

  • Назначение: Проверка наличия принятых с пульта данных.
  • Синтаксис: check([ УДЕРЖАНИЕ ]);
  • Параметры:
    • УДЕРЖАНИЕ - необязательный параметр, типа bool - указывающий что необходимо реагировать на удержание кнопок пульта.
  • Возвращаемые значения: bool - приняты или нет, данные с пульта.
  • Примечание: Если функция вызвана без параметра, или он равен false, то функция будет реагировать только на сигналы с пульта при нажатии его кнопок, а если указать true, то функция будет реагировать, как на нажатие, так и на удержание кнопок пульта.
  • Пример:
if(IR.check()){ ... ;} // Если приняты данные с пульта, при нажатии его кнопки if(IR.check(true)){ ... ;} // Если принимаются данные с пульта, при удержании кнопки

Функция protocol();

  • Назначение: Получение, установка или сброс протокола передачи данных.
  • Синтаксис: protocol([ ПАРАМЕТР ]);
  • Получение протокола: Если функция вызвана без параметра, то она вернёт строку из 25 символов + символ конца строки. Биты данной строки, несут информацию о типе протокола передачи данных пульта, данные которого были приняты последними. Данную строку можно использовать для установки протокола ИК-передатчику, или ИК-приёмнику (см.ниже).
  • Установка протокола: Если функция вызвана с параметром в виде строки из 25 символов протокола + символ конца строки, то после этого, функция chek(), будет реагировать только на пульты, соответствующие указанному протоколу передачи данных.
  • Сброс протокола: Если функция вызвана с параметром IR_CLEAN, то функция chek() опять станет реагировать на сигналы с любых пультов.
  • Получение параметров протокола: Если функция вызвана с параметром int, от 0 до 17, то она вернёт не строку протокола, а значение типа int с одним из параметров протокола передачи данных пульта, данные которого были приняты последними:
    • 0 - тип кодировки:
      • IR_UNDEFINED - тип кодировки не определён;
      • IR_PAUSE_LENGTH - кодирование длинной паузы;
      • IR_PULSE_LENGTH - кодирование длинной (шириной) импульса (ШИМ);
      • IR_BIPHASIC - бифазное кодирование;
      • IR_BIPHASIC_INV - бифазное кодирование с инверсными битами;
      • IR_NRC - пакеты повтора идентичны, а первый и последний пакеты специальные;
      • IR_RS5 - кодировка PHILIPS с битом toggle;
      • IR_RS5X - кодировка PHILIPS с битом toggle;
      • IR_RS6 - кодировка PHILIPS с битом toggle.
    • 1 - несущая частота передачи данных (в кГц);
    • 2 - заявленное количество информационных бит в 1 пакете;
    • 3 - заявленное количество информационных бит в пакете повтора;
    • 4 - длительность паузы между пакетами (в мс);
    • 5 - длительность импульса в стартовом бите (в мкс);
    • 6 - длительность паузы в стартовом бите (в мкс);
    • 7 - длительность импульса в стоповом бите (в мкс);
    • 8 - длительность паузы в стоповом бите (в мкс);
    • 9 - длительность импульса в бите рестарт или toggle (в мкс);
    • 10 - длительность паузы в бите рестарт или toggle (в мкс);
    • 11 - позиция бита рестарт или toggle в пакете (№ бита);
    • 12 - максимальная длительность импульса в информационных битах (в мкс);
    • 13 - минимальная длительность импульса в информационных битах (в мкс);
    • 14 - максимальная длительность паузы в информационных битах (в мкс);
    • 15 - минимальная длительность паузы в информационных битах (в мкс);
    • 16 - флаг наличия стартового бита (true/false);
    • 17 - флаг наличия стопового бита (true/false);
    • 18 - флаг наличия бита рестарт или toggle (true/false);
    • 19 - тип пакета повтора (0-нет, 1-с инверсными битами, 2-идентичен информационному, 3-уникален);
  • Возвращаемые значения: Зависят от наличия и типа параметра.
  • Примечание: Если ранее был установлен протокол, то попытка получения протокола, или параметров протокола, вернёт значения установленного ранее протокола, а не протокола передачи данных пульта, данные которого были приняты последними.
  • Пример:
IR.protocol("AeQQV~zK]Kp^KJp[@@@@@@@Bp"); // Устанавливаем протокол. Теперь приёмник будет получать данные, только от пультов телевизора ELENBERG. IR.protocol(IR_CLEAN); // Сбрасываем ранее установленный протокол. Теперь приёмник снова будет реагировать на любые пульты. if(IR.check()){ Serial.println(IR.protocol()); } // Получаем протокол. Как только приёмник получит данные, в мониторе высветится строка из 25 символов протокола. if(IR.check()){ Serial.println(IR.protokol(12)); } // Получаем один из параметров протокола. Как только приёмник получит данные, в мониторе отобразится максимальная длительность импульса информационного бита в микросекундах.

Переменная data

  • Значение: Возвращает код кнопки, принятый с пульта;
  • Тип данных: uint32_t.
if(IR.check()){ Serial.println(IR.data); } // Выводим код нажатой кнопки, если он принят

Переменная length

  • Значение: Возвращает размер кода кнопки, в битах;
  • Тип данных: uint8_t.
if(IR.check()){ Serial.println(IR.length); } // Выводим размер кода нажатой кнопки, если он принят

Переменная key_press

  • Значение: Возвращает флаг, указывающий на то, что кнопка пульта нажимается а не удерживается;
  • Тип данных: bool.
if(IR.check(true)){ if(IR.key_press){Serial.println("PRESS");} // Текст будет выведен 1 раз, когда кнопка нажимается else {Serial.println("HOLD ");} // Текст будет выводиться постоянно, пока кнопка удерживается }

Применение:

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

В сегодняшней статье будет рассматриваться подключение ИК приемника TSOP34836 к плате Aduino UNO. Для этих целей можно применить любой имеющийся у вас приемник, совместимый с вашим пультом по частоте. Назначение выводов показано на рисунке.

1. Vout – выход приемника.
2. GND – «земля», общий провод.
3. Vcc – питание.
Передача данных от ИК пульта к приемнику осуществляется по протоколу RC5, представляющий из себя последовательность импульсов. Подключение осуществляется по следующей схеме.

А собрав, получаем примерно следующее:

Для обработки данных, передаваемых пультом, используем библиотеку IRremote, данная библиотека прикреплена к статье. Вставляем следующий код:

#include "IRremote.h" IRrecv irrecv(11); // Указываем пин, к которому подключен приемник decode_results results; void setup() { Serial.begin(9600); // Выставляем скорость COM порта irrecv.enableIRIn(); // Запускаем прием } void loop() { if (irrecv.decode(&results)) // Если данные пришли { Serial.println(results.value, HEX); // Отправляем полученную данную в консоль irrecv.resume(); // Принимаем следующую команду } }

Теперь в консоле COM - порта можно наблюдать код нажимаемой клавиши в HEX.


Вот и все, теперь можно использовать эту схему в ваших устройствах. Ниже приведен пример одного из практических применений ИК - приемника.

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

Схема устройства:

Вот так оно должно выглядеть:

Для работы устройства используем следующий код:

#include "Servo.h" #include "IRremote.h" IRrecv irrecv(11); decode_results results; Servo servoMain; int servPoz = 90; //Начальное положение сервы int lastPoz = 0; void setup() { irrecv.enableIRIn(); servoMain.attach(10); // Servo присоединен к 10 выводу servoMain.write(servPoz); } void loop() { if (irrecv.decode(&results)) { int res = results.value; Serial.println(res, HEX); if(res==0xFFFF906F)// Если нажата кнопка "+" { lastPoz=res; servPoz++; servoMain.write(servPoz); } else if(res==0xFFFFA857)// Если нажата кнопка "-" { servPoz--; lastPoz=res; servoMain.write(servPoz); } else if(res==0xFFFFFFFF)// Если кнопку удерживают { if(lastPoz==0xFFFF906F) servPoz++;// Удерживают "+" if(lastPoz==0xFFFFA857) servPoz--;// Удерживают "-" servoMain.write(servPoz); } irrecv.resume(); delay(100); } }

Пульт используется какой-то китайский, при нажатии "+" серва вращается в одну сторону, при нажатии "-", в другую.