Протокол управления электрокарнизами Akko по радиоканалу.
Радиопульт AC316D — симпатичное устройство, которое выглядит как настенный выключатель. Крепится на стену. Проводку подводить не надо - работает от батарейки CR2430. По заверению производителя, радиопульт, при стандартном режиме эксплуатации, способен на одной батарейке проработать три года.
Сначала фотки.
AC316D
Батарейка
Крепёж
Инструкция
Рамка
AC316D
Батарейка устанавливается с обратной стороны
Плата со стороны батарейки.
Место под CR2430
Передатчик 433 МГц
Кроме самой батарейки на этой стороне платы расположен передатчик на 433МГц. Передатчик самый простой, в буквальном смысле на одном транзисторе. Используется амплитудная двоичная модуляция (Amplitude shift keying). Частота задаётся резонатором ПАВ.
Резонатор ПАВ 433 МГц
Spy-bi-wire
Место под разъём для программирования и отладки.
Плата со стороны микроконтроллера.
MSP430G2201
Spy-bi-wire
Место под разъём для программирования и отладки.
Транзистор, управляющий светодиодами
У меня получилась вот такая схема этого устройства (сделал в KiCad и вставил картинкой):
Радиопульт выполнен на микроконтроллере MSP430G2201. Кварца нет — МК тактируется внутренним генератором. Интерфейс для программирования и отладки spy-bi-wire выведен на разъём. Возможно, прошивку с МК можно считать, но у меня нет программатора для MSP430, поэтому изучать протокол будем по сигналам с ножек МК. В целом, причины выбора элементной базы понятны. MSP430 очень экономичны в плане энергопотребления.
Подключим осциллограф к ножке 12 МК. Будем нажимать кнопки и наблюдать за сигналом, который отправляется на передатчик. Пример того, что можно наблюдать при нажатии на одну из кнопок `||`(Стоп) можно посмотреть здесь:
Видим, что сигнал состоит минимум из трёх пакетов. Пакеты абсолютно одинаковые. Предполагаем, что пакетом кодируется команда, которая передаётся минимум три раза. Пакет целиком выглядит так:
Для нас здесь важно, что можно выделить начало сигнала. Назовём его стартовым битом. Имеет ширину 4,864 мс. Затем видим последовательность высоких и низких уровней в количестве 40 штук. Можем предположить, что это 40 бит или 5 байт команды. Длится всё ровнёхонько 50 мс. Т.о. мы не сможем передавать больше 20 команд в секунду.
Каждый пакет начинается с сигнала, который имеет такой вид:
Это стартовый бит. Сделан достаточно большим, чтобы устройство на стороне приёмника детектировало начало передачи и успело выйти из спячки. Если округлить в сторону уменьшения временные интервалы (делается, чтобы убрать лишние задержки, связанные, с реализацией в МК), то получим, что длительность высокого уровня стартового бита — 4,8 мс, низкого — 1,5 мс. Если сложим вместе, то получим длительность — 6,3 мс.
Рассматривая последовательность дальше, замечаем, что период сигнала всегда одинаковый. Примерно 1080 мс. А вот длительности сигналов высокого и низкого уровней разные, но принимают только два значения — 720 мкс и 360 мкс. Я немного округлил значения в меньшую сторону. Если за базу взять длительность 360 мкс, то период составит три таких интервала. Сигнал всегда начинается с высокого уровня, а переход из высокого в низкий происходит либо через 360 мкс, либо через 720 мкс. Нет большой разницы какой из двух сигналов считать «0», а какой «1», но для просторы дальнейшего понимания будем считать «1» вот такой сигнал (выделен двумя вертикальными линиями):
Если считывать значение сигнала с периодом 1080 мкс, то по перепаду в середине периода получим значение бита (0 или 1).
Сигнал «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.
: 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 ;
Как видим, наши предположения подтвердились и всё работает. Четыре команды по радиоканалу — это не весь протокол, есть ещё команды. Если появится желание поэкспериментировать - можете продолжить. Замечу ещё, что в ходе экспериментов было замечено, что, если вместо последней цифры в адресе будет «0» (например 0x18 0x60 0x87 0xb0, вместо 0x18 0x60 0x87 0xb2), команду выполнят все моторы, к которым привязаны радиопульты, с адресами 0x18 0x60 0x87 0xbx. Другими словами, адрес в радиопротоколе состоит из двух частей: самого адреса 28 бит и 4 бита — канал. Т.о. моторы можно объединять в группы и управлять всей группой сразу.