Реверс-инжиниринг радиопульта AC316D.

Протокол управления электрокарнизами Akko по радиоканалу.

        Радиопульт AC316D — симпатичное устройство, которое выглядит как настенный выключатель. Крепится на стену. Проводку подводить не надо - работает от батарейки CR2430. По заверению производителя, радиопульт, при стандартном режиме эксплуатации, способен на одной батарейке проработать три года.

Сначала фотки.

AC316D

Батарейка

Крепёж

Инструкция

Control System specification Akko

Рамка

AC316D

Настенный радиовыключатель

Батарейка устанавливается с обратной стороны

Настенный радиовыключатель

Плата со стороны батарейки.

Место под CR2430

Передатчик 433 МГц

Кроме самой батарейки на этой стороне платы расположен передатчик на 433МГц. Передатчик самый простой, в буквальном смысле на одном транзисторе. Используется амплитудная двоичная модуляция (Amplitude shift keying). Частота задаётся резонатором ПАВ.

Резонатор ПАВ 433 МГц

Spy-bi-wire

Место под разъём для программирования и отладки.

Настенный радиовыключатель без крышки

Плата со стороны микроконтроллера.

MSP430G2201

Spy-bi-wire

Место под разъём для программирования и отладки.

Транзистор, управляющий светодиодами

Настенный радиовыключатель схема

У меня получилась вот такая схема этого устройства (сделал в KiCad и вставил картинкой):

schematic

        Радиопульт выполнен на микроконтроллере MSP430G2201. Кварца нет — МК тактируется внутренним генератором. Интерфейс для программирования и отладки spy-bi-wire выведен на разъём. Возможно, прошивку с МК можно считать, но у меня нет программатора для MSP430, поэтому изучать протокол будем по сигналам с ножек МК. В целом, причины выбора элементной базы понятны. MSP430 очень экономичны в плане энергопотребления.

        Подключим осциллограф к ножке 12 МК. Будем нажимать кнопки и наблюдать за сигналом, который отправляется на передатчик. Пример того, что можно наблюдать при нажатии на одну из кнопок `||` (Стоп) можно посмотреть здесь:

 

        Видим, что сигнал состоит минимум из трёх пакетов. Пакеты абсолютно одинаковые. Предполагаем, что пакетом кодируется команда, которая передаётся минимум три раза. Пакет целиком выглядит так:

all_command

       Для нас здесь важно, что можно выделить начало сигнала. Назовём его стартовым битом. Имеет ширину 4,864 мс. Затем видим последовательность высоких и низких уровней в количестве 40 штук. Можем предположить, что это 40 бит или 5 байт команды. Длится всё ровнёхонько 50 мс. Т.о. мы не сможем передавать больше 20 команд в секунду.

        Каждый пакет начинается с сигнала, который имеет такой вид:

start_bit

        Это стартовый бит. Сделан достаточно большим, чтобы устройство на стороне приёмника детектировало начало передачи и успело выйти из спячки. Если округлить в сторону уменьшения временные интервалы (делается, чтобы убрать лишние задержки, связанные, с реализацией в МК), то получим, что длительность высокого уровня стартового бита — 4,8 мс, низкого — 1,5 мс. Если сложим вместе, то получим длительность — 6,3 мс.

        Рассматривая последовательность дальше, замечаем, что период сигнала всегда одинаковый. Примерно 1080 мс. А вот длительности сигналов высокого и низкого уровней разные, но принимают только два значения — 720 мкс и 360 мкс. Я немного округлил значения в меньшую сторону. Если за базу взять длительность 360 мкс, то период составит три таких интервала. Сигнал всегда начинается с высокого уровня, а переход из высокого в низкий происходит либо через 360 мкс, либо через 720 мкс. Нет большой разницы какой из двух сигналов считать «0», а какой «1», но для просторы дальнейшего понимания будем считать «1» вот такой сигнал (выделен двумя вертикальными линиями):

bit_1

        Если считывать значение сигнала с периодом 1080 мкс, то по перепаду в середине периода получим значение бита (0 или 1).

        Сигнал «0» выглядит так:

bit_0

        Теперь переведём наши 40 бит в байты. Сигнал слишком длинный и при его увеличении не помещается на экране. Чтобы с ним разобраться придётся ещё раз посмотреть видео, останавливая его время от времени и переводя сигнал в его значения.

        У меня получилась такая последовательность: 0x18 0x40 0x85 0xb2 0x55.

        Нажимая в этой же вертикали кнопки `>|<` (Закрыть) и `<|>`(Открыть) я получил значения 0x18 0x40 0x85 0xb2 0x33 и 0x18 0x40 0x85 0xb2 0x11. Видно, что последовательность отличается только последним байтом. Нажимая кнопки `>|<`, `||`, `<|>` в другой вертикали (это другой канал радиопульта), замечаем, что первые четыре байта другие (0x18 0x40 0x85 0xb1), но для каждой кнопки в ряду одни и те же. А последний байт совпадает с байтами из другого ряда, т. е. 0x33, 0x55 и 0x11 соответственно. Можно предположить, что первые четыре байта — это адрес устройства, а вслед за адресом передаётся команда. Ещё удалось узнать, что команда «Установка», которая используется для привязки радиопульта к электрокарнизу (чтобы пульт передал эту команду надо нажать одновременно кнопки`||`, `<|>`), имеет код 0xcc.

        Настало время проверить наши предположения. Создадим устройство и с помощью его будем отправлять команды электрокарнизу. Проверим, будет ли электрокарниз нас понимать.

        Для тестирования я взял плату с микроконтроллером STM32F103 - «blue pill», залил туда прошивку с Mecrisp-Stellaris Forth. Получил возможность прямо с компьютера, через консоль, управлять микроконтроллером. Мне это показалось очень удобным. Никакой специальной среды разработки. Можно писать программы в том редакторе, который нравится. Просто ты, твой код и терминал — больше ничего. Для автоматизации, особенно домашней — очень классный подход. Да, нужен ещё передатчик, на 433 МГц. У меня нашелся STX882.

        Подключил всё вот так:

Схема

Код программы на Forth

\ bit-banged Akko radio protocol driver

[ifndef] RF_OUT PC14 constant RF_OUT [then]

$184085b1 constant RF_ADDR
$11 constant UP_CMD
$33 constant DOWN_CMD
$55 constant STOP_CMD
$cc constant SETTING_CMD

: rf_start ( -- ) \ set RF_OUT high to 4.8ms, change RF_OUT from 1 to 0, wait 1.5ms
RF_OUT ios! 4800 us RF_OUT ioc! 1500 us ;
: rf_0 ( -- ) \ set RF_OUT high to 720us, change RF_OUT from 1 to 0, wait 360us
RF_OUT ios! 360 us RF_OUT ioc! 720 us ;
: rf_1 ( -- ) \ set RF_OUT high to 360us, change RF_OUT from 1 to 0, wait 720us
RF_OUT ios! 720 us RF_OUT ioc! 360 us ;
: b>rf ( f -- ) \ send one rf bit
0= if rf_0 else rf_1 then ;
: addr>rf ( n -- ) \ send address
32 0 do dup $80000000 and b>rf shl loop drop ;
: b>rf ( b -- ) \ send command (one byte)
8 0 do dup $80 and b>rf shl loop drop ;
: cmd>rf ( b -- ) \ send start_bit + address + command
rf_start RF_ADDR addr>rf b>rf ;

: up ( b -- ) \ send command UP
UP_CMD cmd>rf ;

: down ( b -- ) \ send command DOWN
DOWN_CMD cmd>rf ;

: stop ( b -- ) \ send command STOP
STOP_CMD cmd>rf ;

: setting ( b -- ) \ send command SETTING
SETTING_CMD cmd>rf ;

OMODE-PP RF_OUT io-mode!

        Что в итоге получилось можно посмотреть здесь:

        Как видим, наши предположения подтвердились и всё работает. Четыре команды по радиоканалу — это не весь протокол, есть ещё команды. Если появится желание поэкспериментировать - можете продолжить. Замечу ещё, что в ходе экспериментов было замечено, что, если вместо последней цифры в адресе будет «0» (например 0x18 0x60 0x87 0xb0, вместо 0x18 0x60 0x87 0xb2), команду выполнят все моторы, к которым привязаны радиопульты, с адресами 0x18 0x60 0x87 0xbx. Другими словами, адрес в радиопротоколе состоит из двух частей: самого адреса 28 бит и 4 бита — канал. Т.о. моторы можно объединять в группы и управлять всей группой сразу.

Графическое представление радиопротокола Akko.

image/svg+xml стартовыйбит адрес канал команда 28 бит 4 бита 8 бит 40 бит стартовый бит 4,8 мс 1,5 мс 360 мкс 720 мкс 360 мкс 720 мкс 6,3 мс 1080 мкс 1080 мкс "0" "1"
Команда
Код
Открыть
0x11
Закрыть
0x33
Стоп
0x55
Установка
0xсс

Разработчик протокола компания Ningbo Dooya Mechanic & Electronic Technology Co. Ltd

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

ВВЕРХ
preloader