00:06 Распознавание ИК команд с помощью UART на AVR | ||
Введение О распознавании команд с инфракрасного пульта написано много статей. В-основном, речь идёт о протоколе RC5 от пультов Philips [1]. Этот протокол не единственный и не самый распространённый. Хорошее описание других форматов на русском языке можно найти в документе [2]. Во всех найденных мною статьях распознавание производится чтением состояния датчика TSOP в строго определённые моменты времени ( в обработчике прерывания от таймера или в основном цикле программы ). Однако в моём последнем проекте мне нужно общаться с внешним устройством со строгими временными задержками, из-за чего приходится запрещать прерывания на периоды до 2мс. Этот факт делает невозможным опрос состояния датчика TSOP с требуемой точностью ( раз в 560мкс +-100мкс ). Так родилась идея использовать UART как "хитрый” сдвиговый регистр. В полученной реализации при декодировании NEC-подобного протокола необходимо неспешно опрашивать состояние датчика лишь раз в 4мс, при этом сам микроконтроллер может находиться в idle mode или даже в power down mode! ИК протоколы Не вижу смысла повторять описание протоколов ИК пультов - они описаны достаточно хорошо в статье [2]. Обозначу лишь основные моменты: ИК-посылка на примере протокола NEC состоит из Mark pulse(9мс), Space pulse(4.5мс) и последовательности импульсов данных. В разных протоколах биты данных кодируются по-разному, но длина импульса одной полярности всегда равна или кратна длине импульса противоположной полярности (разницу в несколько микросекунд можно игнорировать, так как накопленная ошибка в течении посылки не мешает декодированию. Важно, что в середине импульса можно получить значение бита). Следует отметить, что на выходе датчика TSOP показанный сигнал будет инвертирован: Для декодирования команды необходимо синхронизироваться с фронтом первого импульса данных, подождать его середины (280мкс), и продолжить опрос состояния датчика каждые 560мкс: Моменты опроса датчика должны быть соблюдены достаточно точно (не более +-100мкс). Если временнЫе промежутки соблюсти невозможно, то программное декодирование работать не будет. Нужно искать какое-то другое решение. Решением "в лоб” было бы использовать второй микроконтроллер, или специализированную микросхему-декодер. Однако стоит вспомнить, что "на борту” у AVR есть масса устройств, которые можно попробовать применить не по назначению :) UART протокол UART использует простой последовательный протокол [3]: При простое линия держится в стоянии "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. Если использовать UART в режиме 9 бит данных, 1 паритет и 1 стоп, то период опроса можно ещё увеличить. 2. Приведённый алгоритм не проверяет время, прошедшее между приёмом байтов. Проверяя, можно уменьшить ложные срабатывания. 3. Во время ожидания команды микроконтроллер может находиться в idle mode и просыпаться по прерыванию от UART. 4. В Power down mode UART не работает. Но если соединить RX с INT0, то это даст возможность выводить микроконтроллер в нормальный режим для приёма команды. Заключение Алгоритм опробован в реальном устройстве и показал отличные результаты. Материалы 1. RC-5 Прикрепленные файлы:
Статья скопирована с http://cxem.net/ik/2-21.php | ||
|
Всего комментариев: 0 | |