Эмуляция ведомых 1-wire устройств на MSP430

64515fdaaba646bd93d4e127010d6fd6.pngКак-то раз я купил на eBay диммер для светодиодной ленты с ИК-пультом управления. Помимо того, факта, что через пару часов использования умер выходной MOSFET и его пришлось менять, со временем обнаружились следующие проблемы: Слишком низкая частота ШИМ. При низкой яркости мигание было видно невооруженным глазом. Наверное, это связано с параметрами работы выходного транзистора — если, например, время включения/выключения слишком большое, то частоту ШИМ повышать нельзя. Отсутствие каких-либо возможностей для коммуникации, кроме ИК-пульта. На плате обнаружилось много разных дополнительных разъемов (питание +5V, выход ШИМ и еще какие-то), но никакого другого интерфейса управления. Что, впрочем, логично. Иногда такие недостатки можно устранить доработкой прошивки, но на микроконтроллере была стерта маркировка, и ничего похожего в таком корпусе я на Digikey/Mouser не нашел. Было решено реализовать аналогичную схему, лишенную указанных недостатков. Из интерфейсов управления рядом оказался 1-wire. Так появилась библиотека для эмуляции slave-устройств, совместимых с 1-wire.

Протокол работы1-wire — двунаправленная шина связи. Устройства используют выход с открытым коллектором для изменения состояния линии данных, которая подтянута к +5V. Кодирование информации осуществляется с помощью времени, на которое устройство притягивает линию данных к 0. Более подробно о шине можно прочитать здесь.

Реализация на базе микроконтроллера MSP430G2553 Основная проблема — микроконтроллер питается от напряжения 3.3V максимум, на такое же напряжение рассчитаны порты GPIO. Для того, чтобы подключиться к линии данных, можно использовать два пина: один как вход (с подключением через резистивный делитель), второй — как выход (с использованием транзистора для соединения линии с землей). Ориентировочная схема представлена на рисунке ниже.

958817c069cf4f2c930af856d48d2d72.png

Линейный стабилизатор нужен, если планируется питать МК от 1-wire линии.

Код Созданная библиотека состоит из двух частей:

Код, обрабатывающий передачу отдельных бит (таймслотов), байтов, сигнала сброса и работающий с командами SEARCH и MATCH Код, отвечающий за какое-либо конкретное устройство. Эта часть обрабатывает доступ к регистровому пространству Зачем это сделано? Во-первых, для того, чтобы можно было легко перейти от одного устройства к другому. Во-вторых, у библиотеки есть возможность эмуляции нескольких устройств с разными адресами на одном микроконтроллере. Это возможно благодаря алгоритму поиска устройств на шине: микроконтроллер отвечает сразу за несколько адресов. Каждое такое виртуальное устройство отвечает за собственную часть периферии микроконтроллера.

Чтобы полученное устройство было совместимо с существующими решениями, был написан код для эмуляции микросхемы, частично совместимой с DS2408, которую по каким-то причинам перестали выпускать. Это позволяет использовать устройство вместе с owserver и owhttpd. В случае с диммером байт, отвечающий за состояние выходов микросхемы, задает скважность ШИМ-выхода.

Инициализировать библиотеку можно довольно просто:

#include #include

#include «one-slave.h» #include «one-2408.h»

// Массив с описаниями устройств static one_device devices[] = { { // (ROM-адрес) | (Family code) .rom = 0×0011223344556600 | ONE_2408_FC, // Функция инициализации предоставляется конкретным устройством .init = &one_2408_init, // Параметры устройства: в данном случае указатель на область регистров, // отвечающих за PORT1 в микроконтроллере .device = &(one_2408) { .port_base = &P1IN } }, { .rom = 0×00AA000000000100 | ONE_2408_PWM_FC, .init = &one_2408_pwm_init, // PWM-выход: P2.1 .device = &(one_2408_pwm) { .out_bit = BIT1, .port_base = &P2IN } } };

void main (void) { WDTCTL = WDTPW | WDTHOLD; one_init ( (one_device *) &devices, ARRAY_SIZE (devices) ); _EINT (); while (1) { one_process_state (); } } Железо Вместо существующей платы была создана другая:

1b601b18381844f88637e917bd5530db.png

В реальности плата выглядит хуже, потому что нашлось несколько огрехов, которые нужно было исправить. Использовать переменный резистор для ручной регулировки, к сожалению, не получилось — не хватило таймеров, из двух два были заняты. Создавать на основе аппаратного таймера много «программных» в данном случае нельзя, так как на линии все происходит довольно быстро (для МК) и код обработки прерывания таймера может испортить какой-нибудь таймслот длиной в 30 мкс.

В новой плате частота PWM составляет 15 кГц, увидеть мерцание глазами и камерой не получилось.

Подключение к Openhab Подключение к Openhab осуществляется довольно просто — с использованием биндинга HTTP. Для изменения яркости достаточно отправить запрос к owhttpd следующего вида:

http://owhttpd:2121/29.0100000000AA/PIO.BYTE/? PIO.BYTE=VALUE VALUE — значение от 0 до 255.

На телефоне это выглядит так:

bee971b074f243bfbfd4b2bb466868be.png

Пульт управления тоже работать не перестал, он теперь работает через LIRC, который передает коды клавиш в Openhab. Благодаря Openhab при нажатии кнопок на пульте сразу изменяется состояние элементов управления на телефоне.

Заключение В заключение перечислю еще раз основные особенности библиотеки:

Работа на прерываниях, в промежутках между транзакциями микроконтроллер находится в режиме низкого энергопотребления Возможность эмуляции нескольких устройств на одном микроконтроллере Работа проверялась на MSP430G2553, теоретически, на других контроллерах этой серии тоже заработает Исходники можно найти здесь: github.com/resetnow/one-slave

© Habrahabr.ru