Инфракрасная (ИК) связь — это широко используемая и простая в реализации беспроводная технология, имеющая множество полезных применений. Наиболее яркими примерами в повседневной жизни являются пульты дистанционного управления телевизором, датчики движения и инфракрасные термометры.
Существует множество интересных проектов Arduino, которые также используют ИК-связь. С помощью простого ИК-передатчика и приемника вы можете создавать роботов с дистанционным управлением, датчики расстояния, мониторы сердечного ритма, пульты дистанционного управления телевизором и многое другое.
В этой статье сначала рассмотрим, что такое инфракрасное излучение и как оно работает. А затем рассмотрим, как подключить ИК-приемник к Ардуино.
Что значит инфракрасный?
Инфракрасное излучение – это форма света, похожая на тот, который мы видим вокруг себя. Единственное различие между ИК-излучением и видимым светом заключается в частоте и длине волны. Инфракрасное излучение находится за пределами диапазона видимого света, поэтому люди не могут его видеть:
Поскольку ИК — это тип света, ИК-связь требует прямой видимости от приемника к передатчику. Он не может передавать данные через стены или другие материалы, такие как Wi-Fi или Bluetooth.
Как работают ИК-пульты и ИК-приемники
Типичная система инфракрасной связи требует ИК-передатчика и ИК-приемника. Передатчик выглядит как стандартный светодиод, за исключением того, что он излучает свет в ИК-спектре, а не в видимом спектре. Если вы посмотрите на переднюю часть пульта телевизора, вы увидите светодиод ИК-передатчика:
Светодиоды такого же типа используется в модулях ИК-передатчика для Arduino. Вот один из них, KY-005:
ИК-приемник представляет собой фотодиод и предварительный усилитель, преобразующий ИК-излучение в электрический сигнал. Диоды ИК-приемника обычно выглядят следующим образом:
Можно встретить вот такой готовый модуль, KY-022:
Модуляция ИК-сигнала
Инфракрасный свет излучается солнцем, лампочками и всем остальным, что выделяет тепло. Это означает, что вокруг нас много шума от инфракрасного излучения. Чтобы этот шум не мешал ИК-сигналу, используется метод модуляции сигнала.
При модуляции ИК-сигнала происходит следующее:
- энкодер на пульте дистанционного управления преобразует двоичный сигнал в модулированный электрический сигнал;
- этот электрический сигнал отправляется на передающий светодиод;
- передающий светодиод преобразует модулированный электрический сигнал в модулированный ИК-световой сигнал;
- затем ИК-приемник демодулирует ИК-световой сигнал и преобразует его обратно в двоичный формат перед передачей информации в микроконтроллер.
Модулированный ИК-сигнал представляет собой серию импульсов инфракрасных световых импульсов, включаемых и выключаемых на высокой частоте, известной как несущая частота. Несущая частота, используемая большинством передатчиков, составляет 38 кГц, поскольку она встречается редко в природе и ее можно отличить от окружающего шума.
Диод приемника обнаруживает все частоты ИК-излучения, но он оснащен полосовым фильтром и пропускает ИК-излучение только на частоте 38 кГц. Затем он усиливает модулированный сигнал с помощью предусилителя и преобразует его в двоичный сигнал.
Протоколы ИК-передачи
Схема, по которой модулированный ИК-сигнал преобразуется в двоичный, определяется протоколом передачи. Существует множество протоколов ИК-передачи. NEC, RC5, Sony и Panasonic являются одними из наиболее распространенных протоколов.
Протокол NEC также является наиболее распространенным ИК протоколом в проектах Arduino, поэтому рассмотрим его на примере.
Логическая 1 начинается с высокого импульса (HIGH) длительностью 562,5 мкс при ИК-диапазоне 38 кГц, за которым следует низкий импульс (LOW) длительностью 1687,5 мкс.
Логический 0 передается с высоким импульсом (HIGH) длительностью 562,5 мкс, за которым следует низкий импульс (LOW) длительностью 562,5 мкс:
Так протокол NEC кодирует и декодирует двоичные данные в модулированный сигнал. Другие протоколы отличаются только длительностью отдельных импульсов HIGH и LOW.
ИК-коды
Каждый раз, когда вы нажимаете кнопку на пульте дистанционного управления, генерируется уникальный шестнадцатеричный код. Это информация, которая модулируется и передается по ИК-каналу на приемник. Чтобы расшифровать, какая кнопка нажата, принимающему микроконтроллеру необходимо знать, какой код соответствует каждой кнопке на пульте.
Разные пульты отправляют разные коды при нажатии клавиш, поэтому вам нужно будет определить код, сгенерированный для каждой клавиши на вашем пульте. Если вы сможете найти техническую документацию на пульт, то там должны быть указаны коды. Если нет, то есть простой скетч для Arduino, который считывает большинство популярных пультов и выводит шестнадцатеричные коды в монитор порта. Я покажу вам, как это настроить, через минуту, но сначала нам нужно подключить приемник к Arduino
Как подключить ИК-приемник к Arduino
Существует различные типы ИК-приемников. Лучше всего, конечно, найти техническое описание вашего конкретного ИК-приемника, поскольку контакты могут быть расположены иначе, чем у модуля ИК-приемника KY-022 (на базе HX1838) или ИК-диода TSOP312. Однако все ИК-приемники будут иметь три контакта: сигнал S, земля GND и питание Vcc.
Как подключить ИК-приемник и модуль KY-022 к Arduino показано на картинках ниже:
Модуль KY-022 это тот же ИК-диод, только дополнительно имеет токоограничивающий резистор и светодиод, который загорается при приеме сигнала.
Установка библиотеки IRremote
Как установить библиотеку можно прочитать здесь.
Скачать библиотеку можно по ссылкам:
Как считать коды вашего пульта ДУ
Чтобы найти коды кнопок для вашего пульта, загрузите этот код в Arduino и откройте последовательный монитор.
Обратите внимание!
Для версий библиотек 2.0.1 и 4.2.0 код будет отличаться.
Код для версии 2.0.1 библиотеки IRremote
#include <IRremote.h> // Подключаем библиотеку const int RECV_PIN = 7; // Сигнальный вывод, подключенный к Ардуино IRrecv irrecv(RECV_PIN); // Создаем объект decode_results results; // Объявляем переменную для хранения принятого значения void setup() { Serial.begin(9600); // Инициализируем последовательный порт irrecv.enableIRIn(); // Включаем ИК irrecv.blink13(true); // Если сигнал пришел, диод D13 будет мигать } void loop() { if (irrecv.decode(&results)) // Проверяем, пришли ли данные { Serial.println(results.value, HEX); // Выводим в порт irrecv.resume(); // Ловим следующий пакет } }
Для версии 4.2.0 библиотеки IRremote
#include <IRremote.hpp> // Подключаем библиотеку #define IR_RECEIVE_PIN 7 // Сигнальный вывод, подключенный к Ардуино void setup() { Serial.begin(9600); IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK); // Инициализация приемника } void loop() { if (IrReceiver.decode()) { // // Проверяем, пришли ли данные Serial.println(IrReceiver.decodedIRData.decodedRawData, HEX); // Выводим в порт IrReceiver.resume(); // Включение приема следующего значения } }
Теперь понажимайте на кнопки и запишите шестнадцатеричный код, который будет выводиться в монитор порта.
Обратите внимание!
Вы можете заметить, что коды для разных версий библиотек отличаются, хотя были нажаты одни и те же кнопки одного и того же пульта ДУ.
Это связано с изменением последовательности битов. В библиотеке версии 2.0.1 первым шел старший бит (MSB), а в библиотеке 4.2.0 первым идет младший бит (LSB), согласно протоколам ИК-передачи.
Чтобы преобразовать одно значение в другое, нужно “отзеркалить”/отразить двоичный код . Например:
0xFFA25D = 0000 0000 1111 1111 1010 0010 0101 11012 – полученный код кнопки “1”, при использовании версии 2.0.1
0xBA45FF00 = 1011 1010 0100 0101 1111 1111 0000 00002 – полученный код кнопки “1”, при использовании версии 4.2.0
Монитор порта для версии 2.0.1 библиотеки IRremote
Монитор порта для версии 4.2.0 библиотеки IRremote
Используя приведенные выше программы, были получены таблицы кодов кнопок пульта, который шел в комплекте с модулем KY-022.
Кнопка на пульте | Код |
---|---|
1 | FFA25D |
2 | FF629D |
3 | FFE21D |
4 | FF22DD |
5 | FF02FD |
6 | FFC23D |
7 | FFE01F |
8 | FFA857 |
9 | FF906F |
0 | FF9867 |
* | FF6897 |
# | FFB04F |
↑ | FF18E7 |
↓ | FF4AB5 |
← | FF10EF |
→ | FF5AA5 |
OK | FF38C7 |
Кнопка на пульте | Код |
---|---|
1 | BA45FF00 |
2 | B946FF00 |
3 | B847FF00 |
4 | BB44FF00 |
5 | BF40FF00 |
6 | BC43FF00 |
7 | F807FF00 |
8 | EA15FF00 |
9 | F609FF00 |
0 | E619FF00 |
* | E916FF00 |
# | F20DFF00 |
↑ | E718FF00 |
↓ | AD52FF00 |
← | F708FF00 |
→ | A55AFF00 |
OK | E31CFF00 |
Обратите внимание!
При непрерывном нажатии кнопки вы получаете код 0xFFFFFFFF
в версии 2.0.1 и 0
в версии 4.2.0
Определение протокола пульта
Знание того, какой протокол использует ваш пульт, может быть полезно, если вы будете работать над более сложными проектами. Или просто от любопытства. Приведенная ниже программа определит протокол, используемый вашим пультом.
Для версии 2.0.1
#include <IRremote.h> // Подключаем библиотеку const int RECV_PIN = 7; // Сигнальный вывод, подключенный к Ардуино IRrecv irrecv(RECV_PIN); // Создаем объект decode_results results; // Объявляем переменную для хранения принятого значения void setup() { Serial.begin(9600); // Инициализируем последовательный порт irrecv.enableIRIn(); // Включаем ИК irrecv.blink13(true); // Если сигнал пришел, диод D13 будет мигать } void loop() { if (irrecv.decode(&results)) // Проверяем, есть пришли ли данные { Serial.println(results.value, HEX); // Выводим в порт /* Выводим протокол ИК-связи */ switch (results.decode_type){ case NEC: Serial.println("NEC"); break ; case SONY: Serial.println("SONY"); break ; case RC5: Serial.println("RC5"); break ; case RC6: Serial.println("RC6"); break ; case DISH: Serial.println("DISH"); break ; case SHARP: Serial.println("SHARP"); break ; case JVC: Serial.println("JVC"); break ; case SAMSUNG: Serial.println("SAMSUNG"); break ; case LG: Serial.println("LG"); break ; case WHYNTER: Serial.println("WHYNTER"); break ; case PANASONIC: Serial.println("PANASONIC"); break ; case DENON: Serial.println("DENON"); break ; default: case UNKNOWN: Serial.println("UNKNOWN"); break ; } irrecv.resume(); // Ловим следующий пакет } }
Для версии 4.2.0
Здесь для вывода детальной информации можно использовать метод printIRResultShort
:
#include <IRremote.hpp> // Подключаем библиотеку #define IR_RECEIVE_PIN 7 // Сигнальный вывод, подключенный к Ардуино void setup() { Serial.begin(9600); IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK); // Инициализация приемника } void loop() { if (IrReceiver.decode()) { // // Проверяем, пришли ли данные IrReceiver.printIRResultShort(&Serial); // Вывод в порт результата IrReceiver.resume(); // Включение приема следующего значения } }
Вот такой вывод будет в мониторе порта:
Действия, при нажатии определенных кнопок
Можно дополнить приведенный выше код, чтобы печатать название кнопки вместо шестнадцатеричного кода. Или выполнять другое какое либо действие, увеличить/уменьшить переменную, включить/выключить реле или светодиод, ввести код и тому подобное.
Для версии 2.0.1
#include <IRremote.h> // Подключаем библиотеку const int RECV_PIN = 7; // Сигнальный вывод, подключенный к Ардуино IRrecv irrecv(RECV_PIN); // Создаем объект decode_results results; // Объявляем переменную для хранения принятого значения void setup() { Serial.begin(9600); // Инициализируем последовательный порт irrecv.enableIRIn(); // Включаем ИК irrecv.blink13(true); // Если сигнал пришел, диод D13 будет мигать } void loop() { if (irrecv.decode(&results)) // Проверяем, есть пришли ли данные { switch(results.value){ // Сравниваем код кнопки и выводим в порт название при совпадении case 0xFFB04F: Serial.println("#"); break; case 0xFF6897: Serial.println("*"); break; case 0xFF18E7: Serial.println("UP"); break; case 0xFF4AB5: Serial.println("DOWN"); break; case 0xFF10EF: Serial.println("LEFT"); break; case 0xFF5AA5: Serial.println("RIGHT"); break; case 0xFF38C7: Serial.println("OK"); break; case 0xFF9867: Serial.println("0"); break; case 0xFFA25D: Serial.println("1"); break; case 0xFF629D: Serial.println("2"); break; case 0xFFE21D: Serial.println("3"); break; case 0xFF22DD: Serial.println("4"); break; case 0xFF02FD: Serial.println("5"); break; case 0xFFC23D: Serial.println("6"); break; case 0xFFE01F: Serial.println("7"); break; case 0xFFA857: Serial.println("8"); break; case 0xFF906F: Serial.println("9"); break; } irrecv.resume(); } }
Для версии 4.2.0
#include <IRremote.hpp> // Подключаем библиотеку #define IR_RECEIVE_PIN 7 // Сигнальный вывод, подключенный к Ардуино void setup() { Serial.begin(9600); IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK); // Инициализация приемника } void loop() { if (IrReceiver.decode()) { // // Проверяем, пришли ли данные switch(IrReceiver.decodedIRData.decodedRawData){ case 0xF20DFF00: Serial.println("#"); break; case 0xE916FF00: Serial.println("*"); break; case 0xE718FF00: Serial.println("UP"); break; case 0xAD52FF00: Serial.println("DOWN"); break; case 0xF708FF00: Serial.println("LEFT"); break; case 0xA55AFF00: Serial.println("RIGHT"); break; case 0xE31CFF00: Serial.println("OK"); break; case 0xE619FF00: Serial.println("0"); break; case 0xBA45FF00: Serial.println("1"); break; case 0xB946FF00: Serial.println("2"); break; case 0xB847FF00: Serial.println("3"); break; case 0xBB44FF00: Serial.println("4"); break; case 0xBF40FF00: Serial.println("5"); break; case 0xBC43FF00: Serial.println("6"); break; case 0xF807FF00: Serial.println("7"); break; case 0xEA15FF00: Serial.println("8"); break; case 0xF609FF00: Serial.println("9"); break; } IrReceiver.resume(); // Включение приема следующего значения } }
Если ваш пульт отправляет коды, которые отличаются от приведенных в таблице выше, просто замените шестнадцатеричный код для каждой кнопки:
case 0xF20DFF00: Serial.println("#");
Вот здесь, когда получен шестнадцатеричный код 0xF20DFF00
, Arduino печатает символ “#“.