Алгоритм уверенного декодирования команд ИК пульта
Алгоритм уверенного декодирования команд ИК пульта
Делаю устройство на ATmega48. Управляться оно должно обычного пульта ДУ от бытовой техники. В интернете нашел кучу реализаций разных алгоритмов декодирования сигнала, но все они не подходят по некоторым причинам. Проблемы такие:
1. Контроллер сильно загружен, и декодирование должно занимать минимум ресурсов (тактов, времени)
2. Аппаратные счетчики все заняты
3. Работать должно с любым пультом ДУ после обучения, а не с конкретным (т.е. привязки к протоколу нет)
Проще говоря, надо выщемить из сигнала максимальное количество бит, не зависимо от того, какой протокол используется, дальше дело техники. Два аппаратных счетчика задействованы ШИМом, частота не критична (регулируют яркость), можно использовать их для замеров длительности, с одним условием - не останавливая.
Датчик - TSOP 36кГц, заведён на INT0. Пока идея одна - после срабатывания прерывания сделать как можно больше замеров (снять "осциллограмму") с данного пина, но тоже не надёжно - любое колебание частоты пульта (а это не редкость) приведёт к изменению кода...
Какие варианты посоветуете?
1. Контроллер сильно загружен, и декодирование должно занимать минимум ресурсов (тактов, времени)
2. Аппаратные счетчики все заняты
3. Работать должно с любым пультом ДУ после обучения, а не с конкретным (т.е. привязки к протоколу нет)
Проще говоря, надо выщемить из сигнала максимальное количество бит, не зависимо от того, какой протокол используется, дальше дело техники. Два аппаратных счетчика задействованы ШИМом, частота не критична (регулируют яркость), можно использовать их для замеров длительности, с одним условием - не останавливая.
Датчик - TSOP 36кГц, заведён на INT0. Пока идея одна - после срабатывания прерывания сделать как можно больше замеров (снять "осциллограмму") с данного пина, но тоже не надёжно - любое колебание частоты пульта (а это не редкость) приведёт к изменению кода...
Какие варианты посоветуете?
- Реклама
- Леонид Иванович
- Друг Кота
- Сообщения: 4779
- Зарегистрирован: Сб апр 02, 2011 12:40:46
- Откуда: Минск
- Контактная информация:
Re: Алгоритм уверенного декодирования команд ИК пульта
Я делал как-то помехоустойчивый программный декодер для конкретного кода RC-5, задействовал таймер только для этой задачи, и то замаялся. А ваша задача по-моему вообще неподъемная.
Код: Выделить всё
//----------------------------------------------------------------------------
//Декодер RC-5
//----------------------------------------------------------------------------
//Декодер использует два прерывания: внешнее от фотоприемника и
//прерывание по переполнению таймера 0.
//После того, как обнаружен стартовый бит (переход из единицы
//в ноль на входе прерывания), в обработчике внешнего прерывания
//разрешается прерывание таймера 0 и загружается интервал до первой
//выборки T_SAMPLE. В прерывании таймера 0 делаются выборки для
//каждной половинки бита. Подсчет выборок ведется в переменной SampCnt.
//Количество выборок задается константой SAMPLE_COUNT.
//Логический уровень для каждой половинки бита вычисляется по
//мажоритарному принципу. Для этого вычисляется сумма выборок
//в переменной SampVal. Если на входе обнаруживается ВЫСОКИЙ уровень,
//то к этой переменной добавляется единица, если НИЗКИЙ - вычитается.
//Значение суммы не может быть равно нулю, так как общее количество
//выборок всегда задается нечетным. По первой половине текущего бита
//принимается решение о значении принятого бита. Для проверки
//корректности кода Манчестер этот уровень сравнивается со значением
//второй половины предыдущего бита, которое сохраняется в переменной
//PreVal. Если значения совпадают, была ошибка, и прием начинается
//с начала. То же самое происходит, если очередной переход на входе
//не обнаружен через время T_SAMPLE * 2 после последней выборки
//(ошибка таймаута). Принятые биты вдвигаются в переменную Rc5Code.
//Подсчет принятых битов осуществляется в переменной BitCounter.
//Когда принято RC5_LENGTH битов, прием завершен, номер системы
//копируется в переменную SysVar, а код команды - в переменную ComVar.
//Декодер поддерживает Extended RC-5 Code, второй стартовый бит
//интерпретируется как бит F (Field). Бит F представляет собой
//инвертированный дополнительный (старший) бит кода команды,
//в результате количество команд удваивается.
//----------------------------------------------------------------------------
#include "Main.h"
#include "RC5.h"
//----------------------------- Константы: -----------------------------------
#define PRE 64 //предделитель таймера 0
#define RC5_SLOT 1778 //длительность слота RC-5, мкс
#define RC5_LENGTH 14 //количество принимаемых битов
#define SAMPLE_COUNT 3 //количество выборок (должно быть нечетным)
#define T_SAMPLE_US (RC5_SLOT / ((SAMPLE_COUNT + 1) * 2))
#define T_SAMPLE (T_SAMPLE_US * F_CLK / PRE + 0.5)
//----------------------------- Переменные: ----------------------------------
static char SampCnt; //счетчик выборок
static signed char SampVal; //величина, полученная суммой выборок
static bool PreVal; //значение педыдущего полу-интервала
static int RC5Code; //принятый код
static char BitCounter; //счетчик принятых битов
static char SysVar; //номер системы
static char ComVar; //код команды
//-------------------------- Прототипы функций: ------------------------------
#pragma vector = INT0_vect
__interrupt void EdgeIR(void); //прерывание по сигналу фотоприемника
#pragma vector = TIMER0_OVF_vect
__interrupt void TimerIR(void); //прерывание таймера 0
//----------------- Инициализация модуля декодера RC-5: ----------------------
void RC5_Init(void)
{
BitCounter = RC5_LENGTH; //инициализация счетчика битов
PreVal = 1; //перед стартовым битом была единица
SysVar = 0xFF; //неиспользуемый код системы
ComVar = 0xFF; //неиспользуемый код команды
TCCR0 = (1<<CS00) | (1<<CS01); //прескалер CK/64 для таймера 0
MCUCR = (1<<ISC01); //INT0 по спаду
GIFR = (1<<INTF0); //очистка отложенных прерываний
GICR |= (1<<INT0); //разрешение INT0
}
//------------- Обработчик прерывания по сигналу фотоприемника: --------------
#pragma vector = INT0_vect
__interrupt void EdgeIR(void)
{
Port_LED_1;
GICR &= ~(1<<INT0); //запрещение INT0
TCNT0 = 256 - T_SAMPLE; //интервал до первой выборки
TIFR = (1<<TOV0); //очистка отложенных прерываний
TIMSK |= (1<<TOIE0); //разрешение прерываний таймера 0
SampCnt = SAMPLE_COUNT * 2; //общее количесто выборок
SampVal = 0; //очистка принятого значения
}
//------------------ Обработчик прерывания таймера 0: ------------------------
#pragma vector = TIMER0_OVF_vect
__interrupt void TimerIR(void)
{
if(SampCnt) //проверка таймаута
{
if(Pin_RC5) SampVal++; //если на входе единица, инкремент суммы,
else SampVal--; //иначе декремент суммы
if(--SampCnt) //декремент количества выборок
{
if(SampCnt != SAMPLE_COUNT)
{
TCNT0 = 256 - T_SAMPLE; //продолжаем опрашивать
return;
}
else //первая половина интервала закончилась:
{
TCNT0 = 256 - T_SAMPLE * 2; //загрузка интервала между сериями выборок
bool Val = (SampVal > 0); //оценка бита
if(Val != PreVal) //проверка корректности кода Манчестер
{
RC5Code <<= 1; //сдвиг принятого кода
if(!Val) RC5Code |= 1; //первая половина = 0, бит = 1
SampVal = 0; //очистка счетчика выборок
return;
}
}
}
else //вторая половина интервала закончилась:
{
TCNT0 = 256 - T_SAMPLE * 2; //загрузка интервала таймаута
PreVal = (SampVal > 0); //оценка второй половины бита
if(PreVal) //обнаружена единица,
MCUCR &= ~(1<<ISC00); //INT0 по спаду,
else MCUCR |= (1<<ISC00); //иначе INT0 по фронту
GICR |= (1<<INT0); //разрешение INT0
if(--BitCounter) //декремент счетчика битов
return; //переход к приему следующего бита
SysVar = (RC5Code >> 6) & 0x3F; //номер системы
ComVar = RC5Code & 0x3F; //код команды
if(!(RC5Code & 0x1000)) //добавление бита F
ComVar |= 0x40;
}
}
BitCounter = RC5_LENGTH; //загрузка счетчика битов
PreVal = 1; //перед стартовым битом была единица
TIMSK &= ~(1<<TOIE0); //запрещение прерываний таймера 0
MCUCR &= ~(1<<ISC00); //INT0 по спаду
GICR |= (1<<INT0); //разрешение INT0
Port_LED_0;
}
//------------------------- Чтение номера системы: ---------------------------
char RC5_GetSys(void)
{
return(SysVar);
}
//-------------------------- Чтение кода команды: ----------------------------
char RC5_GetCom(void)
{
return(ComVar);
}
//----------------------------------------------------------------------------
- pyzhman
- Друг Кота
- Сообщения: 7016
- Зарегистрирован: Вс июл 12, 2009 19:15:29
- Откуда: Ижевск
- Контактная информация:
Re: Алгоритм уверенного декодирования команд ИК пульта
Два типа протоколов:
1. Посылки кода команды передаются через определенный интервал.
2. Первая посылка содержит код команды, остальные - просто импульс, подверждающий факт удержания кнопки.
Второе: избитый RC5 от нажатия к нажатию инвертирует первый бит. Есл сдирать один в один, то каждые последующие нажатия будут восприниматься как другая команда.
Я делал так: в режиме программирования, то бишь запоминания посылки, снимал осциллограмму(все как предполагается). По максимуму забивая озу, предназанченное для этого. Вне зависимости от протокола(он может быть любой) отсекал первые ... перепады, так скажем. Таким образом приблуда RC5 отваливается. Потом все сохраняю в епром. После чтения посылки сравниваю с допуском в десять процентов, вернее +-пять процентов. Работает, кнопки от Philips, Samsung, LG не путает.
1. Посылки кода команды передаются через определенный интервал.
2. Первая посылка содержит код команды, остальные - просто импульс, подверждающий факт удержания кнопки.
Второе: избитый RC5 от нажатия к нажатию инвертирует первый бит. Есл сдирать один в один, то каждые последующие нажатия будут восприниматься как другая команда.
Я делал так: в режиме программирования, то бишь запоминания посылки, снимал осциллограмму(все как предполагается). По максимуму забивая озу, предназанченное для этого. Вне зависимости от протокола(он может быть любой) отсекал первые ... перепады, так скажем. Таким образом приблуда RC5 отваливается. Потом все сохраняю в епром. После чтения посылки сравниваю с допуском в десять процентов, вернее +-пять процентов. Работает, кнопки от Philips, Samsung, LG не путает.
Оптимизируем функционал.Контроллер сильно загружен
Подъемная-подъемная.неподъемная.
Docendo discimus
Re: Алгоритм уверенного декодирования команд ИК пульта
Допуск 10% - это процент совпадений?Вне зависимости от протокола(он может быть любой) отсекал первые ... перепады, так скажем. Таким образом приблуда RC5 отваливается. Потом все сохраняю в епром. После чтения посылки сравниваю с допуском в десять процентов. Работает, кнопки от Philips, Samsung, LG не путает.
Просто хранить весь дамп накладно, желательно из этого дампа получить (вычислить) код кнопки - достаточно 1 байта на хранение, остальное математика, которая может работать в фоновом режиме. Но тут проблема с этим допуском... хотя... есть мысля одна...
Мы лёгких путей не ищем!А ваша задача по-моему вообще неподъемная.
Я думаю подъёмная, но пошевелить мозгами придётся.
- pyzhman
- Друг Кота
- Сообщения: 7016
- Зарегистрирован: Вс июл 12, 2009 19:15:29
- Откуда: Ижевск
- Контактная информация:
Re: Алгоритм уверенного декодирования команд ИК пульта
Фига се, процент совпадений! Это допуск при сравнении полученной последовательности и записанной при программировании кнопки.
- Вложения
-
- posylka.JPG
- (28.85 КБ) 760 скачиваний
Docendo discimus
- Реклама
Re: Алгоритм уверенного декодирования команд ИК пульта
ааа, понятно...
pyzh_man, у вас двмп был в виде последовательности бит (...1111000111111111100011111...) или в виде последовательности длительностей импульсов?
pyzh_man, у вас двмп был в виде последовательности бит (...1111000111111111100011111...) или в виде последовательности длительностей импульсов?
- pyzhman
- Друг Кота
- Сообщения: 7016
- Зарегистрирован: Вс июл 12, 2009 19:15:29
- Откуда: Ижевск
- Контактная информация:
Re: Алгоритм уверенного декодирования команд ИК пульта
В виде времён. Ну относительных, конечно, величин.
Docendo discimus
Re: Алгоритм уверенного декодирования команд ИК пульта
Ясно, попробую реализовать на макетке.
- pyzhman
- Друг Кота
- Сообщения: 7016
- Зарегистрирован: Вс июл 12, 2009 19:15:29
- Откуда: Ижевск
- Контактная информация:
Re: Алгоритм уверенного декодирования команд ИК пульта
Что хочу сказать - мой алгоритм не претендует на истину в последней инстанции. Как задумалось, так написалось. Может у вас интереснее получится.
Docendo discimus
-
Мастер Ломастер
- Поставщик валерьянки для Кота
- Сообщения: 1995
- Зарегистрирован: Ср май 11, 2011 21:37:45
- Откуда: Цветочный город
- Контактная информация:
Re: Алгоритм уверенного декодирования команд ИК пульта
у ARV на сайте есть статья с подробным описанием метода реализации этого "неподъемного" алгоритма. правда, там все сделано на программных задержках, но изменить их на какие-то таймерные - не сложно, главное, сам принцип, который работает неплохо. если нужно - ищите статью на его сайте
битва с дураками проиграна, победители торжествуют. слава победителям!
Re: Алгоритм уверенного декодирования команд ИК пульта
Мастер Ломастер посмотрю, спасибо.
pyzh_man, практически получилось!
Частота на входе счетчика около 40 кГц. Настроено прерывание по спаду (значит по фронту сигнала, т.к. с tsop'а он инвертирован), между спадами идёт замер "времени".
Первые 16 значений откидываем, у остальных 48 (примерно) берём только старший бит (сдвигаем вправо несколько раз), т.к. длительности импульсов отличаются почти в два раза. И эти байты, значениями "0" и "1" пуляем в UART.
В итоге (в HEX-режиме) чётко видно "битовый" массив (в данном случае из байтов, равных 0 или 1).
Этот массив повторяется практически всегда, при нажатии одной и той же кнопки.
Сложив его в несколько байт получим образ кнопки. Проверял тремя пультами.
Этот вариант УЖЕ мне подходит, так как внутри прерывания получается не более 15 тактов по времени, всё остальное можно сделать по фону. Счетчик не останавливается и не сбрасывается, частота его годна для ШИМа, т.е. можно будет использовать любой занятый счетчик.
Но пока время есть, подумаю как еще оптимизировать, или еще какой алгоритм найду...
pyzh_man, практически получилось!
Частота на входе счетчика около 40 кГц. Настроено прерывание по спаду (значит по фронту сигнала, т.к. с tsop'а он инвертирован), между спадами идёт замер "времени".
Первые 16 значений откидываем, у остальных 48 (примерно) берём только старший бит (сдвигаем вправо несколько раз), т.к. длительности импульсов отличаются почти в два раза. И эти байты, значениями "0" и "1" пуляем в UART.
В итоге (в HEX-режиме) чётко видно "битовый" массив (в данном случае из байтов, равных 0 или 1).
Этот массив повторяется практически всегда, при нажатии одной и той же кнопки.
Сложив его в несколько байт получим образ кнопки. Проверял тремя пультами.
Этот вариант УЖЕ мне подходит, так как внутри прерывания получается не более 15 тактов по времени, всё остальное можно сделать по фону. Счетчик не останавливается и не сбрасывается, частота его годна для ШИМа, т.е. можно будет использовать любой занятый счетчик.
Но пока время есть, подумаю как еще оптимизировать, или еще какой алгоритм найду...
- pyzhman
- Друг Кота
- Сообщения: 7016
- Зарегистрирован: Вс июл 12, 2009 19:15:29
- Откуда: Ижевск
- Контактная информация:
Re: Алгоритм уверенного декодирования команд ИК пульта
Ну и темпы! Не успел подумать, уже готово.
Мне б такой заряд.
Docendo discimus
Re: Алгоритм уверенного декодирования команд ИК пульта
Да, но кажется обнаружился косяк - 48 импульсов маловато, нашел повторяющиеся кнопки. Или просто сам затупил среди ночи, сегодня проверю подробней 
Скидывать в буфер 96 (и более) байт уже некуда (макетирую на тини2313), а отправлять сразу же в уарт скорость последнего не позволяет (пойдут пропуски).
Ща перепишу код, чтобы он складывал 8 импульсов в один байт.
Ну и покурю статьи, пока на работе
Скидывать в буфер 96 (и более) байт уже некуда (макетирую на тини2313), а отправлять сразу же в уарт скорость последнего не позволяет (пойдут пропуски).
Ща перепишу код, чтобы он складывал 8 импульсов в один байт.
Ну и покурю статьи, пока на работе
- pyzhman
- Друг Кота
- Сообщения: 7016
- Зарегистрирован: Вс июл 12, 2009 19:15:29
- Откуда: Ижевск
- Контактная информация:
Re: Алгоритм уверенного декодирования команд ИК пульта
Насколько помню многовато. Скорее всего отсекается еще и нужная инфа, код команды урезается. Уточните минимум обрезка.Первые 16 значений откидываем
Docendo discimus
Re: Алгоритм уверенного декодирования команд ИК пульта
Вот похожий алгоритм, только прерывание настроено на любое изменение (фронт, спад).
http://we.easyelectronics.ru/Soft/prost ... ik-du.html
Будем экспериментировать
http://we.easyelectronics.ru/Soft/prost ... ik-du.html
Будем экспериментировать
Re: Алгоритм уверенного декодирования команд ИК пульта
Победил я его окончательно. Алгоритм такой:
1. Замеряем и выплёвываем длительность импульсов в UART
2. Медитируем над цифрами
3. Подбираем предделитель счетчика, чтобы длинный и короткий импульсы были как можно ближе к середине 8-битного диапазона. Например последовательность 0х05, 0х0A, 0х05 не годится. А вот 0х46, 0х8C, 0х46 - гораздо лучше
4. Вычисляем золотую середину между длинным и коротким импульсом. В случае с 0х46 и 0х8C это будет 0х69
5. Внутри прерывания из получившейся длительности вычитаем эту середину. Перевалило за ноль - единица, нет - ноль. Это дело и двигаем в 16-ти битный буфер.
6. Вводим константу - количество пропусков импульсов.
7. Вышеназванный буфер выплёвываем в UART, подбираем количество пропусков так, чтобы числа не повторялись с разными пультами. Тут уже легко чётко попасть на код кнопки.
8. Всё проверено? Можно выкидывать отладочную информацию, а буфер использовать как угодно - чтение/запись/обучение...
Работает чётко. Повесил 8 светодиодов на разные пульты (3 пульта) 3+3+2 кнопки. Давно я так не радовался светодиодам
По ресурсам - уложился в 25 тактов внутри прерывания, лучше некуда.
1. Замеряем и выплёвываем длительность импульсов в UART
2. Медитируем над цифрами
3. Подбираем предделитель счетчика, чтобы длинный и короткий импульсы были как можно ближе к середине 8-битного диапазона. Например последовательность 0х05, 0х0A, 0х05 не годится. А вот 0х46, 0х8C, 0х46 - гораздо лучше
4. Вычисляем золотую середину между длинным и коротким импульсом. В случае с 0х46 и 0х8C это будет 0х69
5. Внутри прерывания из получившейся длительности вычитаем эту середину. Перевалило за ноль - единица, нет - ноль. Это дело и двигаем в 16-ти битный буфер.
6. Вводим константу - количество пропусков импульсов.
7. Вышеназванный буфер выплёвываем в UART, подбираем количество пропусков так, чтобы числа не повторялись с разными пультами. Тут уже легко чётко попасть на код кнопки.
8. Всё проверено? Можно выкидывать отладочную информацию, а буфер использовать как угодно - чтение/запись/обучение...
Работает чётко. Повесил 8 светодиодов на разные пульты (3 пульта) 3+3+2 кнопки. Давно я так не радовался светодиодам
По ресурсам - уложился в 25 тактов внутри прерывания, лучше некуда.
- Леонид Иванович
- Друг Кота
- Сообщения: 4779
- Зарегистрирован: Сб апр 02, 2011 12:40:46
- Откуда: Минск
- Контактная информация:
Re: Алгоритм уверенного декодирования команд ИК пульта
ploop: Вы просто монстр! Поздравляю! А с пультами каких фирм пробовали?
Re: Алгоритм уверенного декодирования команд ИК пульта
Да какой монстр? Немного мозг пришлось напрячь, да и только. Думал, сложнее будет... Времени бы побольше...
Пульты: от телевизора SAMSUNG (стеклянный, с проским экраном), от спутникого ресивера Dreambox, и от звуковой карты SB Live (внешняя)
Пульты: от телевизора SAMSUNG (стеклянный, с проским экраном), от спутникого ресивера Dreambox, и от звуковой карты SB Live (внешняя)
- pyzhman
- Друг Кота
- Сообщения: 7016
- Зарегистрирован: Вс июл 12, 2009 19:15:29
- Откуда: Ижевск
- Контактная информация:
Re: Алгоритм уверенного декодирования команд ИК пульта
Однако... За двое суток... Не-е-е, не монстр. Годзилла!
Docendo discimus


