Двухканальный диммер на AtTiny85 (UART I2C)

Тема в разделе "Глядите, что я сделал", создана пользователем SergeiL, 13 апр 2018.

  1. SergeiL

    SergeiL Оракул Модератор

    Искал варианты плавного управления освещением.
    Схема стандартная.
    Хотелось сделать надежный, стабильный диммер, который можно было бы подключить к уже существующим устройствам в дополнение, на шину I2C.
    Тот код, что был в сети работал, но качество работы именно диммера меня не радовало, на небольшой яркости было дрожание яркости.
    Данный вариант работает уже много лет, и претензий к нему нет совсем.
    Никаких подергиваний яркости нет, лампы включаются и выключаются плавно, дабы уменьшить удар по нити в момент включения, да и поинтересней так.

    Схема практически стандартная:
    I2C:
    scheme_I2C.png

    Код для I2C:
    Код (C++):
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include "TinyWireS.h"                  // I2C slave

    //  AtTiny85 16MHz internal
    // Fuses: HIGH = 0xDF; LOW = 0xF1; EXTENDED = 0xFF

    #define I2C_SLAVE_ADDR    0x26            // i2c slave address (38)

    #define AC_DETECT 3       // Пин B3 zero cross detect, PCINT3 , физический pin 2
    #define AC_LOAD_0 4       // Пин B4 выход на нагрузку 1 физический pin 3
    #define AC_LOAD_1 1       // Пин B1 выход на нагрузку 2 физический pin 6

    #define MIN_TCNT_VAL 5    // Минимальное  значение TCNT1   Dimming level (5-150)  5 = ON, 150 = OFF
    #define MAX_TCNT_VAL 150  // Максимальное значение TCNT1   Dimming level (5-150)  5 = ON, 150 = OFF

    #define PULS_COUNT   4    // Длина импульса на Gate симистора в тиках таймера 1

    #define MAX_BUFF_LENG 5   // Размер буфера под команду

    volatile uint8_t dimming_0 = MAX_TCNT_VAL;  // Переменная для уровня диммирования нагрузки 1
    volatile uint8_t dimming_1 = MAX_TCNT_VAL;  // Переменная для уровня диммирования нагрузки 2
    volatile uint8_t dimming_0_cur = MAX_TCNT_VAL; // Переменная для хранения текущего уровня диммирования нагрузки 1
    volatile uint8_t dimming_1_cur = MAX_TCNT_VAL; // Переменная для хранения текущего уровня диммирования нагрузки 2

    volatile uint8_t Errflag=1;                 // Флаг ошибки  0 - штатная работа zero cross detect, 1 - не работает zero cross detect

    ISR(TIMER1_COMPA_vect)                      // Отработчик Timer1 прерывание по сравнению с регистром OC1A
    {
        static uint8_t dimming_0_pulse=0;

        if(dimming_0_pulse)
        {
          PORTB &= ~( 1 << AC_LOAD_0 );            // Выключим оптопару
          dimming_0_pulse=0;
        }
        else
        {
          if ( dimming_0_cur < MAX_TCNT_VAL && Errflag==0 )    // Если уровень диммирования больше минимального и нет ошибки от  zero cross detect
          {
            PORTB |= ( 1 << AC_LOAD_0 );                   // Включение нагрузки 0
            OCR1A=OCR1A+PULS_COUNT;
            dimming_0_pulse=1;
          }
        }
    }

    ISR(TIMER1_COMPB_vect)            // Отработчик Timer1 прерывание по сравнению с регистром OC1B
    {
        static uint8_t dimming_1_pulse=0;

        if(dimming_1_pulse)
        {
          PORTB &= ~( 1 << AC_LOAD_1 );            // Выключим оптопару
          dimming_1_pulse=0;
        }
        else
        {
          if ( dimming_1_cur < MAX_TCNT_VAL && Errflag==0 )    // Если уровень диммирования больше минимального и нет ошибки от  zero cross detect
          {
            PORTB |= ( 1 << AC_LOAD_1 );                   // Включение нагрузки 1
            OCR1B=OCR1B+PULS_COUNT;
            dimming_1_pulse=1;
          }
        }
    }

    ISR(TIMER1_OVF_vect)             // Обработчик Таймер 1 переполнение. Что то пошло не так, возможно не работает zero cross detection или нет напряжения сети
    {
        PORTB &= ~( 1 << AC_LOAD_0 );            // Выключим нагрузку 1
        PORTB &= ~( 1 << AC_LOAD_1 );            // Выключим нагрузку 2
        Errflag=1;                               // взведем флаг ошибки в работе zero cross detect.
    }

    ISR(PCINT0_vect)             // Отработчик PCINT, zero cross detect, нам нужен фронт (спад сетевого напряжения)
    {

        if ( !(PINB & (1<<PINB3)) &&  TCNT1 < 120 && Errflag==0)           // минимизируем помехи в рабочем режиме.  10мс - 156,25 отсчетов таймера. Должны попадать сюда на отсчетах таймера 155-158
          return;

        GTCCR |= 2;                              // сбросим счетчики предделителей
        TCNT1 = 0;   // сбросим таймер

        if (dimming_0_cur>dimming_0)
        {
          OCR1A=dimming_0_cur--;                // пропишем в регистр сравнения значение уровня диммирования нагрузки 0
        }
        else if(dimming_0_cur<dimming_0)
        {
          OCR1A=dimming_0_cur++;                // пропишем в регистр сравнения значение уровня диммирования нагрузки 0
        }
        else
        {
          OCR1A=dimming_0_cur;                  // пропишем в регистр сравнения значение уровня диммирования нагрузки 0
        }

        if (dimming_1_cur>dimming_1)
        {
          OCR1B=dimming_1_cur--;                // пропишем в регистр сравнения значение уровня диммирования нагрузки 1
        }
        else if (dimming_1_cur<dimming_1)
        {
          OCR1B=dimming_1_cur++;                // пропишем в регистр сравнения значение уровня диммирования нагрузки 1

        }
        else
        {
          OCR1B=dimming_1_cur;                  // пропишем в регистр сравнения значение уровня диммирования нагрузки 1
        }

        PORTB &= ~( 1 << AC_LOAD_0 );            // Выключим оптопару
        PORTB &= ~( 1 << AC_LOAD_1 );            // Выключим оптопару
        Errflag=0;                               // рабочий режим, сбросим режим ошибки
    }


    void setup()
    {
        DDRB &= ~(1 << AC_DETECT);                       // Настроим как вход
        PORTB |= (1 << AC_DETECT);                       // Включим подтяжку

        DDRB |= 1 << AC_LOAD_0;                          // Настроим как выход
        DDRB |= 1 << AC_LOAD_1;                          // Настроим как выход

        PORTB &= ~( 1 << AC_LOAD_0 );                    // Выключим оптопару
        PORTB &= ~( 1 << AC_LOAD_1 );                    // Выключим оптопару
        GIMSK |= 1 << PCIE;                               // Hазрешим прерывание от PCINT
        PCMSK |= 1 << PCINT3;                             // Настроим прерывание от PCINT3.

        TIMSK |= 1 << OCIE1A | 1 << OCIE1B | 1 << TOIE1;  // Разрешим прерывание для Таймера 1 по сравненю с OCR1A, OCR1B, и переполнению таймера
        TCNT1 = 0;                                        // сбросим таймер
        TCCR1 = B00001011;                                // включим таймер с предделителем на 1024

        OCR1A=MAX_TCNT_VAL;                               // пропишем в регистр сравнения значение для выключенной нагрузки
        OCR1B=MAX_TCNT_VAL;                               // пропишем в регистр сравнения значение для выключенной нагрузки
        GTCCR=0x00;

        TinyWireS.begin(I2C_SLAVE_ADDR);                  // init I2C Slave mode
    }

    void loop()
    {                      
      uint8_t  byteRcvd;
      uint8_t  load_num;
      uint8_t  pow_val;


       if (TinyWireS.available())                   //
       {
            byteRcvd = TinyWireS.receive();
            load_num = (byteRcvd & 0x80) ? 1 : 0;  // единица в старшем разряде - первый канал, 0 - нулевой.
            pow_val = byteRcvd & 0x7F;

            if ( pow_val <= 100)
            {
                if (load_num == 0)
                {
                  dimming_0=map(pow_val, 0, 100, MAX_TCNT_VAL, MIN_TCNT_VAL);
                }
                else
                {
                  dimming_1=map(pow_val, 0, 100, MAX_TCNT_VAL, MIN_TCNT_VAL);
                }
            }
       }
    }
    Управляется просто:
    Код (C++):
          Wire.beginTransmission(0x26);
          Wire.write(Level);
          Wire.endTransmission();    
    Level - значение яркости от 0 до 100 (%)
    Первый канал - просто значение яркости.
    Второй канал - значение яркости + взведен старший бит. ( Level = Level | 0x80; )
    Ничего не возвращает, не нужно это.

    Fuses: HIGH = 0xDF; LOW = 0xF1; EXTENDED = 0xFF

    Библиотека TinyWireS.h выложена здесь

    PS. Первые сообщения темы были удалены мною, тема скрыта.
    Написал сегодня все снова, будем потихоньку восстанавливать информацию.
     
    Последнее редактирование: 27 май 2021
    SOLOway, Рокки1945, vvr и 3 другим нравится это.
  2. SergeiL

    SergeiL Оракул Модератор

    Этот вариант с UART был первоначальным, на нем отлаживал работу именно диммера, потом был добавлен I2C.

    Схема с UART:
    scheme.png

    Код с UART:
    Код (C++):
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <SoftwareSerial.h>


    // AtTiny85 16MHz internal

    #define RX    4   // *** P4, Pin 2 (RX from Tiny need to connect to <- TX)
    #define TX    3   // *** P3, Pin 3 (TX from Tiny need to connect to -> RX)

    SoftwareSerial TinySerial(RX, TX);

    #define AC_DETECT 2       // Пин B2 zero cross detect, interrupt 0, физический pin 7
    #define AC_LOAD_0 0       // Пин B0 выход на нагрузку 1 физический pin 5
    #define AC_LOAD_1 1       // Пин B1 выход на нагрузку 2 физический pin 6

    #define MIN_TCNT_VAL 5    // Минимальное  значение TCNT1   Dimming level (5-150)  5 = ON, 150 = OFF
    #define MAX_TCNT_VAL 150  // Максимальное значение TCNT1   Dimming level (5-150)  5 = ON, 150 = OFF

    #define PULS_COUNT   4    // Длина импульса на Gate симистора в тиках таймера 1

    #define MAX_BUFF_LENG 5   // Размер буфера под команду

    volatile uint8_t dimming_0 = MAX_TCNT_VAL;  // Переменная для уровня диммирования нагрузки 1
    volatile uint8_t dimming_1 = MAX_TCNT_VAL;  // Переменная для уровня диммирования нагрузки 2
    volatile uint8_t dimming_0_cur = MAX_TCNT_VAL; // Переменная для хранения текущего уровня диммирования нагрузки 1
    volatile uint8_t dimming_1_cur = MAX_TCNT_VAL; // Переменная для хранения текущего уровня диммирования нагрузки 2

    volatile uint8_t Errflag=1;                 // Флаг ошибки  0 - штатная работа zero cross detect, 1 - не работает zero cross detect

    volatile uint8_t test_val;                  // переменные для отладки

    ISR(TIMER1_COMPA_vect)             // Отработчик Timer1 прерывание по сравнению с регистром OC1A
    {    
        static uint8_t dimming_0_pulse=0;

        if(dimming_0_pulse)
        {
          PORTB &= ~( 1 << AC_LOAD_0 );            // Выключим оптопару
          dimming_0_pulse=0;
        }
        else
        {
          if ( dimming_0_cur < MAX_TCNT_VAL && Errflag==0 )    // Если уровень диммирования больше минимального и нет ошибки от  zero cross detect
          {
            PORTB |= ( 1 << AC_LOAD_0 );                   // Включение нагрузки 0
            OCR1A=OCR1A+PULS_COUNT;
            dimming_0_pulse=1;
          }
        }
    }

    ISR(TIMER1_COMPB_vect)            // Отработчик Timer1 прерывание по сравнению с регистром OC1B
    {
        static uint8_t dimming_1_pulse=0;

        if(dimming_1_pulse)
        {
          PORTB &= ~( 1 << AC_LOAD_1 );            // Выключим оптопару
          dimming_1_pulse=0;
        }
        else
        {
          if ( dimming_1_cur < MAX_TCNT_VAL && Errflag==0 )    // Если уровень диммирования больше минимального и нет ошибки от  zero cross detect
          {
            PORTB |= ( 1 << AC_LOAD_1 );                   // Включение нагрузки 1
            OCR1B=OCR1B+PULS_COUNT;
            dimming_1_pulse=1;
          }
        }
    }

    ISR(TIMER1_OVF_vect)             // Обработчик Таймер 1 переполнение. Что то пошло не так, возможно не работает zero cross detection или нет напряжения сети
    {
        PORTB &= ~( 1 << AC_LOAD_0 );            // Выключим нагрузку 1
        PORTB &= ~( 1 << AC_LOAD_1 );            // Выключим нагрузку 2
        Errflag=1;                               // взведем флаг ошибки в работе zero cross detect.
    }

    ISR(INT0_vect)             // Отработчик INT0, zero cross detect, срабатывает по фронту (спад сетевого напряжения)
    {

        if (TCNT1 < 120 && Errflag==0)           // минимизируем помехи в рабочем режиме.  10мс - 156,25 отсчетов таймера. Должны попадать сюда на отсчетах таймера 155-158
          return;
        GTCCR |= 2;                              // сбросим счетчики предделителей
        TCNT1 = 0;   // сбросим таймер

        test_val=TCNT1;                          // отладка ( для отображения отсчета на котором сюда попали)

        if (dimming_0_cur>dimming_0)      
        {
          OCR1A=dimming_0_cur--;                // пропишем в регистр сравнения значение уровня диммирования нагрузки 0
        }
        else if(dimming_0_cur<dimming_0)
        {
          OCR1A=dimming_0_cur++;                // пропишем в регистр сравнения значение уровня диммирования нагрузки 0
        }
        else
        {
          OCR1A=dimming_0_cur;                  // пропишем в регистр сравнения значение уровня диммирования нагрузки 0
        }


        if (dimming_1_cur>dimming_1)
        {
          OCR1B=dimming_1_cur--;                // пропишем в регистр сравнения значение уровня диммирования нагрузки 1
        }
        else if (dimming_1_cur<dimming_1)
        {
          OCR1B=dimming_1_cur++;                // пропишем в регистр сравнения значение уровня диммирования нагрузки 1

        }
        else
        {
          OCR1B=dimming_1_cur;                  // пропишем в регистр сравнения значение уровня диммирования нагрузки 1
        }

        PORTB &= ~( 1 << AC_LOAD_0 );            // Выключим оптопару
        PORTB &= ~( 1 << AC_LOAD_1 );            // Выключим оптопару
        Errflag=0;                               // рабочий режим, сбросим режим ошибки
    }


    void setup()
    {
        DDRB &= ~(1 << AC_DETECT);                       // Настроим как вход
        PORTB |= (1 << AC_DETECT);                       // Включим подтяжку

        DDRB |= 1 << AC_LOAD_0;                          // Настроим как выход
        DDRB |= 1 << AC_LOAD_1;                          // Настроим как выход

        PORTB &= ~( 1 << AC_LOAD_0 );                    // Выключим оптопару
        PORTB &= ~( 1 << AC_LOAD_1 );                    // Выключим оптопару
        GIMSK |= 1 << INT0;                              // Hазрешим прерывание от INT0
        MCUCR |= 1 << ISC01  | 1 << ISC00;               // Настроим прерывание от INT0 по фронту.

        TIMSK |= 1 << OCIE1A | 1 << OCIE1B | 1 << TOIE1;  // Разрешим прерывание для Таймера 1 по сравненю с OCR1A, OCR1B, и переполнению таймера
        TCNT1 = 0;                                        // сбросим таймер
        TCCR1 = B00001011;                                // включим таймер с предделителем на 1024

        OCR1A=MAX_TCNT_VAL;                               // пропишем в регистр сравнения значение для выключенной нагрузки
        OCR1B=MAX_TCNT_VAL;                               // пропишем в регистр сравнения значение для выключенной нагрузки
        GTCCR=0x00;

        TinySerial.begin(38400);                          // оптимальный вариант, (в SoftwareSerial есть cli() на отправке)
    }

    void loop()                                           // отладочный вариант loop() с получением информациии из Arduino IDE:  Канал + Мощность от 0 до 100. Например:  190  первый канал, мощность 90; 020 нулевой канал, мощность 20.
    {
       static char      buff[5];
       static byte      pos=0;
       static uint32_t  last_ms=0;
       static uint32_t  disp_ms=0;

       uint32_t         tmp_ms=millis();
       int              result = 0;
       byte             processing_flag = 0;
       char             c;

       if (TinySerial.available() > 0)   // если что то приняли
       {
          c=TinySerial.read();           // прочитаем байт

          if (c >= '0' && c <= '9' && pos < MAX_BUFF_LENG)      // если цифра
          {
            buff[pos++]=c;               // положим в буфер и сдвинем позицию
            last_ms = tmp_ms;            // запомним время получения байта
          }
          else
            processing_flag=1;           // если не символ - взведем флаг

       }

       if( pos >= 1 && ((tmp_ms - last_ms > 30) || processing_flag) )  // если пауза больше 30 милисекунд или не цифра
       {
          buff[pos]=0;
          result=atoi(buff+1);  //
          pos=0;

          if (buff[0] <= '1' && result >= 0 && result <= 100)  // если канал 0-1, значение 0-100
          {
                                       // ------ потом убрать  вместе с принтами ----
            TinySerial.println();        

            if (buff[0]=='0')
              TinySerial.print(" 0: <");
            else
              TinySerial.print(" 1: <");

            TinySerial.print(result);
            TinySerial.print("> (");
                                        //-------------------------
            if (buff[0]=='0')
            {
              dimming_0=map(result, 0, 100, MAX_TCNT_VAL, MIN_TCNT_VAL);
              TinySerial.print(dimming_0);
            }
            else
            {
              dimming_1=map(result, 0, 100, MAX_TCNT_VAL, MIN_TCNT_VAL);
              TinySerial.print(dimming_1);
            }
     
            TinySerial.println(") ");
         }
       }
    }
     
    Управление по UART:
    Первый символ номер канала (0 или 1)
    Дальше без пробела мощность от 0 до 100

    Пример:
    00 - выключение первого канала.
    050 - первый канал на 50%
    130 - второй канал на 30%
     
    Последнее редактирование: 27 май 2021
    Антон Овсянников и ИгорьК нравится это.
  3. SergeiL

    SergeiL Оракул Модератор

    Сегодня добавил в код сброс предделителей таймера (перед сбросом таймера, в прерывании от Zero-Cross). Теперь даже намека нет на мизерные (и до этого почти не ощутимые на вгляд) подрагивания яркости. :)
    Раньше грешил на нестабильность работы Zero-Cross, но все оказалось гораздо проще! :)
     
    atompost и ИгорьК нравится это.
  4. SergeiL

    SergeiL Оракул Модератор

    Сегодня затестил работу диммера со светодиодной, диммируемой лампой Навигатор 10Вт GX53.
    На втором канале обычная галогенка на 220В.
    Галогенки в квартире, в принципе, диммируются идеально.

    В работе со светодиодной лампой замечены следующие особенности:
    1. Диапазон заметного диммирования LED лампы 20%-70%. ( у галогенки 5%-95%)
    2. В диапазоне 20%-25% яркость увеличивается очень быстро. (галогенки на 25% еле горят)
    3. В диапазоне 20%-25% видно небольшое хаотичное изменение яркости. Похоже в пределах одного - двух отсчетов таймера. Сказывается быстрое нарастание яркости, указанное в предыдущем пункте.
    В общем хотел использовать в качестве ночного режима в санузлах (в ночное время, чуть подсветить заметив движение, дабы не сшибать предметы, но и не будить ярким светом).
    Из-за пункта 3, даже и не знаю теперь.
    Может галогенки оставлю, или ленту, под подвесную тумбочку раковины.
    Еще попробую с другой LED лампой.

    Или стоит попробовать поднять частоту таймера. Но просто поднять не получится, таймер 8-ми бтиный.

    Вот, а Дядя Витя спрашивал, зачем нужно такое космически точное диммирование.
    Представляю, что было бы с 10% погрешностью.
     
    Последнее редактирование: 30 сен 2018
    vvr и ИгорьК нравится это.
  5. DIYMan

    DIYMan Guest

    Во второй строке должно же быть AC_LOAD_1, не?
     
    SergeiL нравится это.
  6. SergeiL

    SergeiL Оракул Модератор

    Да, все правильно! Спасибо!
    Конечно должно быт AC_LOAD_1
    Как всегда, у себя давно исправил, сюда не перенес. Поправил в первом сообщении.
     
  7. parovoZZ

    parovoZZ Гуру

    С 8-ми битным ловить нечего. Только 12-ти или 16-ти битный.
    И не увидел - длительность управляющего импульса как регулируется/задаётся?
     
  8. SergeiL

    SergeiL Оракул Модератор

    У меня прерывание - по спаду сетевого напряжения, поэтому выключаю там.
    То есть - включил из таймера, напряжение падает - выключил.
     
  9. parovoZZ

    parovoZZ Гуру

    Не, я имею ввиду импульс, который подаётся на ногу gain симистора для его открытия - не во всех квадрантах ток с этой ноги попадает в нагрузку, что приводит к неоправданному перерасходу электроэнергии.
     
  10. SergeiL

    SergeiL Оракул Модератор

    Да я понял, о чем речь, но пристраивать выключение не стал.
    Выключаю оптопару по спаду в прерывании ZeroCross.
    Попробовал и так и так, по ослику разницы не увидел.
     
  11. parovoZZ

    parovoZZ Гуру

    Себе в комнату сделал 160 Вт светодиодного света. Убавить - единственное желание. Сейчас примерно 30 Вт всего - хочется добавить, но пока не реализовано. Блок питания управляемый - хошь резистором, хошь ШИМ, хошь напругой 0-10В.
     
  12. SergeiL

    SergeiL Оракул Модератор

    А какие лампы? Или ленты?
    Второй второй день бьюсь с LED лампами GX35, диммируемыми - нормально не диммируются.
    Я понимаю, можно на постоянку с ШИМ перейти, но какие лампы использовать?

    Нужны диммируемые светильники, с возможностью достать электронику через отверстие из под гипрочного потолка.
    То есть, отверстие хотя бы 9см диаметром, Вынуть светильник, через отверстие достать WiFi блок, для возможности коммутации, доработки.

    Может кто-то лампы посоветует.
    Пробовал диммируемые Navigator, Gauss GX35.
     
  13. parovoZZ

    parovoZZ Гуру

    Arlight CRI 98%
    с внешним драйвером. Но они будут токовые, 99%.
    Споты и те с ШИМ стабилизатором внутри.
    Ничего себе(((
    Эти бы брал в последнюю очередь.

    Вообще дешманский светодиодный свет очень сильно режет глаз. В командировке снимали квартиру с такими светильниками - за 2 недели так и не привык.
    Приехал к себе - вообще ляпота.
    Как ни странно, но лампа из икеи на 10 вт горит уже 5 лет. Очень приятный свет даёт, но не диммируется.
     
  14. SergeiL

    SergeiL Оракул Модератор

    А что выбрать-то?
    Лента вроде не в тему, ищу светильники,можно с регулятором 0-10В.
    Вариантов много, но как работает... - не факт, что нормально.

    Нужен свет 2700К, диммируемый, без пульсаций :). Помещение 7 кв.м. Что выбрать?
     
  15. SergeiL

    SergeiL Оракул Модератор

    Подключил параллельно LED лампе галогенку, Gauss начала прекрасно диммироваться...
    У кого есть практический опыт??? Советуйте! :)
     
  16. parovoZZ

    parovoZZ Гуру

    Что-то отдельное от драйвера. У novolampa хороший ассортимент - я там затаривался.
    это да - кпд под вопросом. У ламп должно быть поболее.
    кухня?
    Очевидно, что не хватает тока для удержания симистора в открытом состоянии. Но это всего лишь догадки. Не знаю, как устроена диммируемая лампочка.
     
  17. SergeiL

    SergeiL Оракул Модератор

    Сейчас проверил параллельно Navigator, Gauss и галогенка.
    При наличии параллельной галогенки, Gauss диммируется прекрасно, без пульсаций и хаотичного изменения яркости.
    Зажигается на 3% и нормально диммируется до 80% (100% освещения). Вопрос, как решить проблему параллельной галогенки?
    Novigator - однозначно не айс :)!
    20-25% мощности очень большое изменение яркости на процент. Яркость заметно колбасит в пределах отсчета.
     
  18. SergeiL

    SergeiL Оракул Модератор

    Не, ванная.

    Вроде все стало работать стабильно. Нужно было добавить ламп. :) Маловата нагрузка была.
    Но на диммируемой LED лампе Navigator осталась небольшая болтанка яркости в диапазоне 20-25%.
    Даже с параллельно подключенной галогенкой.

    С Gauss 8W LED Dimmable начиная с двух параллельно подключенных ламп все стабильно. Понравилось! :)

    Добавил константу длительности управляющего импульса. Разницы не увидел, но пусть будет.
    Добавил плавное нарастание снижение мощности, при изменении уровня диммирования.
    Выглядит поинтереснее.
     
    Последнее редактирование: 2 окт 2018
  19. SergeiL

    SergeiL Оракул Модератор

    Зашел, обновил код и схему диммера с интерфейсом I2C. Может кому пригодится.
    Работой диммера (два канала легко лезут в Тини25) в связке с ESP8266 и Open HAB не просто доволен, а очень доволен.
    Два санузла, в каждом по контроллеру на ESP8266, с ночным и дневным режимом освещения, плюс плавный разогрев нитей ламп, счетчики воды, герконы дверей, PIR датчики движения, включение вентиляции, датчики температуры труб, включения теплого пола по присутствию в квартире из OH.
    За все время эксплуатации ни одного сбоя!
    Одним словом продолжаю доработку.
    А на форуме ничего нового... Только болтовня.
    Ну очень хочется найти прорывные решения!:)
     
    Последнее редактирование: 22 мар 2019
    SOLOway, KindMan, Andrey12 и ещё 1-му нравится это.
  20. SergeiL

    SergeiL Оракул Модератор

    Надеюсь, что будет время, и причешу, и выложу ESP-шную часть.
    Честно говоря не ожидал от Wi-Fi решения такой стабильности в работе.
    После замены точек доступа на UniFi, счетчики переподключения по Wi-Fi и MQTT, с декабря 2018-го стоят на нулях.
    После этого поменял точки доступа на UniFi в наших офисах в Москве и в Питере.
    Теперь, все говорят: что на проводе, что на Wi-Fi - разницы нет! :)
    Доволен!:)