В статье описываю как можно подружить arduino (да и собственно любой микроконтроллер) с ИК пультом от телевизора, плеера и т.д. Так же приведу получившийся плагин для arduino для работы с пультом от тюнера Behold TV и небольшое тестовое устройство, которое по нажатию кнопок пульта может зажигать один из двух светодиодов или гасить их.


Кодирование команд пультом:

Сначало расскажу про принцип кодирования команд для нашего пульта (у меня был от тюнера Behold TV, хотя такой принцип используется многими производителям).

Сначало идет еденичный импульс длительностью около 9 мс (из-за разных помех и разброса параметров может несколько изменяться). Он является самым длиным, поэтому его можно определять из условия того что он длинее 8 мс (делаем небольшой запас, что б точно определить сигнал).

Далее передается 32 бита с кодом клавиши. Биты кодируются временным методом: отправляется опорные импульсы (порядка 500 мкс) и в зависимости от времени между опорными импульсами будет 1 или 0. 0 соответствует время около 500 мкс, а 1 - 1600 мкс. Если кнопка продолжается оставаться нажатой, то после кода клавиши непрерывно формируются импульсы аналогичные начальному (длительностью около 9 мс).

Осцилограмма
Пример того как выглядят сигналы для пульта

Распознование команд arduino от пульта:

Я решил оформить часть, которая распознает команды, для удоабства в виде плагина. В рамках данной заметки мы не будем рассматриваться премудрости написания плагинов для ардуино, так что остановлюсь на самом алгоритме.

Он состоит из двух функций одна (getCode) предназначена для того что б получить 32х битный код любой клавиши. Служит для распознования кнопок, на случай, если используется пульт отличный от моего или вовсе другой, но с таким же методом шифрования.

Вторая функция (waitPressKey)  ожидает нажатия клавиши на пульте, ее следует запускать из цикла. Правда функиця отслеживает только одинарное нажатие, при удержании кнопок, возможны какие-то проблемы.

Следует учесть что я использовал применик с инверсным выходом.

Разберем принцип работы функции  waitPressKey (у getCode аналогичный принцип)

int IRB::waitPressKey(){
int time = pulseIn(_pin, LOW);
int code[32];

//ждем начальный длинный сигнал (который около 9 мс)
if (time > 8000) {
//пришел начальный сигнал, начинаем считывать код
int i = 0;
while(true) {
time = pulseIn(_pin, HIGH);

//читаем 32 бита, но если чтение было

//вызвано долгим удержанием кнопки, то прерываем чтение

if (time > 2000) {
return 0;
}

if (i > 31) {
break;
}

//исходя из длительности паузы определяем 0 или 1
code[i] = time > 900 ? 1 : 0;
i++;
}

//делаем задержку в 200 мс, что б у пользователя было время

//отпустить кнопку, это время не читаем команды

delay(200);

//ищем какую кнопку нажал пользователь и возращаем

//ее номер (часть команд пропущено)
if (IRB::isThisCommand(code,  "01100001110101100011100011000111")) {
return IRB_FUNCTION;
}
if (IRB::isThisCommand(code,  "01100001110101100100100010110111")) {
return IRB_POWER;
}

//...

if (IRB::isThisCommand(code, "01100001110101101100100000110111"))  {
return IRB_MUTE;
}

}

return 0;
}

//служебная функция сравнивает два массива

//со считанной командой и записаными командами

boolean IRB::isThisCommand(int check[], char command[]) {
for (int i=0; i < 32; i++) {
int code = command[i] == 49 ? 1 : 0;
if (check[i] != code){
return false;
}
}
return true;
}

Железная часть:

Для приема и усиления сигнала был взят ИК приемник из серии TSOP (впринципе можно брать любой, хотя лучше что б частота несущая в приемнике была такая же как и у пульта).

Для индикации нажатых кнопок взял два сверхярких светодиода разных цветов.

Для питания используется 6В свинцовый акумулятор.

ИК-приемник можно подключать сразу с арудино, т.к. он снабжен всем необходимым (демодулятором, усилителем). Питиание для приемника я взял с выходов 5V и GND, а передавать данные можно в любой цифровой порт (я брал 8). Светодиоды я  подключал напрямую к свободным портам (10 и 11) и к земле (GND), хотя, если они будут гореть долгое время, то лучше поставить на каждый последовательно резистор Ом на 100 (зависит от светодиодов).

Программа управления:
Для тестирования ИК-приемника напишем небольшую программу, которая сделает так что при нажатии на кнопку function пульта будет загораться один светодиод, при нажатии на ok другой, а при нажатии на power отключаться оба светодиода:

//включаем наш плагин
#include

//объявляем переменные с номерами кнопок
#define IRB_FUNCTION 1
#define IRB_POWER 2
#define IRB_OK 24

//инициализируем плагин на 8 порт (тут слушаем ИК-приемник)
IRB IRB(8);

void setup() {
//на этих портах светодиоды
pinMode(11, OUTPUT);
pinMode(12, OUTPUT);
}

void loop() {
//получаем номер нажатой кнопки
int code = IRB.waitPressKey();
if (code != 0) {

switch (code) {
case IRB_FUNCTION :
digitalWrite(11, HIGH);
break;
case IRB_POWER :
digitalWrite(11, LOW);
digitalWrite(12, LOW);
break;
case IRB_OK :
digitalWrite(12, HIGH);
break;
}
}
}

Вот так будет работать устройство:

Скачать плагин можно отсюдо.