Эмуляция ведомых 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, теоретически, на других контроллерах этой серии тоже заработает


    Исходники можно найти здесь: github.com/resetnow/one-slave
    Share post

    Comments 11

      –1
      Как вам вот этот проект: www.souliss.net?

      www.cnx-software.com/tag/internet-of-things/page/2 — больше информации.
        0
        Можете разъяснить как работает нога MPS430_OUT. Я так понял при выдачи «1» на эту ногу, транзистор начнет притягивать DATA к земле, а как достигается единица (или DATA по умолчанию где-то подтянута к «1»)?
          0
          Да, подтянута к 1 где-нибудь, обычно в адаптере шины мастер-устройства.
          +1
          Проблема с ШИМ частотой 15 кГц — в том, что длинные провода на такой частоте (и ее гармониках — фронты-то нужны крутые) безбожно излучают в эфир. Так что на выход нужно ставить суровый ФНЧ.
            0
            Думал над этим, но дома я никак не проверю, что там и куда излучается. Как вообще сказать, начиная с какой частоты появится излучение? Частота довольно низкая, в этом диапазоне есть какие-то коммуникации?

            ФНЧ поставить не получится, потому что тогда функция регулировки яркости испортится (точнее, зависимость яркости от скважности). Насколько я понял, каких-либо более удобных способов управления такой нагрузкой пока не придумали. Если только в каждый светодиод встраивать контроллер (как в RGB адресуемых) и тогда можно и больше частоту сделать.
              0
              Чтобы не испортилась, нужно, чтобы фильтр начинался с индуктивности.
              А что до частоты — тут важна не частота, как таковая, а длительность фронта. Если она составляет 1 мкс, то начиная с мегагерца уровень помехи будет падать под 3 дБ/октаву. И «палки» помехи будут стоять через каждые 15 кГц. Практически весь КВ диапазон этой штуковиной будет загажен.
                0
                Длительность фронта меньше, чем микросекунда. Как тогда вообще эти диммеры работают (в оригинале было около 400 Гц)? Фронты специально растягиваются? Может быть, подскажете пример конструкции фильтра именно для такого применения? Спасибо за советы.
              0
              А если поднять рабочую частоту до 62кГц — насколько все станет хуже?
                0
                Там есть куда поднимать и 62 кГц тоже можно сделать, а почему именно это число?
                  0
                  Это предельная частота для Arduino, вроде как. Ниже можно, а выше — уже сложнее.
                  Ну и, насколько я помню, значительная часть полевых транзисторов работает на частотах до 100кГц. Если выше, то там возникают нехорошие эффекты типа недопереключения.
              +1
              По поводу согласования уровней 3.3v-5v посмотрите этот документ: www.adafruit.com/datasheets/an97055.pdf
              Не здесь, так в другом проекте возможно пригодится )

              Самое интересное начинается в пункте 2.3 на стр. 10.
              По большому счету для одной линии достаточно одного транзистора и одного резистора(на подтяжку со стороны 3.3v).

              Only users with full accounts can post comments. Log in, please.