...

суббота, 13 июня 2015 г.

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


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

Иногда такие недостатки можно устранить доработкой прошивки, но на микроконтроллере была стерта маркировка, и ничего похожего в таком корпусе я на Digikey/Mouser не нашел. Было решено реализовать аналогичную схему, лишенную указанных недостатков. Из интерфейсов управления рядом оказался 1-wire. Так появилась библиотека для эмуляции slave-устройств, совместимых с 1-wire.

Протокол работы

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

Реализация на базе микроконтроллера MSP430G2553

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

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

Код

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

  1. Код, обрабатывающий передачу отдельных бит (таймслотов), байтов, сигнала сброса и работающий с командами SEARCH и MATCH
  2. Код, отвечающий за какое-либо конкретное устройство. Эта часть обрабатывает доступ к регистровому пространству

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

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

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

#include <msp430.h> 
#include <stdint.h>

#include "one-slave.h"
#include "one-2408.h"

// Массив с описаниями устройств
static one_device devices[] = {
    {
        // (ROM-адрес) | (Family code)
        .rom = 0x0011223344556600 | ONE_2408_FC,
        // Функция инициализации предоставляется конкретным устройством
        .init = &one_2408_init,
        // Параметры устройства: в данном случае указатель на область регистров,
        // отвечающих за PORT1 в микроконтроллере
        .device = &(one_2408) {
            .port_base = &P1IN
        }
    },
    {
        .rom = 0x00AA000000000100 | 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();
    }
}

Железо

Вместо существующей платы была создана другая:

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

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

Подключение к Openhab

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

http://owhttpd:2121/29.0100000000AA/PIO.BYTE/?PIO.BYTE=VALUE

VALUE — значение от 0 до 255.

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

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

Заключение

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

  • Работа на прерываниях, в промежутках между транзакциями микроконтроллер находится в режиме низкого энергопотребления
  • Возможность эмуляции нескольких устройств на одном микроконтроллере
  • Работа проверялась на MSP430G2553, теоретически, на других контроллерах этой серии тоже заработает

Исходники можно найти здесь: http://ift.tt/1B8nbOs

This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.

Комментариев нет:

Отправить комментарий