Протокол RC5

В некоторых микроконтроллерных проектах в качестве дополнительной функции предлагается разработка системы дистанционного управления прибором. В качестве протокола часто используется довольно распространенный (но далеко не единственный) протокол RC5, так как по нему в Интернете можно найти очень много разнообразной информации. Многие современнеы приложения поддерживают этот протокол, так что возможно "использование не по назначению" ПДУ одного из таких аппаратов. Ведь контроллеру в принципе все равно, откуда поступит сигнал, его нужно лишь "обучить", чтобы в зависимости посланного сигнала выполнялась та или иная операция.
В рассматриваемом примере для пересылки сигнала используется обычный инфракрасный светодиод, управляемый транзостором, который подключен к микроконтроллеру. В качестве приемника используется TSOP 17xx. Последние две цифры 'x' указывают на частоту принимаемого сигнала в кГц. В данном примере использован TSOP 1736. В принципе, с его помощью можно декодировать и сигнал другой частоты, например, 38 кГц, однако, при этом существенно снижаются дальность и помехоустойчивость приема. TSOP 1736 содержит демодулятор, который выделяет из несущей частоты полезный сигнал и производит его предварительное усиление. Затем этот сигнал может быть непосредственно обработан.
Сначала необходимо рассмотреть принципы построения сигнала в формате RC5. Согласно спецификации, блок состоит из 14 битов. Этими битами модулирована соответствующая несущая частота. При этом каждый бит в блоке имеет постоянное значение. Первые два бита - это так называемые стартовые биты. Обычно они всегда равны 1. После них следует триггерный бит. Он изменяет свое значение при каждом нажатии клавиши. Если клавиша нажата постоянно, то он остается неизменным. Далее следуют 5 битов, определяющие адрес прибора и 6 битов, являющиеся собственно кодом команды.
Само собой разумеется, определена также временная схема процесса передачи. Общее время пересылки сигнала составляет примерно 114 мс. Длительность пересылки отдельного бита равна 1,778 мс. Отсюда получаем время пересылки пакета 1,778 мс * 14 = 25 мс и дополнительно паузу длительностью 89 мс.
Все биты пересылаются в бифазной кодировке. Это означает, что всегда в центре периода пересылки одного бита происходит изменение логического уровня сигнала. При этом смена с низкого на высокий уровень означает логический 0, а смена с высокого на низкий уровень означает логическую 1. Возможно, это звучит несколько нелогично, однако обусловлено инвертированием сигнала в приемнике.

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

После того как обсужден вопрос приема сигнала, пора перейти к его генерации, а именно к случаю, когда под рукой нет ПДУ, работающего по протоколу RC5, но зато имеется микроконтроллер.
Генерация частоты может осуществляться с помощью PWM (ШИМ) или простого цикла. Для этой цели, собственно, подойдет самый простой микроконтроллер. Все модели ATMega являются слишком производительными для выполнения этой задачи, ATTiny должен быть более чем достаточным. Он постоянно находится в режиме ожидания (Sleep-Mode) и следит только за нажатием кнопки, после чего пару раз посылает сигнал и вновь возвращается в режим ожидания. Это должно существенно снизить потребление тока и позволить устройству в течение длительного времени работать без замены батареек. Тем не менее, поскольку описываемая схема создавалась лишь для экспериментов, в ней был использован микроконтроллер ATMega8, более знакомый автору.
Так как инфракрасный светодиод потребляет ток около 100 мА (в зависимости от модели), необходимо отказаться от прямого управления диодом, так как в противном случае ресурс микроконтроллера мог бы существенно снизиться. Поэтому в качестве драйвера использован npn-транзистор. Его база через промежуточное сопротивление может быть подключена непосредственно к микроконтроллеру. ИК-светодиод подключается к коллектору, при необходимости последовательно с ним должно быть включено сопротивление, защищающее светодиод от перегрузки. Его номинал можно рассчитать по простой формуле:
Rv = (Us - Uce - Uf)/If = (5V-0,7V-1,5V)/0,13A = 21,5Ω.
Точные величины напряжения и тока (Flussspannung & Flussstrom) можно найти в документации на ИК-диод, напряжение коллектор-эмиттер - в документации на транзистор. Схема может выглядеть следующим образом:

Прежде чем заняться протоколом RC5 вплотную, рассмотрим пару простых тестовых алгоритмов, которые также вполне могут использоваться для простых задач дистанционного управления. Если речь идет об управлении роботом, то вполне достаточно десятка отличающихся друг от друга сигналов, которые могут интерпретироваться как 10 разных команд.
Основу сигналов образует несущий сигнал частотой 36 кГц. Этот сигнал должен быть сгенерирован в первую очередь. Далее приведен пример процедуры для генерации несущей частоты.
//36kHz Trager
TCCR1A = (1<<COM1A1) | (1<<COM1A0) | (1<<WGM11);
TCCR1B = (1<<WGM12) | (1<<WGM13) | (1<<CS10);
OCR1A = 111;
ICR1 = 222;

Приведенный пример работает только при тактовой частоте 8 МГц. В нем используется режим 14, описанный на странице 97 документации на ATMega8. ICR1 определяет верхнюю границу счетчика. Используется прескалер (Prescaler) 1, т.е. счетчик работает с системной частотой. В результате генерируется частота 8 МГц/1/222=36,036 кГц.
Если в регистре направления данных для PORTB установить соответствующий PB1 бит, то на соответствующем выводе появляется сигнал с частотой 36 кГц. С помощью OCR1A можно изменять ширину импульса, в нашем случае выбрано соотношение 1:1.
Теперь созданная несущая может быть промодулирована "полезным сигналом". Следует учитывать, что его частота должна бать в целое число раз меньше частоты несущего сигнала.
Далее в качетсве примера приведен один из возможных вариантов использования таймера для передатчика или приемника. Прерывание приемника вызывается в 8 раз чаще, чем прерывание передатчика, чтобы обеспечить достаточно высокое качество распознавания сигнала.

//Прерывание таймера каждые 2,048 ms для генерации сигнала --> 1/(8MHz/256/64)
TCCR0 = (1<<CS01) | (1<<CS00);
TIMSK |= (1<<TOIE0);

//Реализация сканирования //Прерывание таймера каждые 0,256ms для приема сигнала --> 1/(8MHz/256/8) TCCR0 |= (1<<CS01); TIMSK |= (1<<TOIE0);

ISR передатчика должен на определенное время подавать несущую на передатчик. Длительность определяется переменной pulse. Переменная empty служит функции передачи в качестве индикатора того, продолжается ли процесс передачи или уже завершен. Таким образом предотвращается изменение переменной pulse во время процесса передачи.
volatile unsigned char empty = 0;
volatile unsigned char pulse = 0;

SIGNAL (SIG_OVERFLOW0) { if (pulse) { DDRB |= (1<<PB1); empty = 1; pulse--; } if (!pulse) { empty = 0; DDRB &= ~(1<<PB1); } }
void ir_send (unsigned char byte) { if (!empty) pulse = byte; }

ISR приемника должна ожидать, пока на выходе TSOP не появится сигна низкого уровня. Если это произошло, то можно начинать процесс сканирования длины импульсов. В зависимости от длины импульса сигнал может интерпретироваться как та или иная команда. Количество команд может быть увеличено в любой момент за счет применения импульсов другой длины, здесь же для наглядности используется набор из двух команд.
volatile unsigned short timecount = 0;
volatile unsigned char empty = 0;
volatile unsigned char rec_byte = 0;

SIGNAL (SIG_OVERFLOW0) { //------------ if (!(PINB & (1<<PB0))) { //Low-Pegel = log. 1 am Sender timecount++; empty = 1; } else empty = 0; if ((!empty) && (timecount)) { //----------- //8fache Abtastung if ((timecount > 70) && (timecount < 90)) { //pulse war 10 rec_byte = 10; } if ((timecount > 150) && (timecount < 170)) { //pulse war 20 rec_byte = 20; } timecount = 0; } }
unsigned char ir_receive (void) { //Empfangsroutine return rec_byte; }

Тестовая функция, в которой объединены оба процесса, может быть рассмотрена здесь в рубрике Программа. В ней с помощью #define определяется, должна она работать в режиме передатчика или приемника. Можно было бы составить программу и из двух файлов, однако такой вариант менее удобен на этапе отладки.
Вариант с полной поддержкой протокола RC5 будет добавлен в ближайшем будущем: хотя он уже функционирует, однако иногда возникают проблемы синхронизации. Как только ошибки будут отловлены, эта программа с соответствующими комментариями будет представлена здесь.