Алгоритм уверенного декодирования команд ИК пульта

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Закрыто
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Алгоритм уверенного декодирования команд ИК пульта

Сообщение ploop »

Делаю устройство на ATmega48. Управляться оно должно обычного пульта ДУ от бытовой техники. В интернете нашел кучу реализаций разных алгоритмов декодирования сигнала, но все они не подходят по некоторым причинам. Проблемы такие:
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: Алгоритм уверенного декодирования команд ИК пульта

Сообщение pyzhman »

Два типа протоколов:
1. Посылки кода команды передаются через определенный интервал.
2. Первая посылка содержит код команды, остальные - просто импульс, подверждающий факт удержания кнопки.
Второе: избитый RC5 от нажатия к нажатию инвертирует первый бит. Есл сдирать один в один, то каждые последующие нажатия будут восприниматься как другая команда.
Я делал так: в режиме программирования, то бишь запоминания посылки, снимал осциллограмму(все как предполагается). По максимуму забивая озу, предназанченное для этого. Вне зависимости от протокола(он может быть любой) отсекал первые ... перепады, так скажем. Таким образом приблуда RC5 отваливается. Потом все сохраняю в епром. После чтения посылки сравниваю с допуском в десять процентов, вернее +-пять процентов. Работает, кнопки от Philips, Samsung, LG не путает.
Контроллер сильно загружен
Оптимизируем функционал.
неподъемная.
Подъемная-подъемная.
Docendo discimus
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Re: Алгоритм уверенного декодирования команд ИК пульта

Сообщение ploop »

Вне зависимости от протокола(он может быть любой) отсекал первые ... перепады, так скажем. Таким образом приблуда RC5 отваливается. Потом все сохраняю в епром. После чтения посылки сравниваю с допуском в десять процентов. Работает, кнопки от Philips, Samsung, LG не путает.
Допуск 10% - это процент совпадений?
Просто хранить весь дамп накладно, желательно из этого дампа получить (вычислить) код кнопки - достаточно 1 байта на хранение, остальное математика, которая может работать в фоновом режиме. Но тут проблема с этим допуском... хотя... есть мысля одна...
А ваша задача по-моему вообще неподъемная.
Мы лёгких путей не ищем! :)
Я думаю подъёмная, но пошевелить мозгами придётся.
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
pyzhman
Друг Кота
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск
Контактная информация:

Re: Алгоритм уверенного декодирования команд ИК пульта

Сообщение pyzhman »

Фига се, процент совпадений! Это допуск при сравнении полученной последовательности и записанной при программировании кнопки.
Вложения
posylka.JPG
(28.85 КБ) 760 скачиваний
Docendo discimus
Реклама
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Re: Алгоритм уверенного декодирования команд ИК пульта

Сообщение ploop »

ааа, понятно...

pyzh_man, у вас двмп был в виде последовательности бит (...1111000111111111100011111...) или в виде последовательности длительностей импульсов?
Реклама
Аватара пользователя
pyzhman
Друг Кота
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск
Контактная информация:

Re: Алгоритм уверенного декодирования команд ИК пульта

Сообщение pyzhman »

В виде времён. Ну относительных, конечно, величин.
Docendo discimus
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Re: Алгоритм уверенного декодирования команд ИК пульта

Сообщение ploop »

Ясно, попробую реализовать на макетке.
Аватара пользователя
pyzhman
Друг Кота
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск
Контактная информация:

Re: Алгоритм уверенного декодирования команд ИК пульта

Сообщение pyzhman »

Что хочу сказать - мой алгоритм не претендует на истину в последней инстанции. Как задумалось, так написалось. Может у вас интереснее получится.
Docendo discimus
Мастер Ломастер
Поставщик валерьянки для Кота
Сообщения: 1995
Зарегистрирован: Ср май 11, 2011 21:37:45
Откуда: Цветочный город
Контактная информация:

Re: Алгоритм уверенного декодирования команд ИК пульта

Сообщение Мастер Ломастер »

у ARV на сайте есть статья с подробным описанием метода реализации этого "неподъемного" алгоритма. правда, там все сделано на программных задержках, но изменить их на какие-то таймерные - не сложно, главное, сам принцип, который работает неплохо. если нужно - ищите статью на его сайте
битва с дураками проиграна, победители торжествуют. слава победителям!
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Re: Алгоритм уверенного декодирования команд ИК пульта

Сообщение ploop »

Мастер Ломастер посмотрю, спасибо.

pyzh_man, практически получилось!
Частота на входе счетчика около 40 кГц. Настроено прерывание по спаду (значит по фронту сигнала, т.к. с tsop'а он инвертирован), между спадами идёт замер "времени".
Первые 16 значений откидываем, у остальных 48 (примерно) берём только старший бит (сдвигаем вправо несколько раз), т.к. длительности импульсов отличаются почти в два раза. И эти байты, значениями "0" и "1" пуляем в UART.

В итоге (в HEX-режиме) чётко видно "битовый" массив (в данном случае из байтов, равных 0 или 1).
Этот массив повторяется практически всегда, при нажатии одной и той же кнопки.
Сложив его в несколько байт получим образ кнопки. Проверял тремя пультами.

Этот вариант УЖЕ мне подходит, так как внутри прерывания получается не более 15 тактов по времени, всё остальное можно сделать по фону. Счетчик не останавливается и не сбрасывается, частота его годна для ШИМа, т.е. можно будет использовать любой занятый счетчик.

Но пока время есть, подумаю как еще оптимизировать, или еще какой алгоритм найду...
Аватара пользователя
pyzhman
Друг Кота
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск
Контактная информация:

Re: Алгоритм уверенного декодирования команд ИК пульта

Сообщение pyzhman »

Ну и темпы! Не успел подумать, уже готово. :write: Мне б такой заряд.
Docendo discimus
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Re: Алгоритм уверенного декодирования команд ИК пульта

Сообщение ploop »

Да, но кажется обнаружился косяк - 48 импульсов маловато, нашел повторяющиеся кнопки. Или просто сам затупил среди ночи, сегодня проверю подробней :)

Скидывать в буфер 96 (и более) байт уже некуда (макетирую на тини2313), а отправлять сразу же в уарт скорость последнего не позволяет (пойдут пропуски).
Ща перепишу код, чтобы он складывал 8 импульсов в один байт.

Ну и покурю статьи, пока на работе :)
Аватара пользователя
pyzhman
Друг Кота
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск
Контактная информация:

Re: Алгоритм уверенного декодирования команд ИК пульта

Сообщение pyzhman »

Первые 16 значений откидываем
Насколько помню многовато. Скорее всего отсекается еще и нужная инфа, код команды урезается. Уточните минимум обрезка.
Docendo discimus
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Re: Алгоритм уверенного декодирования команд ИК пульта

Сообщение ploop »

Вот похожий алгоритм, только прерывание настроено на любое изменение (фронт, спад).
http://we.easyelectronics.ru/Soft/prost ... ik-du.html

Будем экспериментировать :)
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Re: Алгоритм уверенного декодирования команд ИК пульта

Сообщение ploop »

Победил я его окончательно. Алгоритм такой:
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: Вы просто монстр! Поздравляю! А с пультами каких фирм пробовали?
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Re: Алгоритм уверенного декодирования команд ИК пульта

Сообщение ploop »

Да какой монстр? Немного мозг пришлось напрячь, да и только. Думал, сложнее будет... Времени бы побольше...

Пульты: от телевизора SAMSUNG (стеклянный, с проским экраном), от спутникого ресивера Dreambox, и от звуковой карты SB Live (внешняя)
Аватара пользователя
pyzhman
Друг Кота
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск
Контактная информация:

Re: Алгоритм уверенного декодирования команд ИК пульта

Сообщение pyzhman »

Однако... За двое суток... Не-е-е, не монстр. Годзилла!
Docendo discimus
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»