Главная » 2013 » Декабрь » 29 » Распознавание ИК команд с помощью UART на AVR
00:06
Распознавание ИК команд с помощью UART на AVR

Введение

О распознавании команд с инфракрасного пульта написано много статей. В-основном, речь идёт о протоколе RC5 от пультов Philips [1]. Этот протокол не единственный и не самый распространённый. Хорошее описание других форматов на русском языке можно найти в документе [2]. 

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

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

Пульты ДУ

ИК протоколы

Не вижу смысла повторять описание протоколов ИК пультов - они описаны достаточно хорошо в статье [2].  Обозначу лишь основные моменты:

ИК-посылка на примере протокола NEC

ИК-посылка на примере протокола NEC состоит из Mark pulse(9мс), Space pulse(4.5мс) и последовательности импульсов данных.

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

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

Осциллограмма ИК сигнала пульта

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

Моменты опроса датчика должны быть соблюдены достаточно точно (не более +-100мкс). 

Если временнЫе промежутки соблюсти невозможно, то программное декодирование работать не будет. Нужно искать какое-то другое решение. Решением "в лоб” было бы использовать второй микроконтроллер, или специализированную микросхему-декодер. 

Однако стоит вспомнить, что "на борту” у AVR есть масса устройств, которые можно попробовать применить не по назначению :)

UART протокол

UART использует простой последовательный протокол [3]:

Последовательный протокол UART

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

Протокол UART  не совместим с ИК протоколами.

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

О том, как именно работает приёмник UART , можно прочесть в даташите на AT90USB162[4]. 

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

После этого начинается цикл приёма битов данных, без всяких проверок, через промежутки, равные длине бита. Биты данных "заезжают” в сдвиговый регистр приёмника, а первый стоповый бит - в флаг FE в инвертированном виде. 

Если описать весь этот процесс упрощенно, то в режиме 7N1 приемник ждёт спадающего фронта, после чего читает вход 8 раз через равные промежутки времени. Но именно так и работает программное декодирование ИК протокола, описанное выше!

Распознавание ИК команд с помощью UART

Давайте посмотрим что будет, если "скормить” сигнал с ИК приёмника в UART.

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

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

Импульс Mark длиной 9мс ("0” на выходе датчика TSOP ) будет принят приёмником как 0000000b с ошибочным стоповым битом:

После этого приёмник будет ждать следующего спадающего фронта (пропустит до конца Mark и весь Space ). С началом ИК посылки приёмник синхронизируется на середину бита (560мкс / 2 = 280 мкс ) и прочитает 7 бит данных + стоповый бит:

После приёма 7+1 бит, UART будет ждать следующего спадающего фронта, причём если последний бит был "0”, то линия должна сначала вернуться в "1”. В этот момент у нас происходит некий "пробел” в приёме, что делает невозможным точное декодирование ИК протоколов, в которых биты кодируются длиной импульсов. Но даже в этом случае уникальный пакет будет формировать уникальные данные в приёмнике UART. Поскольку задачей является не декодирование содержания команды, а распознавание посылки, такая ситуация нас полностью устраивает.

Реализация

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

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

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

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

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

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

1
2
3
4
5
6
( 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)

Прикрепленные файлы:
Статья скопирована с http://cxem.net/ik/2-21.php
Просмотров: 2391 | Добавил: Дмытрохан | Теги: управление с пульта, инфракрасный сенсор, Пульт, ик сенсор | Рейтинг: 0.0/0
Всего комментариев: 0
avatar
Яндекс.Метрика
24 log 24 LOG statistick
счетчик посещений
Если вы видите это,
то ваш браузер устарел
и не поддерживает технологий
CSS 3.0