Диммер на esp

Тема в разделе "ESP8266, ESP32", создана пользователем Melandr, 30 янв 2021.

  1. Melandr

    Melandr Нуб

    Добрый вечер, уважаемые форумчане!
    Хотел поинтересоваться. Делаю диммер на ESP8266. Для отслеживания перехода через 0 использую следующую схему
    2021-01-30_190801.jpg
    Минимум ставил резисторы R2 и R3 по 15к. Проблема вот в чем. Для отслеживания перехода через 0 использую внешнее прерывание по входу ESP и из-за флуктуации напряжения вблизи 0, прерывание срабатывает и по спадающему и по нарастающему фронту сигнала, независимо от настройки. Может кто подскажет достаточно точную схему перехода через 0.
    SDS00004.png
    SDS00005.png
    Используемый код:
    Код (C++):
    #include "ets_sys.h"
    #include "gpio.h"
    #include "OTA.h"

    #define INTC_EDGE_EN  (*(volatile uint32_t *)0x3FF00004)
    #define TIMER_LOAD (*(volatile uint32_t *)0x60000600)
    #define TIMER_COUNT (*(volatile uint32_t *)0x60000604)
    #define TIMER_CTRL (*(volatile uint32_t *)0x60000608)
    #define TIMER_INT  (*(volatile uint32_t *)0x6000060c)
    #define GPIO_OUT_W1TS (*(volatile uint32_t *)0x60000304)
    #define GPIO_OUT_W1TC (*(volatile uint32_t *)0x60000308)
    #define GPIO_OUTP (*(volatile uint32_t *)0x60000300)
    #define GPIO_STATUS (*(volatile uint32_t *)0x6000031C)
    #define GPIO_PIN2_CFG (*(volatile uint32_t *)0x60000330)
    #define GPIO_STATUS_W1TC (*(volatile uint32_t *)0x60000324)

    static const int GPIO_OUT = 2; // GPIO2
    static const int GPIO_IN = 1; // GPIO1

    const char* ssid = "ASUS";
    const char* password = "gCU8YNZs";

    uint32_t volatile pulse1_in_0us2 = 12 * 5; // in 0.2 us (0x007fffff max), min 12*5
    uint32_t volatile pulse2_in_0us2 = 50 * 5; // in 0.2 us (0x007fffff max), min 12*5

    //обработчик внешнего прерывания по входу
    void ICACHE_RAM_ATTR GPIOs_intr_handler(void *arg)
    {
      (void)arg;
      uint32_t tmp = GPIO_STATUS;
      GPIO_STATUS_W1TC = tmp;
      ets_isr_mask(BIT(ETS_GPIO_INUM)); // запретить прерывания GPIOs
      ETS_GPIO_INTR_DISABLE();
      if (tmp & BIT(GPIO_IN)) {
        GPIO_OUT_W1TC = BIT(GPIO_OUT);
        TIMER_LOAD = pulse1_in_0us2;
        TIMER_COUNT = 0;
        TIMER_CTRL = 4 // TM_DIVDED_BY_16
                     //| BIT(6) // TM_AUTO_RELOAD_CNT
                     | BIT(7) //  TM_ENABLE_TIMER
                     ;
      }
    }

    //обработчик прерывания аппаратного таймера
    void ICACHE_RAM_ATTR hw_test_timer_cb(void *arg) {
      (void)arg;
      if (GPIO_OUTP & BIT(GPIO_OUT)) {      //если симистор включен
        GPIO_OUT_W1TC = BIT(GPIO_OUT);      //выключаем симистор
        TIMER_CTRL = 0; // stop timer
        gpio_pin_intr_state_set(GPIO_IN, GPIO_PIN_INTR_NEGEDGE);
        ets_isr_unmask(BIT(ETS_GPIO_INUM)); // разрешить прерывания GPIOs
        ETS_GPIO_INTR_ENABLE();
      } else {
        GPIO_OUT_W1TS = BIT(GPIO_OUT);    //если симистор выключен, включаем
        TIMER_LOAD = pulse2_in_0us2;      //загружаем в таймер значение времени импульса открытия
      }
    }

    void WiFi_init() {
      WiFi.mode(WIFI_STA);
      WiFi.begin(ssid, password);
      while (WiFi.waitForConnectResult() != WL_CONNECTED) {
        Serial.println("Connection Failed! Rebooting...");
        delay(500);
        ESP.restart();
      }
    }

    void setup() {
      gpio_init();

      ets_isr_mask(BIT(ETS_FRC_TIMER1_INUM) | BIT(ETS_GPIO_INUM)); // запретить прерывания GPIOs & Timer0
      GPIO_OUT_W1TC = BIT(GPIO_OUT);
      TIMER_CTRL = 0; // stop timer

      TIMER_COUNT = 0;
      PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_GPIO1);
      PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_GPIO2);
      gpio_output_set(0, 0, BIT(GPIO_OUT), BIT(GPIO_IN));
      GPIO_PIN2_CFG &= ~BIT(GPIO_OUT); // normal out (push-pull)

      ets_isr_attach(ETS_GPIO_INUM, GPIOs_intr_handler, NULL);
      gpio_pin_intr_state_set(GPIO_IN, GPIO_PIN_INTR_NEGEDGE);

      ets_isr_attach(ETS_FRC_TIMER1_INUM, hw_test_timer_cb, NULL);
      INTC_EDGE_EN |= BIT(1); // + timer0
      ets_isr_unmask(BIT(ETS_FRC_TIMER1_INUM) | BIT(ETS_GPIO_INUM)); // разрешить прерывания GPIOs & Timer0

      WiFi_init();
      OTA_init();
    }

    void loop() {
      ArduinoOTA.handle();

    }
    OTA.h
    Код (C++):
    #include "ArduinoOTA.h"

    void OTA_init() {
      ArduinoOTA.onStart([]() {
      });

      ArduinoOTA.onEnd([]() {
      });

      ArduinoOTA.begin();
    }
    Проверял отдельно на кнопке работу прерывания, работает правильно.
     
  2. parovoZZ

    parovoZZ Гуру

    Здесь надо звать @SergeiL Он реализовал диммер на ESP.
    Я использую такую схему
    dimmer.png
     
    Рокки1945 нравится это.
  3. Melandr

    Melandr Нуб

    По Вашей схеме переход через 0 - импульс высокого уровня. Какова его длительность? И насколько круты фронт и спад? Все элементы можно использовать smd?
    ЗЫ: Я на другом форуме создавал тему, подсказали с реализацией кода. Но из-за отсутствия нормальных таймеров в ESP невозможно организовать более одного канала диммера, плюс непонятки с отслеживанием перехода через 0. Попробую на макетке собрать Вашу схему. Просто хочу данный димер поместить в монтажную коробку д.100 мм и имеет значение размер схемы.
     
  4. parovoZZ

    parovoZZ Гуру

    Зависит от соотношения емкости конденсатора, токоограничивающего резистора и прямого тока светодиода оптрона. Я реагирую на передний фронт. Передний фронт возникает при напряжении в сети менее 20 вольт. Этого достаточно, чтобы уйти на прерывание и попасть прямо в ноль. Если не получается попасть ровно в ноль, ничто не мешает включать программную корректировку (при необходимости).

    Не измерял. Спад не крутой. В общем случае зависит от коэффициента передачи тока оптрона. У применённого мной этот параметр имеет разброс от 100 и до 300%.

    у меня только smd. Вводные резисторы из-за высокой загруженности по напряжению я использовал MELF на 250В.
     
    Последнее редактирование: 30 янв 2021
  5. parovoZZ

    parovoZZ Гуру

    Нет, низкий. Всё остальное время на пине 1.
     
  6. SergeiL

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

    Мы же знаем частоту сети, кто мешает после срабатывания прерывания игнорировать все импульсы в течение 7,5-8мс?

    Не, у меня диммер не на ESP.
    Сам диммер на ATtiny85 влезает и в ATtiny45.
    А вот тинькой управляет ESP8266 по I2C.

    upload_2021-1-30_21-49-27.png

    Мне кажется так правильней.
     
    Последнее редактирование: 30 янв 2021
    Рокки1945 нравится это.
  7. Melandr

    Melandr Нуб

    Согласен с Вами 100%. Но есть два "но". Первое - важен минимальный габарит платы диммера, а дополнительные элементы этот размер увеличивают. Второе: вроде бы разобрался как реализовать на ESP управление диммером, прошивку через OTA. Если добавить контроллер для реализации управления симисторами, то усложняется код программы ESP, необходимо организовать обмен данными между ESP и AVRа если организовывать прошивку обоих контроллеров по воздуху, то все становится еще сложней. Нашел интересный проект esp-link, который позволяет такое сделать, но расстраивает его надежная работа.
     
  8. parovoZZ

    parovoZZ Гуру

    Тогда бери двухъядерные SoC.

    А AVR зачем прошивать? Сразу заложить весь функционал и прошить.
     
  9. Рокки1945

    Рокки1945 Гуру

    или
    вот и прикиньте что важнее
     
  10. SergeiL

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

    Ну тут хозяин - барин.
    По поводу кода на ESP - так он проще намного. Там управление - три команды:
    Код (C++):
    Wire.beginTransmission(0x26);
    Wire.write(Level);
    Wire.endTransmission();      
    Level - значение яркости от 0 до 100 (%)
    Первый канал - просто значение яркости.
    Второй канал - значение яркости + взведен старший бит. ( Level = Level | 0x80; )

    На самом деле после исправления недоработки со сбросом предделителей таймера (перед сбросом таймера, в прерывании от Zero-Cross).
    Пропали мизерные, и до этого почти не ощутимые на вгляд, подрагивания яркости. От покупного, высококачественного - не отличить.
    Раньше грешил на нестабильность работы Zero-Cross, но все оказалось гораздо проще!
    С 2018-го два таких работают в санузлах, и перепрошивать тиньку необходимости не возникло.
     
  11. SergeiL

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

    Так а тинька в соике 5*7мм, это с выводами.
     
  12. Melandr

    Melandr Нуб

    Мне коллега тоже советует, не парься с ESP, делай реализацию диммера наTiny и поднимай вэб-интерфейс на ESP. Но я для себя прикидываю - обвязка AVR, разъем для программирования обоих контроллеров. Это все место на плате. Короче нужно проектировать плату, и смотреть как впишется в габариты монтажной коробки. Самое что интересное, при использовании кода выше в теме, мерцания диммера нет в принципе на ESP. Но если использовать библиотеку robotdyn или dimmer arduino, то в нем появляются мерцания. Я пока так и не понял, в чем может быть проблема. Но есть мысль, что в коде выше симистор открывается импульсом 20 мкс. А в библиотеках симистор получает импульс управления до конца полупериода.
    PS:делал диммер чисто на AVR - одно удовольствие, работа так как запрограммировал.
     
  13. parovoZZ

    parovoZZ Гуру

    там нет никакой обвязки.
     
  14. Melandr

    Melandr Нуб

    А насколько критичны номиналы R4, R5, R7, R8? Есть просто smd 2512 100к - достаточно поставить пару, вместо четырех 1206?
     
  15. parovoZZ

    parovoZZ Гуру

    абсолютно не критичны. Я подбирал из условия минимального открытия стабилитрона.
     
  16. Melandr

    Melandr Нуб

    А такой вопрос, собрал по такой схеме

    upload_2021-2-7_14-43-27.png
    Но импульс низкого уровня, возникающий при переходе через 0, не дотягивает до 0. С высокого уровня падает где-то на 500 мВ. Это из-за того, что стабилитрон на 5В? Правда вместо РС817 поставил 4N35.
     

    Вложения:

  17. parovoZZ

    parovoZZ Гуру

    Слишком велика емкость конденсатора и сопротивление токоограничивающего резистора. Энергия, запасаемая конденсатором, пропорциональна квадрату напряжения. Поэтому лучше увеличивать напряжение в схеме, чем увеличивать ток.
     
    Последнее редактирование: 7 фев 2021
  18. Melandr

    Melandr Нуб

    достаточно будет стабилитрона на 15 В, или нужно больше?
     
  19. parovoZZ

    parovoZZ Гуру

    Можно и на 15 вольт. Тогда фронт импульса будет ещё ближе к истинному переходу через ноль. Всё остальное оставить из оригинальной схемы.
     
  20. Melandr

    Melandr Нуб

    на 15 В не нашел, поставил на 10. Получил импульс низкого уровня почти до 0 В. Спасибо.