Как-то раз я купил на 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

Комментарии (11)


  1. ignat99
    13.06.2015 12:42
    -1

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

    www.cnx-software.com/tag/internet-of-things/page/2 — больше информации.


  1. Fen1xL
    13.06.2015 15:30

    Можете разъяснить как работает нога MPS430_OUT. Я так понял при выдачи «1» на эту ногу, транзистор начнет притягивать DATA к земле, а как достигается единица (или DATA по умолчанию где-то подтянута к «1»)?


    1. resetnow Автор
      13.06.2015 19:21

      Да, подтянута к 1 где-нибудь, обычно в адаптере шины мастер-устройства.


  1. jar_ohty
    13.06.2015 16:29
    +1

    Проблема с ШИМ частотой 15 кГц — в том, что длинные провода на такой частоте (и ее гармониках — фронты-то нужны крутые) безбожно излучают в эфир. Так что на выход нужно ставить суровый ФНЧ.


    1. resetnow Автор
      13.06.2015 19:26

      Думал над этим, но дома я никак не проверю, что там и куда излучается. Как вообще сказать, начиная с какой частоты появится излучение? Частота довольно низкая, в этом диапазоне есть какие-то коммуникации?

      ФНЧ поставить не получится, потому что тогда функция регулировки яркости испортится (точнее, зависимость яркости от скважности). Насколько я понял, каких-либо более удобных способов управления такой нагрузкой пока не придумали. Если только в каждый светодиод встраивать контроллер (как в RGB адресуемых) и тогда можно и больше частоту сделать.


      1. jar_ohty
        13.06.2015 23:37

        Чтобы не испортилась, нужно, чтобы фильтр начинался с индуктивности.
        А что до частоты — тут важна не частота, как таковая, а длительность фронта. Если она составляет 1 мкс, то начиная с мегагерца уровень помехи будет падать под 3 дБ/октаву. И «палки» помехи будут стоять через каждые 15 кГц. Практически весь КВ диапазон этой штуковиной будет загажен.


        1. resetnow Автор
          14.06.2015 00:29

          Длительность фронта меньше, чем микросекунда. Как тогда вообще эти диммеры работают (в оригинале было около 400 Гц)? Фронты специально растягиваются? Может быть, подскажете пример конструкции фильтра именно для такого применения? Спасибо за советы.


    1. Hellsy22
      13.06.2015 22:06

      А если поднять рабочую частоту до 62кГц — насколько все станет хуже?


      1. resetnow Автор
        14.06.2015 00:23

        Там есть куда поднимать и 62 кГц тоже можно сделать, а почему именно это число?


        1. Hellsy22
          14.06.2015 11:59

          Это предельная частота для Arduino, вроде как. Ниже можно, а выше — уже сложнее.
          Ну и, насколько я помню, значительная часть полевых транзисторов работает на частотах до 100кГц. Если выше, то там возникают нехорошие эффекты типа недопереключения.


  1. dsd_corp
    13.06.2015 23:27
    +1

    По поводу согласования уровней 3.3v-5v посмотрите этот документ: www.adafruit.com/datasheets/an97055.pdf
    Не здесь, так в другом проекте возможно пригодится )

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