Поки робота над проектом Управління будь-яким ІК-пультом не закінчена, я вирішив виділити деякі рішення в окремі замітки (під проекти), тим більше, що частина з них вже не буде включена в проект.
Сьогодні я розповім про алгоритм обробки ІЧ-посилок. (Раніше я вже описував один з можливих варіантів декодування ІК-посилок Працюємо з ІК пультом).
ІК-приймач я буду використовувати найдешевший і здатний працювати при низькій напрузі харчування (від 2,5 до 5,5 В) TSOP31236 (26 рублів):
Використовувати можна на будь-яку з налагоджувальних плат STM8 / STM32 серії Discovery.
Форматів посилок (протоколів) формуються ІК-пультами різної побутової апаратури дуже багато.
Основні відмінності протоколів:
- відмінності в кодуванні "0" і "1"
- різні довжини посилок
- відмінності в командах автоповтора
Наприклад ось такі сигнали генерує один з моїх пультів (як записати сигналів читаємо тут Запис сигналів IR-пульта на звукову карту):
Найбільше формат посилок схожий на Extended NEC protocol:
Я склав таблицю для порівняння протоколів (звичайно вона не повна, тут тільки, що я знайшов):
Як бачимо написати програму здатну декодувати всі протоколи досить складно, надто вже велика різниця між ними.
Особливо, якщо ще врахувати, що і кількість тривалостей імпульсів (як для кодування імпульсів синхронізації, так і кодуванні "0" і "1") значно більше двох.
Однак, для поточного завдання (управління) необхідно просто "приймати" і однозначно ідентифікувати посилки з будь-якого пульта, це дозволяє дуже сильно спростити алгоритм обробки.
Два ключові моменти в алгоритмі:
Використовувати відносне кодування, т. Е. Порівнюючи тривалості попереднього і поточного прийнятого імпульсу виноситься рішення про кодування поточного імпульсу як «0» або «1». Якщо поточний імпульс коротше або довше попереднього, то кодируем поточний імпульс як «1», інакше як «0».
Примітка: Імпульс - часовий відрізок між однаковими фронтами вихідних сигналів ІК-приймача.
Була прийнята наступна послідовність імпульсів.
1) Перше значення посилки використовується тільки для порівняння і не збережуться;
2) Друге значення менше першого, отже маємо перший біт рівний «1»;
3) Третє значення менше другого, отже другий біт дорівнює «1»;
4) Четверте значення дорівнює третьому, отже третій біт дорівнює «0»;
Після обробки отримуємо наступну двійкову послідовність «110101».
У отриманої послідовності відсікати зліва N-біт (я вибрав три біта, в них потрапляє преамбула і біт повтору) і якщо кількість прийнятих біт більше 64, то використовувати тільки останні 64 біта. Отриману послідовність для економії пам'яті "утискувати" до двох байт використовуючи циклічний надлишковий код (CRC16) (хеш-код).
Алгоритм обробки (декодування) посилок з ІК-приймача
Для декодування посилок ІК-приймача використовується один таймер.
Таймер повинен мати канал захоплення з зовнішньої лінії введення-виведення.
Діаграма сигналів для пояснення роботи:
Примітка до малюнка:
1) Лічильник веде рахунок в бік збільшення значень рахункового регістра. 2) По приходу спадаючого фронту (можна змінити на наростаючий, якщо вихідний сигнал з ІК-приймача НЕ інверсний, хоча в цілому вважаю, що напрямок захоплення не впливає на роботу алгоритму) відбувається захоплення значення рахункового регістра таймера і генерується відповідне переривання. 2.1) У обробнику переривань зчитується захоплене значення і скидається лічильник. 2.2) Отримані тривалості імпульсів (в тиках таймера) діляться на дві групи: імпульси коротше 10 мс, вважаються інформаційними (т. Е. Містять інформацію про код клавіші), а імпульси які довше 10 мс або рівні нулю, приймаються за роздільники посилок (т . е. позначають початок посилки). 3) Якщо протягом 20 мс не був прийнятий спадаючий фронт вихідного сигналу з ІК-приймача, то формується переривання в порівнянні (другий канал таймера). Дана подія використовується для фіксації моменту закінчення прийому посилки.
Алгоритм був випробуваний на мікроконтролері STM8S003F3, таймери у нього найпростіші, що однозначно дозволить реалізувати даний алгоритм на інших мікроконтролерах STM8 / STM32.
Налаштування таймера (використовується стандартна бібліотека периферії від ST):
Мікроконтролер тактується від вбудованого RC-генератора на 16 МГц.
Оброблювач (захоплення і переповнення):
Отримання послідовності з вхідних імпульсів:
Закінчення прийому посилки (з таймаут) і отримання хеш-коду посилки ( "стиснення"):
Прийом посилок і формування подій.
На мій погляд обробка прийнятих посилок займає значно більше часу, ніж сам прийом (декодування), що може вплинути на прийом посилок (пропуск, помилки і п.р.).
У зв'язку з чим, код обробки «винесено» з декодера посилок, в інший обробник, виклик якого відбувається через кожні 10 мс.
Спробую пояснити як це працює (тимчасової масштаб не дотримано):
Найпростіший варіант, коли обробляється тільки одна посилка.
Після прийому встановлюється прапор закінчення прийому посилки (ir_decoder.is_received).
У обробнику посилок перевіряється (і скидається) прапор закінчення прийому посилки, якщо він встановлений зчитується код посилки. Лічені код посилки перевіряється з «відомими», в разі збігу генерується (обробляється) подія «кнопка натиснута».
Після 130 мс (тепер відраховується в самому обробнику) генерується (обробляється) подія «кнопка відтиснуті».
Варіант по складніше, коли обробляється дві різні посилки.
Після прийому першої встановлюється прапор закінчення прийому посилки «А».
У обробнику посилок перевіряється прапор і зчитується код посилки, якщо він підтримується, то генерується (обробляється) подія «кнопка натиснута» «А».
Друга посилка приходить до завершення періоду в 130 мс, завдяки «незалежної» обробці вона коректно приймається і коректно відпрацьовуються всі події для посилки «А», а саме: подія «кнопка натиснута» «Б» і подія «кнопка відтиснуті» «А».
Після 130 мс (тепер відраховується в самому обробнику) генерується (обробляється) подія «кнопка відтиснуті» «Б».
Код самого обробника не наводжу.
На цьому поки все.