Розпізнавання ІК команд за допомогою UART на AVR

  • Час 17-12-2014, 15:16
  • Автор admin
  • Коментарів 0 Комент.
  • Силка url

Розпізнавання ІК команд за допомогою UART на AVR

Введення

Про розпізнаванні команд з інфрачервоного пульта написано багато статей. В-основному, мова йде про протокол RC5 від пультів Philips [1]. Цей протокол не єдиний і не найпоширеніший. Хороший опис інших форматів російською мовою можна знайти в документі [2]. 

У всіх знайдених мною статтях розпізнавання проводиться читанням стану датчика TSOP в строго певні моменти часу (в обробнику переривання від таймера або в основному циклі програми). Однак в моєму останньому проекті мені потрібно спілкуватися із зовнішнім пристроєм зі строгими тимчасовими затримками, через що доводиться забороняти переривання на періоди до 2мс. Цей факт робить неможливим опитування стану датчика TSOP з необхідною точністю (раз в 560мкс + -100мкс).  

Так народилася ідея використовувати UART як "хитрий" зсувний регістр. В отриманій реалізації при декодуванні NEC-подібного протоколу необхідно неспішно опитувати стан датчика лише раз на 4мс, при цьому сам мікроконтролер може перебувати в idle mode або навіть в power down mode!

Розпізнавання ІК команд за допомогою UART на AVR

ІК протоколи

Не бачу сенсу повторювати опис протоколів ІК пультів - вони описані досить добре в статті [2]. Позначу лише основні моменти:

Розпізнавання ІК команд за допомогою UART на AVR

ІЧ-посилка на прикладі протоколу NEC складається з Mark pulse (9мс), Space pulse (4.5мс) і послідовності імпульсів даних.

Розпізнавання ІК команд за допомогою UART на AVR

У різних протоколах біти даних кодуються по-різному, але довжина імпульсу однієї полярності завжди дорівнює або кратна довжині імпульсу протилежної полярності (різницю в кілька мікросекунд можна ігнорувати, так як накопичена помилка в перебігу посилки не заважає декодированию. Важливо, що в середині імпульсу можна отримати значення біта). 

Слід зазначити, що на виході датчика TSOP показаний сигнал буде инвертирован: 

Розпізнавання ІК команд за допомогою UART на AVR

Для декодування команди необхідно синхронізуватися з фронтом першого імпульсу даних, почекати його середини (280мкс), і продовжити опитування стану датчика кожні 560мкс:

Розпізнавання ІК команд за допомогою UART на AVR

Моменти опитування датчика повинні бути дотримані досить точно (не більше + -100мкс). 

Якщо часові проміжки дотриматися неможливо, то програмне декодування працювати не буде. Потрібно шукати якесь інше рішення. Рішенням "в лоб" було б використовувати другий мікроконтролер, або спеціалізовану мікросхему-декодер. 

Проте варто згадати, що "на борту" у AVR є маса пристроїв, які можна спробувати застосувати не за призначенням :)

UART протокол

UART використовує простий послідовний протокол [3]:

Розпізнавання ІК команд за допомогою UART на AVR

При просте лінія тримається в стоянні "1". Початок передачі визначається спадаючим фронтом "стартового" біта (0). Далі йдуть біти даних, далі - біт парності (може не використовуватися), далі - один або два степових біта (1). Тобто після передачі байта лінія повертається в стан 1, і цикл передачі починається знову. Довжини всіх бітів однакові і рівні 1 / Baud rate.

Протокол UART не сумісний з ІК протоколами.

Однак, якщо забути про UART протоколі і розглядати приймач UART як зсувний регістр з таймером і синхронізацією по спадающему фронту, то виявиться, що він підходить для розпізнавання (майже) будь-яких послідовностей.

Про те, як саме працює приймач UART, можна прочитати в даташіте на AT90USB162 [4]. 

Розпізнавання ІК команд за допомогою UART на AVR

Після визначення спадаючого фронту приймач робить паузу довгою? біта, після чого перевіряє, що лінія все ще в "0" (valid start bit detection). 

Розпізнавання ІК команд за допомогою UART на AVR

Після цього починається цикл прийому бітів даних, без всяких перевірок, через проміжки, рівні довжині бита. Біти даних "заїжджають" в зсувний регістр приймача, а перший стоповий біт - в прапор FE в інвертованому вигляді. 

Якщо описати весь цей процес спрощено, то в режимі 7N1 приймач чекає спадаючого фронту, після чого читає вхід 8 разів через рівні проміжки часу. Але саме так і працює програмне декодування ІК протоколу, описане вище!

Розпізнавання ІК команд за допомогою UART

Розпізнавання ІК команд за допомогою UART на AVR

Давайте подивимося що буде, якщо "згодувати" сигнал з ІЧ приймача в UART.

Мій пульт використовує протокол з часовим проміжком як в протоколі NEC [2], хоча сам формат команди відрізняється. 

Розпізнавання ІК команд за допомогою UART на AVR

Налаштуємо UART в режим 7N1 (7 біт даних, без бітів парності, 1 стоповий біт). Baud rate встановимо в 1.000.000 / 560мкс = 1786 бод. 

Імпульс Mark довжиною 9мс ("0" на виході датчика TSOP) буде прийнятий приймачем як 0000000b з помилковим стоповим бітом:

Розпізнавання ІК команд за допомогою UART на AVR

Після цього приймач буде чекати наступного спадаючого фронту (пропустить до кінця Mark і весь Space). З початком ІК посилки приймач синхронізується на середину біта (560мкс / 2 = 280 мкс) і прочитає 7 біт даних + стоповий біт:

Розпізнавання ІК команд за допомогою UART на AVR

Після прийому 7 + 1 біт, UART буде чекати наступного спадаючого фронту, причому якщо останній біт був "0", то лінія повинна спочатку повернутися в "1". У цей момент у нас відбувається якийсь "пробіл" в прийомі, що унеможливлює точне декодування ІК протоколів, в яких біти кодуються довжиною імпульсів. Але навіть у цьому випадку унікальний пакет буде формувати унікальні дані в приймачі UART. Оскільки завданням є не декодування змісту команди, а розпізнавання посилки, така ситуація нас повністю влаштовує.

Реалізація

Розпізнавання ІК команд за допомогою UART на AVR

Приклад написаний на Codevision AVR 2.05 для ATMega8A, кварцовий резонатор 8МГц.

Основний цикл програми опитує стан UART кожні 4мс і записує отримані дані в циклічний буфер довжиною 12 байт. Довжина буфера вибирається виходячи з довжини ІК посилки.

Розпізнавання ІК команд за допомогою UART на AVR

У мого пульта посилка має довжину 54мс. 54000/560 = 96 біт або 12 повних байт. Вибираємо 11 байт і +1 для стартового нульового (розбирати всю посилку не обов'язково, але дуже важливо, щоб посилка привела до зациклення буфера). Для пультів, у яких довжина посилки відрізняється в залежності від кнопки, алгоритм буде трохи складніше (тут обговорюватися не буде).

Після прийому чергового байта перевіряється, чи є наступний байт в циклічному буфері нульовим. Нульовий байт означає, що ми отримали вже 11 байт посилки, і пора реагувати на команду.

Приклад виводить на термінал (9600N1) CRC32 отриманої команди, байти команди і символьне представлення посилки:

Після отримання кодів можна зменшити помилкові спрацьовування, Розкоментувати секцію:

(ReadCMDBuffer (s_cmdBufferIndex) == 0) && (ReadCMDBuffer (s_cmdBufferIndex + 1) == 0x95) && (ReadCMDBuffer (s_cmdBufferIndex + 2) == 0x95) && (ReadCMDBuffer (s_cmdBufferIndex + 3) == 0xB7) && (ReadCMDBuffer (s_cmdBufferIndex + 4) == 0xB7) && (ReadCMDBuffer (s_cmdBufferIndex + 5) == 0xB7)

   (Вище вставити заголовок кодів свого пульта)

Під "помилкові спрацьовування" тут розуміється визначення перешкод як команди з якимось кодом, а не помилкове спрацьовування правильної кнопки.

Поліпшення

1. Якщо використовувати UART в режимі 9 біт даних, 1 паритет і 1 стоп, то період опитування можна ще збільшити.

2. Приведений алгоритм не перевіряє час, що минув між прийомом байтів. Перевіряючи, можна зменшити помилкові спрацьовування.

3. Під час очікування команди мікроконтролер може перебувати в idle mode і прокидатися по перериванню від UART. 

4. У Power down mode UART не працює. Але якщо з'єднати RX з INT0, то це дасть можливість виводити мікроконтролер в нормальний режим для прийому команди.

Висновок

Алгоритм випробуваний в реальному пристрої і показав відмінні результати.

Матеріали

1. RC-5
2. Інфрачервоне дистанційне керування (PDF)
3. UART 
4. AT90USB162 datasheet (PDF)

Прикріплені файли:
  • IRDecoderUART.rar (17 Кб)
Tags

Коментарі до новини