Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Алгоритм распознавания команд с любого ИК пульта
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Математика и Физика
TViT
Всем привет. Люди подскажите как с минимальными вычислениями реализовать распознавание, детектирование команд с любого пульта на МК.
Сейчас делаю так - использую ATtiny25 нога к которой подключен TSOP настроена как внешнее прерывание по спаду. После 2го спада начинает записывать в массив из 32х ячеек длину 1 и 0.
И потом соответственно ищем минимум это 0 максимум это 1. Пропускаем через алгоритм сравнения если больше минимума значит устанавливаем в конечной 32битной переменной соответствующий времени бит в 1 или соответствующий расположению от начала приема, если равно минимальной длительности то соответственно 0. Все работает. Но на пульте Philips с RC6 глючит по страшному. Он просто по иному работает. Переворачивает toggle бит если второй раз та же кнопка нажимается, плюет без остановки команды пока кнопку не отпустишь и т.д.

Помимо массива длительностей массив из 4х например 32бит переменных в которые в начале записываются команды, ну и потом с ними сравниваются поступающие в реальном времени команды с пульта для управления.

Так вот задача. Следить за длительностью любого импульса что 1 что 0 что паузы или переходов. Потом массив длительностей преобразовать к виду например мин ширина 1, больше в 1.5 или 2 раза минимальной ширины соответственно 2. И этот преобразованный массив к 1,2 (потому что ширина импульсов гуляет то например 10, то 12 или 36, 37) кинуть на что-то подобное CRC8 после чего у нас число в котором зашифрована команда и последовательность бит учтена. Что-то на подобии сжатия. С другой похожей не совпадет.

Ну потом естественно простое сравнение какая кнопка нажата... Посоветуйте, как сделать с минимальными вычислениями...
jcxz
У меня такой алгоритм:
Разбил работу на процесс захвата посылки и процедуру распознавания захваченных посылок.
Захват посылки:
Изначально процесс захвата посылки ищет тишину на линии не менее заданной, при её обнаружении переходит в состояние "ожидания первого перепада 0->1 или 1->0".
После первого перепада переходит в состояние "захват посылки". Выход из этого состояния - по обнаружении тишины на линии не менее T1 мсек.
После обнаружения каждого перепада кратковременно переходит в состояние "подавление дребезга" (просто пауза T2 мкс в течение которой состояние линии не анализируется - для ограничения загрузки CPU при ВЧ-помехах на линии). При обнаружении ошибочных состояний (например: превышение максимально допустимого числа перепадов в посылке; превышение общей длительности посылки; нарушение фазы (состояние покоя до посылки и после посылки - разное) и прочих), процесс захвата переходит в состояние "ожидание тишины на линии не менее времени T3" (T3 > T1; T3 - минимальный интервал тишины между двумя посылками ИК-приёмника).
Записываю в массив длительности нулей и единиц, начиная от первого перепада 0->1 или 1->0 (знаю что у TSOP состояние покоя - единица вроде, но просто на всякий случай сделал возможность работы на инверсном сигнале) и до обнаружения паузы пороговой длительности. С разрешением 1мкс (можно меньше, точности хватит).
Обнаружение заданной паузы T1 - конец посылки, после этого начинаю анализ посылки.
Анализ посылки:
Приёмник ИК-посылок у меня работает в одном из двух режимов - обучение или детектирование.
В режиме обучения каждая новая принятая посылка сравнивается с массивом имеющихся посылок и, если обнаружена похожая, эти посылки сливаются в одну суммарную посылку для которой длительности нулей и единиц рассчитываются как средние между первой и второй сливаемыми посылками.
После слияния посылок, анализирую весь остальной массив посылок на похожесть с новой посылкой и, если обнаружена похожая, суммирую эти посылки. И так далее, пока не проверен весь массив накопленных посылок на непохожесть. Это нужно, так как после прибавления к существующей посылке новой посылки, длительности её импульсов меняются и она может оказаться похожей на другую, на которую раньше была не похожа. У меня есть пороговый критерий "похожести".
В режиме детектирования, приёмник просто сравнивает новую посылку с массивом имеющихся и, если найдена похожая, выдаёт на выход код виртуальной кнопки назначенной готовой посылке, не сливая её с новой посылкой. Если не найдено похожей - посылка отбрасывается.
Алгоритм сравнения посылок на похожесть:
Я сравниваю не длительности 0 и 1, а длительности пар 0/1 и 1/0. Это гораздо более надёжный способ как показала практика на многих пультах.
Т.е. - процедура сравнения определяет если длительности всех пар 0/1 или длительности всех пар 1/0 двух разных посылок отклоняются не более чем на K друг от друга - посылки похожие. Сейчас у меня K == 5%.
Насчёт формата посылок от разных пультов, обнаружил два вида пультов:
1. Для каждой кнопки выдают определённую уникальную посылку, а при длительном удержании - генерят код автоповтора (общий для всех кнопок пульта).
2. Для каждой кнопки имеют две уникальных посылки, при длительном удержании нажатой кнопки повторяют одну посылку, при каждом новом нажатии - выдают другую посылку из пары.
Так что при обучении пульту, я задаю либо для каждой виртуальной кнопки одну посылку и один общий код автоповтора для всего пульта; или каждой кнопке назначаю 2 посылки (в этом случае кода автоповтора нет).
К тому-же - если у Вас 32 - это максимальное количество 0 и 1 в посылке - это слишком мало. Есть пульты, выдающие несколько десятков импульсов. У меня максимальное количество импульсов в посылке задано ==100 (встречал пульты выдающие около 60 импульсов на посылку, может есть и больше).
Описанный алгоритм у меня работает уже несколько лет, проверял с десятком разных пультов - нажатия детектирует почти 100%-но. Не детектируются только нажатия, на которые наложилась помеха.
ПО у меня может обучаться и хранить информацию сразу о кнопках нескольких разных пультов (сколько хватит памяти) и детектирует посылки сразу от всех пультов и имеющихся в базе. Эти пульты могут разных типов (тип1 или тип2). Так что наружу процесс детектирования выдаёт сообщение вида: пультM.кнопкаN.флаг_автоповтора(с длительностью).
И захватывать посылки надо не по прерыванию на ноге (слишком низкая точность, зависящая от загрузки CPU к тому же), а таймером, работающим в режиме захвата. Тогда разрешение можно поставить любое, хоть 1мкс, хоть меньше (хотя это уже избыточно имхо).
TViT
Я думаю ваш алгоритм сложен, у меня нет столько памяти, чтобы в несжатом виде хранить массивы длительностей. Массив у меня 65байт. Было 32байта ранее, работает кроме пультов от Филипса с RC6. Всего 128байт память и еще занято под программу ФИУ симистором, управлением освещением, плавным включением, яркостью различными режимами и блокировками поступающих команд и т.д. Это всего лишь одна опция моей системы, управление с пульта. Помимо управления кнопками и голосом.

На Филипсе 3 вида длительностей оказалось и разная длительность команд. Может 35 импульсов плюнуть, а может 39 и т.д. Зависит от команды. В остальном похоже с вашим описанием. Плюют постоянно при удержании. И новую команду при повторном нажатии. Но есть еще кнопки, которые 3 команда разом плюют и ожидают. Конечно тайминги и задержки у меня тоже есть, не принимать вторичную посылку. Все упирается в память.



Хотелось бы что-то попроще. Итак не успевает моргает свет при управлении с пульта пока обрабатывает прерывания и вычисляет команду, а управление симистором на это период упускает.
На сколько помню в ATtiny25 нет режима захвата по таймеру.
jcxz
Цитата(TViT @ Mar 24 2017, 12:08) *
Я думаю ваш алгоритм сложен, у меня нет столько памяти,
...
Это всего лишь одна опция моей системы, управление с пульта. Помимо управления кнопками и голосом.

Очевидно Вы неправильно выбрали элементную базу. Раз столько функций, зачем было на дохлом AVR делать?
Переделайте на Cortex-M.

Цитата(TViT @ Mar 24 2017, 12:08) *
На Филипсе 3 вида длительностей оказалось и разная длительность команд. Может 35 импульсов плюнуть, а может 39 и т.д.

Я описанным алгоритмом уже много лет пользуюсь. Несколько программ с ним написал.
Написал даже ПО под винду для визуализации и исследования посылок - вот с помощью него в своё время и выяснил многое про работу пультов.
И пультов 1-го и 2-го вида - полно, то что Вы нашли только один ни о чём не говорит. Я перепробовал десятки разных.
И были очень даже хитрые: например от какого-то потолочного кондишена на каждое новое нажатие менял длительность не одного импульса, а нескольких. Вот для того пульта даже моя программа детектирования работать не будет, так как у него более двух кодов на каждую кнопку (там в посылке похоже какой-то N-разрядный счётчик нажатий передавался, а может он ещё что-то передавал вместе с нажатием, так как пульт был навороченный, имел ЖК-индикатор). Но такой пульт встречал только раз.

Цитата(TViT @ Mar 24 2017, 12:08) *
Хотелось бы что-то попроще. Итак не успевает моргает свет при управлении с пульта пока обрабатывает прерывания и вычисляет команду, а управление симистором на это период упускает.

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

Цитата(TViT @ Mar 24 2017, 12:08) *
На сколько помню в ATtiny25 нет режима захвата по таймеру.

Так меняйте его на адекватный задаче.
TViT
Я пока зашифровал команды все работает. И уменьшил количество кнопок управления с 4х до одной. Т.е. 8байт хранят 4 зашифрованные команды информацию по сути 4х - 65байтовых массивов длительностей, но 4 вариации одной команды полюбому сработает. Не будет 4х функций будет одна на первое время. Тестирую пробую пока все нормально за исключением мерцаний... А в будущем будет видно что и как. Поскольку главное размер и цена моего устройства. Конечно это пробный блин немножко комом оказался...
jcxz
По цене самые простые Cortex-ы не уступают AVR-ам.
А по функционалу Вы уже в потолок упёрлись, уже приходится урезать функционал из-за нехватки ресурсов. Дальше будет хуже.
Какой смысл считать отдельные байты в наше время??
TViT
Я с вами согласен. Но это потом я все переведу на 32битные STM или Atmel. Пока AT32UC3L064 управляет распознаванием речи почти в реальном времени, а ATtiny25 всем остальным командами с пульта с кнопок, импульсами команд от голосового модуля.
Что есть то есть не выкидывать же деньги на ветер, послушался совета называется у разных профи... Что закупил нужно использовать. И платы разведены. Это не считая что Atmel кинула с ценой на AT32UC3L064. Которые пару лет назад стоили 122р... и наши бравые ребята наверху обвалив рубль...

Сами что посоветуете макс дешевое из эл базы. Для распознавания голоса нужно 64кБ флеш и 16кб ОЗУ. А отдельная ATtiny25 просто нужна для освещения. Планируется как полный комплект функций, так и отдельно только управление с пульта и кнопками. Поэтому 2е отдельные МС использовал...

И еще такой выбор был сделан из-за минимизации размеров и главное потребления, поскольку устройство работает сутками в реальном режиме, не отключаясь и не засыпая...
neiver
Я как-то вот такое делал: http://we.easyelectronics.ru/Soft/prostoy-...oder-ik-du.html
TViT
Цитата(neiver @ Mar 24 2017, 20:54) *
Я как-то вот такое делал: http://we.easyelectronics.ru/Soft/prostoy-...oder-ik-du.html


У меня примерно так же только частота 4МГц и еще проверка разных кнопок какая нажата с какой длительностью и что делать. Плюс детектор нуля сетевого напряжения на компараторе и программа генерации и управления импульсами через таймер для MOC и ФИУ симистором. Ну и программа хеширования массива 65байт длительностей импульсов на выходе уникальное 2байтовое число характеризующее нажатую кнопку. С другими кнопками на пульте не совпадает и на разных пультах тоже не совпадает. Только по переполнению таймера детектируется конец кодовой посылки. А значение длительности импульса записывается при новом изменении на входе при прерывании.
aiwa
Цитата(TViT @ Mar 24 2017, 12:08) *
Хотелось бы что-то попроще. Итак не успевает моргает свет при управлении с пульта пока обрабатывает прерывания и вычисляет команду, а управление симистором на это период

Попробуйте точнее замерить длительности, может так случиться, что длительности этих посылок кратны между собой.
~0.44 , ~0.88, ~ 1.2 , ~ 2.7 на самом деле это T, 2*T, 3*T и 6*T.

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

По перепаду запускать таймер с периодом 0.44 мс (или проще - 0.22 мс) в котором считывать очередной бит посылки.
Первый стартовый байт должен быть 0b000000 (~2,7 мc). окончание посылки характеризуется завершающим байтом 0b11111111 как начало 82 мс периода верхнего уровня.
Все что между ними - это команда. Нужно лишь составить список.
Если бывает 39 импульсов, то даже если они будут максимально широкими в 3 бита, то максимальный размер требуемого буфера 17 байт вместе с окантовкой.

TViT
Цитата(aiwa @ Mar 25 2017, 06:22) *
Попробуйте точнее замерить длительности, может так случиться, что длительности этих посылок кратны между собой.
~0.44 , ~0.88, ~ 1.2 , ~ 2.7 на самом деле это T, 2*T, 3*T и 6*T.

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

По перепаду запускать таймер с периодом 0.44 мс (или проще - 0.22 мс) в котором считывать очередной бит посылки.
Первый стартовый байт должен быть 0b000000 (~2,7 мc). окончание посылки характеризуется завершающим байтом 0b11111111 как начало 82 мс периода верхнего уровня.
Все что между ними - это команда. Нужно лишь составить список.
Если бывает 39 импульсов, то даже если они будут максимально широкими в 3 бита, то максимальный размер требуемого буфера 17 байт вместе с окантовкой.


Точно не получится. Когда 32байта массив был. Все работало на разных пультах кроме Филипса так - если ширина большая в 4х байтной переменной устанавливается соответствующий бит в 1 иначе 0. И на выходе 4х байтное число (32бита) - команда. Которых очень много можно записать в память - 16 кнопок управления если брать половину памяти в МК - 64байт.
Проверял на пультах от ЭЛТ телевизоров Rubin, JVC, Samsung, на новом TFT телеке LG и на пульте от звукового ресивера-усилителя Yamaha

А теперь при массиве в 65байт иначе.

Точно не измерить ширину импульса в моем случае (тактируется все от внутреннего RC генератора, плавать значения будут в массиве всегда и по другим причинам - от загрузки МК ведь он прерывает работу и обрабатывает еще кучу всего, прерывания от компаратора например постоянно поступают раз в 10мс, детектирует переходы через 0 сетевого напр, еще прерывания от первого таймера управляет шириной импульса для управления симистором - вкл\выкл освещения, запоминание состояний, команд, уровня яркости в eeprom и само управлением яркостью через генерирование в разные моменты управляющих импульсов в зависимости от начала полупериода сетевого напр).

Да мне точно и не нужно. Поскольку когда массив забивается, потом алгоритм нормирования все приводит к точным числам 1,2,3 --- соответственно 1-мин время импульса какое нашел в массиве, 2-среднее по длит время импульса какое было в массиве и 3-самое высокое время импульса которое было в массиве. А потом хеширование и на выходе уникальное число. Которых в мою память можно напихать кучу, соответственно и команд кучу можно запомнить.

В принципе я уже решил задачу. В моем случае этого для управления пока освещением более чем достаточно. А в будущем просто МК с большей памятью прикручу и все ))



Всем спасибо ))
jcxz
Цитата(aiwa @ Mar 25 2017, 05:22) *
Тогда самую маленькую длительность можно представить как бит, и тогда вся команда представима как несколько байт, что значительно сэкономит память.

Только это никак не соответствует теме треда: "распознавания команд с любого ИК пульта".
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.