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

Осваиваем AVR микроконтроллеры – система команд

Источник: http://nikolaew.org/avr_old/u3.htm

AVR для начинающих.Урок 3.Порты ввода/вывода

Итак, продолжим знакомство с микроконтроллерами!

Сегодня мы рассмотрим такую важную тему как порты ввода/вывода. С ними мы столкнулись уже в предыдущем уроке, когда зажигали светодиод. Взаимодействие микроконтроллера с внешними устройствами, происходит именно благодаря портам ввода/вывода (Порты I/O(Input/Output)).

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

I/O порт микроконтроллера AVR в программном виде представляет из себя 3 регистра, которые непосредственно отвечают за его работу. Так как микроконтроллеры AVR 8 разрядные, ножки контроллера для удобства были сгруппированы в порты по 8 штук.

То есть, ножки контроллера PB0-PB7 являются портом B микроконтроллера AtMega8. Точно так же с выводами PD0-PD7, которые являются портом D.

Каждой ножке соответствует бит в управляющих регистрах. То есть ножке под номером 4 (Например PB4) соответствует 4 бит в регистрах PORTB,DDRB,PINB.

Каждая ножка порта может быть как портом ввода, так и портом вывода. То есть, мы можем либо управлять чем либо (например зажигать светодиод), либо принимать данные с чего либо (например обрабатывать нажатие кнопки).

За работу порта отвечает 3 регистра:

Каждый из данных регистров 8 разрядный. То есть, каждый бит данного регистра регулирует работу одной ножки контроллера. Рассмотрим каждый из данных регистров подробнее.

Рассматривать будем на примере порта B микроконтроллера AtMega8.

DDRB:

Каждый бит регистра DDRB отвечает за режим работы соответствующей ножки (PB0-PB7). Записав 0 в соответствующий бит, мы настраиваем соответствующую ножку в режим входа. То есть, теперь мы сможем считывать с неё входящие с внешних устройств данные. Записав в соответствующий бит 1 мы установим ножку в режим вывода, что позволит нам управлять чем либо (Например зажигать светодиод).

Читайте также  AVR для начинающих. Урок 15. Регистры EEPROM.

Пример кода на C(Настройка ножки PD4 на вывод):

Пример кода на ASM(Настройка ножки PD4 на вывод):

PORTB:

При настройке соответствующего вывода на вывод, регистр PORTB управляет состоянием данной ножки.

То есть установив 1 в соответствующем бите регистра, мы подадим логическую 1 на вывод контроллера (Около +5 вольт), тем самым мы, например, зажигаем светодиод, подав на него +5v.

Установив 0 в соответствующем бите регистра PORTB, мы установим логический 0 на выводе контроллера (Около 0 вольт), тем самым, например, мы гасим светодиод, подав на него около 0v, что прекратит протекание электрического тока через него.

Пример кода на C(установим ножку PB3 в состояние вывода и подадим на нее логическую единицу):

Пример кода на Ассемблере(установим ножку PB3 в состояние вывода и подадим на нее логическую единицу):

PINB:

Каждый бит регистра PINB, показывает текущее состояние соответствующей ножки контроллера, при её настройке в состояние ввода. Данный регистр, в отличии от двух предыдущих работает только в режиме чтения.

То есть записать что либо в него мы не можем, однако считать состояние текущей ножки контроллера не составит труда! При подаче логической единицы на соответствующую ножку контроллера(которая разумеется работает в режиме ввода), в соответствующий бит данного регистра будет записана единица. Наоборот, при подаче логического нуля, в соответствующий бит будет записан 0.

Следующий пример поможет Вам лучше понять описанное выше:

Читайте также  AVR для начинающих. Урок 4. Тактирование микроконтроллера.

Соберем следующую цепь

Номинал резистора R1, вы уже можете рассчитать самостоятельно!

Создадим в Atmel Studio новый проект на удобном Вам языке.

С:

MOV Rd,Rs Эта команда копирует содержимое регистра Rs в регистр Rd. Содержимое Rs не изменяется, предыдущее содержимое Rd теряется. Пример:Работает со всеми регистрами. Биты признаков не изменяет.
LDI Rd,K Загружает в регистр Rd 8-ми разрядную константу. Работает со старшими регистрами (R16-R31). Пример:Биты признаков не изменяет. Если необходимо загрузить константу в младший регистр, то это делается двумя командами:
LD Rd,X Загружает в регистр Rd байт из памяти данных, адрес ячейки памяти в регистровой паре X. Содержимое регистровой пары X не изменяется. Например:Биты признаков не изменяет.
LD Rd,X+ Аналогично предыдущей команде, но содержимое регистровой пары X после выполнения пересылки данных увеличивается на 1. Например:Биты признаков не изменяет.
LD Rd,-X Аналогично предыдущей команде, но содержимое регистровой пары X перед выполнением пересылки данных уменьшается на 1. Например:Биты признаков не изменяет.
LD Rd,YLD Rd,Y+LD Rd,-YLD Rd,ZLD Rd,Z+LD Rd,-Z Эти команды работают абсолютно идентично трем ранее описанным, за исключением того, что индексным регистром является не X, а Y и Z. Наличие трех пар регистров дает возможность эффективной работы с блоками памяти, например:В результате выполнения этого цикла 10 байт памяти, начиная с адреса 0x200 будут скопированы в область памяти с адресом 0x180
LDD Rd,Y+qLDD Rd,Z+q Регистровые пары Y и Z, кроме вышеописанных методов обращения к памяти данных, имеют еще один. В этом случае в регистр Rd загружается байт из ячейки памяти, чей адрес вычисляется как содержимое регистровой пары плюс 6-ти разрядное смещение. Содержимое регистровой пары не изменяется! Например:Такой режим адресации невозможен для регистровой пары X. Значение смещения q – от 0 до 63.
Мы рассмотрели команды LD и LDD, которые обеспечивают пересылку данных из памяти данных в регистр общего назначения. Естественно, что для каждой команды LD и LDD имеется “обратная” ей команда – записи в память данных из регистра. Эти команды имеют мнемоники соотвественно ST и STD (store). Например:Думаю, что совершенно нет необходимости расписывать каждую из них в отдельности…
LDS Rd,ASTS A,Rs Команда LDS загрузит в регистр Rd содержимое ячейки памяти данных с адресом A, где A – шестнадцатиразрядная константа. В этом случае нет необходимости предварительно загружать регистровую пару, но сама команда займет два слова программной памяти, а не одно, как предыдущие. Например:Парой для команды LDS является команда STS – записывающая содержимое регистра в память.
LPM К командам пересылки данных надо отнести и очень специфичную команду LPM, которая пересылает в R0 байт памяти программ, на который указывает региcтровая пара Z. Напомню, что память программ и память данных между собой никак не пересекаются. Данная команда используется в основном для чтения таблиц констант, располагаемых в памяти программ. Например:Содержимое регистровой пары Z не изменяется, биты признаков – тоже. Вообще, ни одна команда пересылки данных не изменяет  признаков.Важно! Поскольку для команды LPM адресация побайтная, а память программ адресуется словами (слово = 2 байта), то необходимо при загрузке адреса таблицы адрес умножить на 2!
IN Rd, I/O Команда IN прочтет байт из регистра ввода-вывода в регистр общего назначения, например:Работает со всеми регистрами, биты признаков не изменяет.
OUT I/O, Rs  А эта – из регистра выведет в порт.
PUSH RsPOP Rd  Эти команды предназначены для работы со стеком. Команда PUSH поместит Rs в стек, после выполнения команды указатель стека уменьшается на единицу. Команда POP извлечет байт из стека и поместит его в Rd. Соответственно, указатель стека увеличится на единицу.Указатель стека должен быть установлен (как правило – на последний байт ОЗУ) при старте программы!
ADD Rd,Rs
ADC Rd,Rs
ADIW Rdl,q
SUB Rd,Rs
SUBI Rd,K
SBC Rd,Rs
SBCI Rd,K
SBIW Rdl,q
AND Rd,Rs
ANDI Rd,K
OR Rd,Rs
ORI Rd,K
EOR Rd,Rs
COM Rd
NEG Rd
SBR Rd,K
CBR Rd,K
INC RdDEC Rd
TST Rs
CLR Rd
SER Rd

 Уффф… Что-то длинная страничка получается. 

Наверное, остальные команды опишу в

#include // подключаем заголовочные файлыDDRB|=(1

Источник: http://mkprog.ru/avr/avr-dlya-nachinayushhih-urok-3-porty-vvoda-vyvoda.html

Самодельный ИК-приемник сигналов дистанционного управления (ATtiny13)

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

Можно организовать срабатывание от определенной команды определенного выхода микроконтроллера, а можно передавать декодированные команды по какому либо интерфейсу в другие устройства или на компьютер.

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

Итак, вам понадобятся: контроллер ATtiny13, интегральный фотоприемник, четыре транзистора, четыре светодиода, несколько резисторов и конденсаторов.

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

Схема приемника:

Для питания схемы необходимо стабильное питание +5В. (Как сделать миниатюрный импульсный блок питания на 5В смотрите здесь).ILMS5360 — интегральный фотоприемник на частоту несущей 36 кГц (если на входе импульсы 36кГц — на выходе низкий уровень, если нет импульсов — высокий уровень).Транзисторы VT1, VT2, VT3, VT4 — любые маломощные (для светодиодов) или среднемощные (для реле) транзисторы. На них реализованы транзисторные ключи.Токи базы транзисторов задаются резисторами R2, R3, R4, R5.Токи через светодиоды (яркость) можно регулировать резисторами R6, R7, R8, R9 (при указанных на схеме номиналах — токи светодиодов около 2 мА).С1 — электролит 100мкФ х 10В, С2 — керамика 0,1 мкФ.

В итоге получается вот такой приемник:

Скачать печатную плату (DipTrace)Эта плата разведена под использование SMD компонентов. Если вы будете использовать другие компоненты, то плату придется переделывать.Как самому собрать программатор для работы с контроллерами AVR — смотрите здесь.Если на сборку программатора нет времени, то вот здесь его можно купить.

Программа для приёма сигналов по протоколу RC-5

Программа для приёма сигналов по протоколу RC-5, не зависящая от точности генератора.

Источник: http://radiohlam.ru/?p=1121

Декодирование сигналов протокола RC5

Дата публикации: 24 июля 2012.

Рейтинг:  5 / 5

В шести разрядах С5—С0 записан собственно код команды, в данном случае 0x35 (00110101), “Воспроизведение”.

Коды команд для некоторых функций приведены ниже:О – 9 – Цифровые величины 0 – 9;12 – Дежурный режим;15 – Дисплей;13 – Пауза;16 – Громкость”+”;17 – Громкость30 – Поиск вперед;31 – Поискназад; 45 – Выброс;48 – Пауза;50 – Перемотка назад;51 – Перемотка вперед;53 – Воспроизведение;54 – Стоп;

55 – Запись;

Протокол RC5 позволяет с помощью одного пульта подавать по 64 команды независимо на 32 различных устройства Если этого недостаточно, используют “расширенный” протокол RC5, согласно которому еще один разряд команды (С6) занимает место второго стартового (St2). Таким образом, число возможных команд возрастает до 128.

При передаче команд по ИК каналу связи сформированной кодовой последовательностью RC5 модулируют несущую частоту 36 кГц, в результате чего ПДУ излучает пачки ИК импульсов этой частоты (черный цвет). Для их приема обычно применяют специализированные фотоприемники, импульсная последовательность на выходе которых (зеленый цвет) инверсна исходной.

Закрепим теоретические знания практикой. Соберем декодер сигнала RC5.

Прибор будет принимать команды с пульта дистанционного управления и декодировать их, выводя их коды в десятичной системе на семисегментный индикатор.

Как всегда используем микроконтроллер Atmega8, который будет тактироваться от внутреннего генератора частотой 8МГц. Индикатор двухразрядный с общим анодом. Схема прибора показана на рисунке 2.

Рисунок 2

Сигнал, принятый и демодулированный ИК приемником IC2, поступает на вывод 4 (PD2) микроконтроллера IC1, сконфигурированный как вход с внутренним “подтягивающим” резистором. Не помешает и внешний подтягивающий резистор. Блокировочный конденсатор С1 должен быть расположен как можно ближе к выводам питания ИК приемника.

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

Так как микроконтроллер, ответственный за декодирование как правило выполняет ещё множество других функций то по приходу каких-либо импульсов с ИК приёмника он должен прерываться на обработку посылки.

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

Первое, что нужно сделать в процедуре обработки прерывания – это запомнить показания таймера, обнулить таймер и запустить его снова. Так, как прерывание у нас первое, то просто обнуляем и запускаем таймер. Считываем уровень на входе и запоминаем его в нулевом бите переменной. Сдвигаем переменную влево.

Устанавливаем признак того, что произошла запись и увеличиваем на 1 счётчик принятых бит. По приходу второго прерывания так же запоминаем показания таймера, перезапускаем его и смотрим, сколько прошло времени. Если интервал получился длиной в период, то импульс был “длинный”.

А это значит, что в любом случае мы прервались в середине периода и надо производить запись уровня на входе в переменную, снова сдвигать её влево и снова увеличивать счётчик.

Если интервал получился длиной в полпериода, то импульс был “коротким”. А это значит, что мы могли прерваться как в середине, так и на границе периода. Тогда проверяем  признак записи.

Если по прошлому прерыванию запись происходила, то мы на границе периода и запись в переменную не производим. Сбрасываем признак записи и ждём следующего прерывания.

Если-же признак записи не установлен, то мы прервались в середине периода. Производим запись, сдвигаем переменную, устанавливаем признак записи и увеличиваем счётчик бит на 1.

Таким образом принимаем все 14 бит, останавливаем  таймер, сбрасываем счётчик бит и признак записи. Переходим к процедуре обработки принятого слова.

Так-же необходимо предусмотреть прерывание от измеряющего таймера, если временной интервал превысит полтора периода. По этому прерыванию следует сбросить все переменные и счётчики ибо произошла ошибка при приёме команды.

начения времени для  “длинного” и “короткого” интервалов следует взять с запасом плюс-минус 20%, т.к. не во всех пультах ДУ задающий генератор стабилизирован кварцевым резонатором. Иногда он выполняется на RC цепочке и частота его не стабильна.

Исходный код полностью представлен ниже:

// Декодирование сигналов протокола RC5 #include #include #include // Временные пределы #define Tmin 40 // длинный промежуток #define Tmax 68 #define TminK 22 // короткий промежуток #define TmaxK 34 //——————0—–1—–2—–3—–4 char SEGMENTE[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, //——————5—–6—–7—–8—–9 0x6D, 0x7D, 0x07, 0x7F, 0x6F}; volatile unsigned char segcounter = 0; volatile int display1 = 0; volatile int display2 = 0; unsigned char sct_bit = 0; // Счетчик битов RC5 unsigned char RC5_buffer [14]; // Буфер RC5 unsigned char centre = 0; // Флаг центра unsigned char not_korr = 0; // Флаг попадания в промежутки unsigned char Timer = 0; // число в счетчике таймера unsigned char command = 0; // переменная для команды // Функция очистки буфера void rc5_cl_buf(void) { unsigned char i = 0; for (i=0; i

Источник: https://radioparty.ru/prog-avr/program-c/392-lesson-01

Ик бампер на микроконтроллере

Ранее в блоге я писал про идею собрать ИК бампер, вот как бы видно настало время описать то, что у меня получилось.

Как всегда путь к результату был тернист, с кучей остановок и не нужных поворотов.
За основу был взят микроконтроллер ATmega8.

Суть устройства следующая:
– есть излучатель ИК сигналов, я решил его построить на транзисторе КТ315 и ИК диоде, который был подобран как раз на частотный диапазон датчика ИК сигналов TSOP1736.

– и есть приемник ИК сигналов TSOP1736.
Облучаем приемник сигналом передатчика и смотрим характеристики.

Первые попытки получить отклик на выходе TSOP1736 не дали результата. Как все оказалось проблема была в транзисторе, в самом первом эксперименте я использовал планарный n-p-n транзистор производства Phillips BC547. По паспорту он должен был выдержать ток, по сему сразу остановился на нем, потому что он был в наличии)))

После первого же запуска стало понятно что фиг что выйдет, так как транзистор BC547 непонятно почему начал греться. После еще нескольких попыток решил использовать старый добрый КТ315! И о чудо! С криками “ХАЛЕЛЛУЙЯ” все заработало как надо.

Настройка и проверка работы устройства усложнялась еще тем, что ИК лучи не видимы для человеческого глаза, они находятся в невидимой для человека части спектра радиосигнала.

Для экспериментов был собран на скорую руку стенд:

Схема устройства очень простая, представлена на рисунке ниже:

Для генерации несущей частоты в 36 кГц я решил использовать таймер, и сделать все аппаратно.

  1. //Подключаем библиотеки

  2. #include //Библиотека ввода/вывода

  3. #include //Библиотека прерываний

  4. //Перечисляем наши переменные

  5. int x, s; //Переменные

  6. #define R_division 1 //константа делителя для АЦП

  7. unsigned int u=0; //Глобальная переменная с содержимым преобразования

  8. #define nop() {asm(“nop”);} //Функция из ассемблера для задержки

  9. //Перечисляем прототипы функций

  10. void delay(int t); //Функция задержки

  11. unsigned int getADC(); //Функция извлечения значения с АЦП

  12. //Функция задержки

  13. void delay(int t)

  14. {

  15. for (x=t; x>0 ;x–)

  16. nop ();<\p>

  17. }

  18. //Считывание АЦП

  19. unsigned int getADC(void)<\p>

  20. {<\p>

  21. unsigned int v;

  22. ADCSRA|=(1

Источник: https://avrlab.com/node/244

Распознавание ИК команд с помощью UART на AVR – 29 Декабря 2013 – МАЛАТОК

Введение

О распознавании команд с инфракрасного пульта написано много статей. В-основном, речь идёт о протоколе 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 полученной команды, байты команды и символьное представление посылки:

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

?

123456 ( 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://malatok.at.ua/news/raspoznavanie_ik_komand_s_pomoshhju_uart_na_avr/2013-12-29-58

Декодирование сигналов инфракрасного пульта дистанционного управления

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

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

Один из самых распространенных протоколов, судя по интернету,  – это RC5.  Изначально я думал, что придется разбираться с ним, но ни одного пульта с таким протоколом у меня под рукой не оказалось.

Зато нашлись три пульта от DVD плееров, использующих протокол фирмы NEC. 

   Принцип передачи ИК сигналов заключается в следующем – электрический сигнал несущей частоты модулируется передаваемыми данными и с помощью инфракрасного светодиода излучается в пространство. 

   Передача сигнала уже реализована в пульте, этот вопрос мы не затрагиваем, хотя ничего сложного там нет.

   Для приема сигнала используется специальная микросхема, объединяющая в себе фотодиод, усилитель с полосовым фильтром, настроенным на определенную несущую частоту, и детектор, выделяющий огибающую сигнала. Как правило, микросхема имеет три вывода – два питающих и один сигнальный. Последний подключен к коллектору выходного транзистора микросхемы, из-за чего сигнал на выходе оказывается инвертированным. 

   Микросхемы этого семейства объединены общей аббревиатурой— TSOP.

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

   Правда есть один момент, ИК приемник рассчитан на работу с одной несущей частотой, а в некоторых протоколах значения несущих частот отличаются – одни используют 38 кГц (например, протокол фирмы Nec),  другие 36 или 40. Поэтому одна и та же схема не сможет работать со всеми без исключения ИК пультами дистанционного управления.

   Схема, которую я использовал при написании программы, приведена на рисунке ниже. Прием ИК сигналов осуществлялся микросхемой TSOP2138, рассчитанной на частоту 38 кГц.  

   Для передачи данных используется несущая частота 38 кГц. Посылка состоит из стартового импульса и четырех байтов данных – адрес, инвертированное значение адреса, команда, инвертированное значение команды.  Адрес и команда передаются дважды для повышения надежности. 

   Данные передаются младшим битом вперед. Каждый бит начинается с пачки импульсов несущей частоты. Длительность пачки равна 560 мкс.  Путем изменением временного интервала между пачками импульсов осуществляется кодирование нулей и единиц. При передаче логической единицы интервал от начала текущей до начала следующей пачки импульсов составляет 2.25 мс, а при передаче логического нуля – 1.12 мс.      Стартовый импульс представляет собой пачку импульсов  несущей частоты длительностью 9 мс. После подачи стартового импульса следует пауза в 4.5 мс.

Посылка, содержащая адрес и команду передается однократно, но при удержании кнопки пульта дистанционного управления через каждые 110 мс излучается код повтора – пачка импульсов несущей частоты длительностью 9мс, пауза в 2.25 мс и пачка импульсов длительностью 560 мкс.

 

Существует расширенная версия протокола Nec, в которой используется 16-ти разрядные адреса.

Алгоритм декодирования сигналов ПДУ

   Для декодирования ИК сигналов, соответствующих протоколу Nec, требуется измерять время между передаваемыми пачками импульсов. Для этого можно использовать схему захвата,  внешнее прерывание или банальный опрос вывода микроконтроллера. Я остановил свой выбор на схеме захвата.   Рассмотрим алгоритм работы программы, декодирующей сигналы ПДУ.

(Код не привожу, чтобы не загромождать описание.

)  В начале функции main() выполняется инициализация таймера Т1 –  разрешается прерывание по событию «захват», устанавливается работа схемы захвата по спадающему фронту (потому что сигнал на выходе ИК приемника инвертированный), нормальный режим работы таймера и коэффициент предделителя, позволяющий вычислять длительность между пачками импульсов без многократных переполнений счетного регистра. Инициализируется lcd дисплей, используемый для отладки. Устанавливается флаг глобального разрешения/запрещения прерываний.   Далее микроконтроллер «попадает» в бесконечный цикл while, в котором вызываются функции обработки и вывода данных – TIM_Handle() и TIM_Display() соответственно.   

   Параллельно выполнению основного кода, работает таймер Т1 и его схема захвата. Как только логический уровень вывода ICP(PD6) меняется с «1» на «0» выполнение основного кода прекращается и вызывается обработчик прерывания. В обработчике микроконтроллер сохраняет текущее и предыдущее значение счетчика таймера и устанавливается флаг, сигнализирующий функции TIM_Handle() о захвате нового значения.

   Функция TIM_Handle() представляет собой конечный автомат с двумя состояниями – IDLE(ожидание) и RESEIVE(прием). В начале функции проверяется установка программного флага и в случае выполнения условия, вычисляется длительность временного интервала и выполняется код автомата.

   Начальное состояние автомата –IDLE. В этом состоянии автомат ожидает появление стартового импульса или кода повтора.

Если длительность временного интервала меньше максимально возможного значения, но больше порогового – принят стартовый импульс. Автомат инициализирует переменные и меняет свое состояние на RESEIVE.

Если значение меньше порогового – принят импульс повтора, выполняется инкремент счетчика  повторов (пятый байт массива buf[]).

   Переменные, используемые автоматом:

currentState – текущее состояние автомата,

period – длительность временного интервала,

data – приемный «сдвиговый регистр», 

countBit – счетчик принятых битов, 

countByte – счетчик принятых байтов,

buf[] – пяти байтовый массив данных  – адрес, инвертированное значение адреса, команда, инвертированное значение команды, количество повторов

   В состоянии RESEIVE автомат сравнивает длительность временного интервала с максимально возможным значением и с пороговым. Если интервал больше порогового значения – значит, принята единица, если меньше – то ноль. 

   В случае приема единицы в переменной data устанавливается 7 разряд. Далее  проверяются счетчики битов и байт, с помощью которых контролируется «укладка» битовой последовательности в массив. 

   Как только будет принято четыре байта, автомат установит флаг RESEIVE_OK и сменит состояние на IDLE. 

    Флаг RESEIVE_OK сигнализирует функции TIM_Display() о выводе принятых данных на символьный lcd. В данном проекте дисплей использовался исключительно в целях отладки.

nec-winavr.rar
nec-codevision.rar

Источник: http://chipenable.ru/index.php/item/96

Ик загрузчик для микроконтроллеров avr. часть 1. host-устройство

» Схемы » Интерфейсы · Применение микроконтроллеров

12-10-2010

ИК загрузчик – это микроконтроллерный электронный комплекс, с помощью которого возможно осуществить дистанционное программирование микроконтроллеров семейства AVR в пользовательском устройстве по ИК каналу связи.

Комплекс состоит из двух частей: целевое устройство и Host-устройство. Целевое устройство имеет ИК-приемник, ИК-передатчик и два канала интерфейса внутрисхемного программирования (для подключения к пользовательскому устройству).

Передатчик (Host-устройство) подключается к USB интерфейсу компьютера, на котором установлено соответствующее ПО и драйверы Host-устройства.

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

Изначально основной целью данного проекта была программная реализация USB интерфейса на микроконтроллерах семейства AVR компании Atmel с помощью программной библиотеки известной как V-USB от Objective Development Software.

Host-устройство базируется на микроконтроллере ATmega8, на котором с помощью V-USB программно реализован USB интерфейс. К микроконтроллеру подключаются ИК-приемник и ИК-передачик, которые собраны в виде отдельных подключаемых модулей. Для программного обеспечения использовался компилятор WinAVR (AVR-GCC).

Программное обеспечение для персонального компьютера написано с использованием бесплатной библиотеки Libusb-Win32 и скомпилировано с использованием Lazarus Freepascal.

Полностью вся реализация использует пользовательский класс устройства, требует простой inf-файл и драйвер libusb, установленный на персональном компьютере.

Передача данных по ИК каналу реализуется при помощи встроенного в микроконтроллер ATmega8 модуля UART и Таймера 2 (таймер используется в качестве генератора сигнала модуляции 38 кГц). Скорость передачи данных 2400 бит/с.

При использовании одного ИК светодиода коммуникация между Host и целевым устройством возможна на расстоянии 6.5 м. В последней версии ИК-передатчика применены 6 ИК светодиодов, что позволило увеличить расстояние до 15 метров.

Принципиальная схема Host-устройства

Кликните для увеличения

Отличительные особенности и характеристики Host-части проекта:

  • программное обеспечение микроконтроллера реализует устройство пользовательского класса;
  • поддержка операций работы с памятью микроконтроллера: стирание, запись, чтение;
  • доступ возможен к Flash-памяти, EEPROM, fuse-битам;
  • определение ошибок в процессе передачи данных (CRC16);
  • размер пакета данных 128 Байт (возможно дальнейшее увеличение длины);
  • процедура usbpoll не может быть запущена, пока идет передача данных USART. Работа модуля USART имеет высший приоритет, чтобы поддерживать ИК коммуникацию между Host и целевым устройством;
  • разработка для микроконтроллеров семейства AVR (не все модели протестированы, ограничения накладываются по частоте сигнала тактирования SCK интерфейса ISP в различных сериях микроконтроллеров);
  • максимальный объем целевой памяти с которой поддерживается работа 32640 Байт (32 КБайт) – это ограничение накладывается из-за ограниченного количества пакетов данных (255) и длиной пакета данных (128 Байт)

Принципиальная схема модуля ИК-передатчика

Принципиальная схема модуля ИК-приемника

Список компонентов для Host-части комплекса

Обозначение в схеме

Описание

IC1

Микроконтроллер ATmega8

C1, C2

18 пФ

С3

100 нФ

С5

10 мкф

Q2

Кварцевый резонатор 12 МГц

R1

10 кОм

R2, R6

68 Ом

R3, R4, R5, R8

330 Ом

R7

1.5 кОм

D1, D2, D3, D4

Светодиоды красного, зеленого, синего и
белого цвета свечения соответственно

DZ1, DZ2

Стабилитрон 3.6 В

KONEKTOR_ISP

Коннектор интерфейса внутрисхемного
программирования

KONEKT

Коннектор USB

Модуль ИК-передатчика

IC1C, IC1D

Логические элементы микросхемы 74HC32

Q1, Q2

Транзистор 2N3906

IR1, IR2, IR3, IR4, IR5, IR6

Светодиоды ИК IR333/H0/L10

R1, R3

820 Ом

R2, R4

22 Ом

R9

330 Ом

LED1

Светодиод красного цвета свечения

Модуль ИК-приемника

IRM8510

Модуль ИК-приемника IRM-8510

R9

1 кОм

С1

100 мкФ

LED

Светодиод красного цвета свечения

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

Загрузки

Host-часть: принципиальная схема, программное обеспечение для микроконтроллера, программное обеспечение для ПК: 20081008.host.side.zip

Модуль ИК-приемника, модуль ИК-передатчика: принципиальная схема: 20080726.ir.circuit.zip

Ссылки

avrirdownloader.wordpress.com

Источник: https://www.rlocman.ru/shem/schematics.html?di=67235

Ссылка на основную публикацию
Adblock
detector
",css:{backgroundColor:"#000",opacity:.6}},container:{block:void 0,tpl:"
"},wrap:void 0,body:void 0,errors:{tpl:"
",autoclose_delay:2e3,ajax_unsuccessful_load:"Error"},openEffect:{type:"fade",speed:400},closeEffect:{type:"fade",speed:400},beforeOpen:n.noop,afterOpen:n.noop,beforeClose:n.noop,afterClose:n.noop,afterLoading:n.noop,afterLoadingOnShow:n.noop,errorLoading:n.noop},o=0,p=n([]),h={isEventOut:function(a,b){var c=!0;return n(a).each(function(){n(b.target).get(0)==n(this).get(0)&&(c=!1),0==n(b.target).closest("HTML",n(this).get(0)).length&&(c=!1)}),c}},q={getParentEl:function(a){var b=n(a);return b.data("arcticmodal")?b:(b=n(a).closest(".arcticmodal-container").data("arcticmodalParentEl"),!!b&&b)},transition:function(a,b,c,d){switch(d=null==d?n.noop:d,c.type){case"fade":"show"==b?a.fadeIn(c.speed,d):a.fadeOut(c.speed,d);break;case"none":"show"==b?a.show():a.hide(),d();}},prepare_body:function(a,b){n(".arcticmodal-close",a.body).unbind("click.arcticmodal").bind("click.arcticmodal",function(){return b.arcticmodal("close"),!1})},init_el:function(d,a){var b=d.data("arcticmodal");if(!b){if(b=a,o++,b.modalID=o,b.overlay.block=n(b.overlay.tpl),b.overlay.block.css(b.overlay.css),b.container.block=n(b.container.tpl),b.body=n(".arcticmodal-container_i2",b.container.block),a.clone?b.body.html(d.clone(!0)):(d.before("
"),b.body.html(d)),q.prepare_body(b,d),b.closeOnOverlayClick&&b.overlay.block.add(b.container.block).click(function(a){h.isEventOut(n(">*",b.body),a)&&d.arcticmodal("close")}),b.container.block.data("arcticmodalParentEl",d),d.data("arcticmodal",b),p=n.merge(p,d),n.proxy(e.show,d)(),"html"==b.type)return d;if(null!=b.ajax.beforeSend){var c=b.ajax.beforeSend;delete b.ajax.beforeSend}if(null!=b.ajax.success){var f=b.ajax.success;delete b.ajax.success}if(null!=b.ajax.error){var g=b.ajax.error;delete b.ajax.error}var j=n.extend(!0,{url:b.url,beforeSend:function(){null==c?b.body.html("
"):c(b,d)},success:function(c){d.trigger("afterLoading"),b.afterLoading(b,d,c),null==f?b.body.html(c):f(b,d,c),q.prepare_body(b,d),d.trigger("afterLoadingOnShow"),b.afterLoadingOnShow(b,d,c)},error:function(){d.trigger("errorLoading"),b.errorLoading(b,d),null==g?(b.body.html(b.errors.tpl),n(".arcticmodal-error",b.body).html(b.errors.ajax_unsuccessful_load),n(".arcticmodal-close",b.body).click(function(){return d.arcticmodal("close"),!1}),b.errors.autoclose_delay&&setTimeout(function(){d.arcticmodal("close")},b.errors.autoclose_delay)):g(b,d)}},b.ajax);b.ajax_request=n.ajax(j),d.data("arcticmodal",b)}},init:function(b){if(b=n.extend(!0,{},a,b),!n.isFunction(this))return this.each(function(){q.init_el(n(this),n.extend(!0,{},b))});if(null==b)return void n.error("jquery.arcticmodal: Uncorrect parameters");if(""==b.type)return void n.error("jquery.arcticmodal: Don't set parameter \"type\"");switch(b.type){case"html":if(""==b.content)return void n.error("jquery.arcticmodal: Don't set parameter \"content\"");var e=b.content;return b.content="",q.init_el(n(e),b);case"ajax":return""==b.url?void n.error("jquery.arcticmodal: Don't set parameter \"url\""):q.init_el(n("
"),b);}}},e={show:function(){var a=q.getParentEl(this);if(!1===a)return void n.error("jquery.arcticmodal: Uncorrect call");var b=a.data("arcticmodal");if(b.overlay.block.hide(),b.container.block.hide(),n("BODY").append(b.overlay.block),n("BODY").append(b.container.block),b.beforeOpen(b,a),a.trigger("beforeOpen"),"hidden"!=b.wrap.css("overflow")){b.wrap.data("arcticmodalOverflow",b.wrap.css("overflow"));var c=b.wrap.outerWidth(!0);b.wrap.css("overflow","hidden");var d=b.wrap.outerWidth(!0);d!=c&&b.wrap.css("marginRight",d-c+"px")}return p.not(a).each(function(){var a=n(this).data("arcticmodal");a.overlay.block.hide()}),q.transition(b.overlay.block,"show",1*")),b.overlay.block.remove(),b.container.block.remove(),a.data("arcticmodal",null),n(".arcticmodal-container").length||(b.wrap.data("arcticmodalOverflow")&&b.wrap.css("overflow",b.wrap.data("arcticmodalOverflow")),b.wrap.css("marginRight",0))}),"ajax"==b.type&&b.ajax_request.abort(),p=p.not(a))})},setDefault:function(b){n.extend(!0,a,b)}};n(function(){a.wrap=n(document.all&&!document.querySelector?"html":"body")}),n(document).bind("keyup.arcticmodal",function(d){var a=p.last();if(a.length){var b=a.data("arcticmodal");b.closeOnEsc&&27===d.keyCode&&a.arcticmodal("close")}}),n.arcticmodal=n.fn.arcticmodal=function(a){return e[a]?e[a].apply(this,Array.prototype.slice.call(arguments,1)):"object"!=typeof a&&a?void n.error("jquery.arcticmodal: Method "+a+" does not exist"):q.init.apply(this,arguments)}}(jQuery)}var debugMode="undefined"!=typeof debugFlatPM&&debugFlatPM,duplicateMode="undefined"!=typeof duplicateFlatPM&&duplicateFlatPM,countMode="undefined"!=typeof countFlatPM&&countFlatPM;document["wri"+"te"]=function(a){let b=document.createElement("div");jQuery(document.currentScript).after(b),flatPM_setHTML(b,a),jQuery(b).contents().unwrap()};function flatPM_sticky(c,d,e=0){function f(){if(null==a){let b=getComputedStyle(g,""),c="";for(let a=0;a=b.top-h?b.top-h{const d=c.split("=");return d[0]===a?decodeURIComponent(d[1]):b},""),c=""==b?void 0:b;return c}function flatPM_testCookie(){let a="test_56445";try{return localStorage.setItem(a,a),localStorage.removeItem(a),!0}catch(a){return!1}}function flatPM_grep(a,b,c){return jQuery.grep(a,(a,d)=>c?d==b:0==(d+1)%b)}function flatPM_random(a,b){return Math.floor(Math.random()*(b-a+1))+a}