CraftDuino v2.0
  • - это CraftDuino - наш вариант полностью Arduino-совместимой платы.
  • CraftDuino - настоящий конструктор, для очень быстрого прототипирования и реализации идей.
  • Любая возможность автоматизировать что-то с лёгкостью реализуется с CraftDuino!
Просто добавьте CraftDuino!

Управление Arduino практически ЛЮБЫМ пультом ДУ при помощи ИК датчика TSOP31236

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

Не посчитайте, что я с пренебрежением отношусь к протоколам. Дело в том, что ДУ много, протоколов то же, скетч и желание чтобы все работало — одно. Поэтому применим принцип универсальности =)

Требование к пультам и датчикам все же есть. Они должны работать на одной частоте. В нашем случае — 36 кГц (наиболее распространенный). Разновидностей TSOP312** несколько, по маркировке — 2 последние цифры. Я другие не пробовал, но есть надежда, что скетч справится с разными, т.к. принцип работы не завязан на частоту сигнала.
Использовать будем датчик TSOP31236 (аналог TSOP1736). Подключить его можно по данной схеме:



К сути скетча… Принцип его работы заключается в записи интервалов времени как сигнала HIGH так и LOW полученных датчика, который в свою очередь принял ИК сигнал от ДУ. Последовательность этих сигналов конфигурируем в массив, который мы потом сравниваем с опорным массивом. Опорный массив — это массив, записанный с используемого ДУ. Это нужно для того, чтобы избавиться от привязкам протоколу, а также позволит не учитывать частоту работы датчика (только в теории — у меня других датчиков и ДУ нет). При сравнении этих массивов находим отличия, и в зависимости от места и количества этих отличий будет формировать индивидуальный код команды ДУ.

Чтобы не приходилось при каждом включении ардуино заново дружить ее с ДУ при записаи опорного массива он автоматом попадет в EEPROM. При включении Ардуино он читается из EEPROM.

Наконец сам код =):

/* Данный скетч предназначен для управления Ардуиной практически любим пультом ИК,
вне зависимости от протоколов, и прочих заморочек.
Принцип его работы заключается в том, что он сравнивает сигналы разных команд с одного ДУ.
Для работы программы надо сначала прижать 10й пин к 1, и нажать каку-ть кнопку на ДУ, чтобы подружить
нашу ардуину с ДУ. Далее 10-й пин кладем на 0, и при нажатии различных кнопок на пульте получаем разные коды на выходе.
Буду рад, если мой скечт кому-нибудь пригодится =)
Peter.
*/

#include <EEPROM.h>

enum { Intervals = 70 }; //Здесь мы указываем, сколько битов бы будем слушать. 
//Разные ДУ выдают разное количество битов.


int starttime, endtime, time,n,  code;
char arrayfix[Intervals],array[Intervals]; // Массивы времени импульсов
byte  distinction;
void setup() {                
  
  pinMode(9, INPUT); // К ноге приемника
  pinMode(10, INPUT); // К кнопки для запоминания опорного кода
  
Serial.begin(9600); 

    
    for (byte x=0; x<Intervals; x++) //Читаем из EEPROM опорный масив (если он записан =)
   {
   arrayfix[x]=EEPROM.read(x); 
   }
}

void loop()
{ 
 if (digitalRead(9)==0) //Если сигнал есть..
  {
    starttime=micros();  
   while (digitalRead(9)==0); //..ждем пока он не прекратися.
   endtime=micros();
   time=endtime-starttime; // Высчитываем время.
   if (time>1000) //если это не шум, а скорее стартовый бит, начинаем слушать.
   {
   while (n<Intervals) //В цикле слушаем бит за битом.
   {
  
    if (digitalRead(9)==0) //Если сигнал есть (1)..
    {
    
    starttime=micros();
    while (digitalRead(9)==0);
    endtime=micros();
    time=endtime-starttime; // ...высчитываем его время.
   
    if (digitalRead(10)==1) //Если кнопка нажата..
   
    arrayfix[n]=time/100;  //..записываем в массив "опорный код" 
//в виде промежутков времени наличия сигнала.
    array[n]=time/100;     // Также записываем в массив текущий код.
    n++;
    }
    if (digitalRead(9)==1) //Если сигнала нет (0)..
    {
       
    starttime=micros();
    
    while (digitalRead(9)==1) //пока ждем появления сигнала проверим, не остановка ли это передачи...
    {
     endtime=micros();
    time=endtime-starttime;
 
   if (time>10000)  //  ...ага, отсановка. Тогда заполняем 
//остаток масива 0-ми, и выходим из цикла.
   {
   while (n<Intervals)
   {
    if (digitalRead(10)==1) 
    arrayfix[n]=0;
    array[n]=0 ;
   n++;
     }
   goto out; 
     }
    }   
    endtime=micros();
    time=endtime-starttime;
    if (digitalRead(10)==1)
    //EEPROM.write(n, time); 
    arrayfix[n]=-time/100; //для отсутствия сигнала запишим время с (-). 
    //Делим на 100 для того, чтобы можно было запихнуть данные в 1 байт, а не использовать растачительно int.
    array[n]=-time/100;    
    n++;
    }
    
    }
    out: // Если остановка, то выходим сюда.
    
    if (digitalRead(10)==1)//Если кнопка нажата, записываем все в EEPROM
    {
    for (byte x=0; x<Intervals; x++)
   {
   EEPROM.write(x, arrayfix[x]); 
   
    }
    }  
    
    
    
    /*for (byte x=0; x<Intervals; x++) // Этот цикл необязателен. Я его закоментил. 
//Он наглядно выводит то, что записано в опорном коде, и что передал нам ДУ. Это полезно для отладки
//или поиска ошибок.

    {    
      Serial.print(x);
      Serial.print("   ");           
      Serial.print(int(arrayfix[x]));
       Serial.print("   ");
        Serial.println(int(array[x]));
    }*/
    
    
   n=0;
   
   for (byte x=0; x<Intervals; x++) //В этом цикле мы ищем отличия в преданном коде и опорном.
   {        
      
    if (abs(array[x]-arrayfix[x])>5 && array[x]!=0 && arrayfix[x]!=0) // Здесь мы отслеживаем,
// где есть отличия на логическом уровне.
    //Если отличие больше 500 мкс, то это однозначно разные логичесике уровни.
    {
    distinction++;
    code=code+(x+1)*distinction; //генерируем код
    }
    }
    
    Serial.println("========Result==========");  // Выводим, что имеем на выходе
    
    Serial.print("Otlichiya   ");
    Serial.println(distinction);
    Serial.print("Code   ");
    Serial.println(code);
    
    distinction=0;
    code=0;

 }
 }   




} 


Соберем просейшую схему, где к 10 пину подключена кнопка, 3-я нога датчика -> 9-й пин, 2-> Vcc, 1-> Gnd через резистор 100 Ом. Повесить конденсаторы рекомендуется, но если нет — не криминал. Кнопка нам понадобится для того, чтобы подружить ДУ с ардуиной, а именно записать опорный массив.

Запускаем скетч, нажимаем кнопку или подаем (1) на 10 pin, нажимаем на ДУ какую-нибудь кнопку, возвращаем (0) на 10 pin. Все, опорный массив задан. Теперь при нажатии любой кнопки на ДУ получаем индивидуальный ее код. При нажатии кнопки, которой задали массив получим код 0.



Внимание. В выложенном коде закомментирован вывод массивов. Это строки 108 — 118.

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

Еще надо отметить пару особенностей. Некоторые ДУ при нажатии одной кнопки выдают разные коды. У меня есть пару пультов от ТВ и один от кондиционера. На одном ДУ от ТВ все кнопки не меняют своего кода. На другом — два кода на кнопке, они чередуются. Пульт от кондиционера может выдавать по 5 разных кодов на кнопке. Т.е. кнопка увеличивает вращения дуйки с каждым нажатием, и следовательно выдает новый код, в зависимости от желаемой скорости.

Также некоторые ДУ при удержании кнопки повторно отправляют команду, некоторые отправляют команду повтора. Т.е. ты нажал на кнопку, сначала идет команда кнопки, потом команда повтора одинаковая для всех. Это необходимо учесть при написании программ.

Чуть погодя…

Решил в академических целях написать библиотеку под это все. Называться будет IR

Она очень проста…

IR.pinIR(9) — выбирает пин, к которому подключен датчик.
IR.readEEPROM() — считывает опорный код (он же массив) из EEPROM.
IR.writeEEPROM() — записывает опорный код в EEPROM. Возвращает true если код записан.
IR.writeMEMORY() — то же, только в RAM, если нет нужды записывать опорный код в EEPROM.
IR.test() — выводит в serial два массива — опорный код и последний считанный (для отладки, проверки).

IR.readIR() — главная функция — возвращает в int код команды. Если команды нет, возвращает (-1).

Пример использования:

/*Пример использования библиотекти IR 
для датчика TSOP31236*/

#include <IR.h>
int code;

IR TSOP31236;

void setup()
{
Serial.begin(9600);

TSOP31236.pinIR(9);  //Указываем на какой пин подключен датчик
TSOP31236.readEEPROM(); //Считываем опорный код из EEPROM

pinMode(8, INPUT);
pinMode(10, INPUT);
pinMode(7, INPUT);
}
void loop ()

{
  
if (digitalRead(8)==1)
{
if (TSOP31236.writeEEPROM()==true) //Одновременно
//записываем опорный код в EEPROM и получив 
//положительный ответ объявляем, что код записан.
Serial.println("EEPROM writen!") ;
}


if (digitalRead(10)==1)
{
if (TSOP31236.writeMEMORY()==true)//Одновременно
//записываем опорный код в RAM и получив 
//положительный ответ объявляем, что код записан/
Serial.println("RAM writen!");
}  



code=TSOP31236.readIR(); //считываем и получаем код. 
//Если ничего не считано - получаем (-1);





if (code!=-1) //Если что-то считали - выведим код.
Serial.println(code);
}
  • +1
  • 6 марта 2012, 18:08
  • Peter

Комментарии (12)

RSS свернуть / развернуть
+
0
как не вникая в дебри протоколов, частоты и прочей мути различных пультов ДУ мы сможем без проблем подружить их с нашей ардуино

Без проблем тут не получится, а не вникая этих проблем не решить.
Начнем с такой мутоты, как частота. Диапазон пультов находится в промежутке 30 — 60 КГц. TSOP31236 Настроен на прием частоты в 36 кГц, и отклонение на 10% приведет к уменьшению чувствительности сильнее, чем в половину. Т.е. Если пульты на 33 и на 38 еще будут приниматься плохо и с близкого расстояния, то про другие стоит или забыть или управлять в упор к датчику:) TSOP`ы выпускают спецом под точные сигналы пульта. Откройте даташит и посмотрите график зависимости чувствительности от частоты.
На момент писания скетча у меня не было конденсаторов, поэтому я использовал только резистор для подтяжки.

И резистор зачем вы выбросили? Он там не для подтяжки, а для ограничения тока. TSOP скромный и довольствуется максимум 5 мА. Хотя бы пару десятков Ом туда надо поставить. Не мучайте микросхему зря.

Новичкам надо показывать простые и полезные примеры, но не такие. Вы тоже можете пить воду из лужи, зачем же тогда покупать фильтр или чайник? Такой пример наплевательского отношения ни во что не годится. Не подавайте дурных примеров)) Чтобы заниматься электроникой, надо сидеть и заниматься, ловя кайф. Другого это дело не терпит.
Сам метод (если на время забыть как вы с железом обошлись), конечно эффективностью не блещет, но иногда смысла нет заморачиваться на сложные и качественные устройства, если простые и топорные с задачей справляются.
avatar

Ozze

  • 7 марта 2012, 10:43
+
0
За частоту — спасибо, исправил.

За железо — спасибо, просветили. Наплевательски не относимся.

А вот про эффективность прошу аргументировать. У Вас не работает? Также что в нем сложного, что именно не понятно(не сложнее многих примеров)? И не понял мысли «но иногда смысла нет заморачиваться на сложные и качественные устройства, если простые и топорные с задачей справляются.» Что есть сложные устройства, что простые, что справляется, что нет. Я запутался. =))

Спасибо.
avatar

Peter

  • 7 марта 2012, 13:09
+
0
Ну вот все вы вверх ногами поняли :)
Про эффективность я писал как плюс вашего решения. Имел ввиду, что если оно при своей простоте справляется со своей задачей, то это его хорошая сторона. И пофиг, что можно было бы сделать лучше, работает же.
конечно эффективностью не блещет

Эффективностью = красотой реализации. Красота реализации ставилась в противовес ее простоте)

Про наплевательски, я к стилю изложения писал. Выглядело как «забейте на все частоты, протоколы, и прочую мутатень, выпейте литр водки и соберите ИК приемник, пусть он тупо записывает и сравнивает, че». Гляжу, стиль слегка поменялся :)

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

И проверьте дш на ваш тсоп:
Pinning:
1 = GND, 2 = VS, 3 = OUT

А у вас:
3-я нога датчика -> 9-й пин, 2-> Gnd, 1-> Vcc через резистор 100 кОм.

И куда там 100 кОм? 30 — 300 Ом я думаю в самый раз.
avatar

Ozze

  • 7 марта 2012, 15:24
+
0
Да. Вы близко к сердцу приняли =). К протоколам и железу я отношусь с уважением. Опыта просто не хватает. Я этим всем увлекся буквально на днях (ардуино и электроника =))). А статейку написал, т.к. сам столкнулся с проблемой отсутствия такого «универсального» скетча. Пультов ДУ то много, а подключить то хочется!!!

avatar

Peter

  • 7 марта 2012, 17:04
+
0
Да, бывает у меня проявляется такая дурная черта:)) Для буквально на днях это успех) Есть такой метод обучения «не знаешь сам — объясни другому». Это я про написание статей)
После стольких уточнений, однозначно +1
avatar

Ozze

  • 7 марта 2012, 17:42
+
0
Благодарю =)
avatar

Peter

  • 7 марта 2012, 17:51
+
0
Собрал, все работает. Только непонятен смысл кнопки? Без ее нажатия тоже все работает.
avatar

Dnik

  • 22 апреля 2013, 13:09
+
0
Товарищи, разбирающиеся в протоколах!
Подскажите чайнику. Есть универсальная библиотека IRremote.h, она работает, но скетч занимает очень много памяти, не влезает в контроллер. Если написать библиотеку только для протокола RC5, уменьшится ли занимаемая память?
Peter, где можно почитать вашу статью про протоколы? Можете написать библиотеку для RC5? А то весь нэт переискал и не нашел.
avatar

Nazzik

  • 10 мая 2013, 13:50
+
0
Сам отвечу на свой вопрос. Методом научного втыка нашёл способ как обрезать библиотеку IRremote.h под нужный протокол и уменьшить объем памяти в несколько раз. Ведь ДУ для многих проектов не самое важное. У мена получился очень большой и сложный (для меня) скетч и под ДУ осталось пара кб, нужно всего 6 команд и один пульт, пришлось комбинировать. Так вот, открываем файл IRremote.cpp с помощью Visual studio и читая коменты, удаляем (или лучше комментируем) ненужные протоколы, сохраняем и пользуемся. Ещё желательно переименовать библиотеку и все ссылки на неё в файлах .cpp и .h.
Таким макаром я переделал под протоколы RC5 и Sanyo. Работает!!! Могу скинуть на почту, если кому надо.
avatar

Nazzik

  • 16 мая 2013, 09:54
+
0
еще одна библиотека на таком же принципе: we.easyelectronics.ru/reptile/biblioteka-priema-ik-du.html
avatar

gogi

  • 14 мая 2013, 11:40
+
0
привет. у меня проблема. воспользовался твоей библиотекой. удалил из примера лишнее, а именно запись опорного кода на носитель и вывод вспомогательного массива.

пробую. вместо одной команды выводит список, причем он изменяется на 1.

при этом просто код, который идет в статье первый работает безупречно, выводя один и тот же код для каждой кнопки. в чем проблема? спасибо за ответ.
avatar

Pimkin_Dima

  • 15 апреля 2014, 00:11
+
0
Так с ходу не скажешь. Надо видеть изменения и прочее. Я советую не пользоваться библиотекой, а взять код, и просто его поместить в другую вкладку в IDE, чтобы не мешался, и там менять как хочется.
avatar

Peter

  • 15 апреля 2014, 06:27

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.