Добрый вечер, уважаемые форумчане! Хотел поинтересоваться. Делаю диммер на ESP8266. Для отслеживания перехода через 0 использую следующую схему Минимум ставил резисторы R2 и R3 по 15к. Проблема вот в чем. Для отслеживания перехода через 0 использую внешнее прерывание по входу ESP и из-за флуктуации напряжения вблизи 0, прерывание срабатывает и по спадающему и по нарастающему фронту сигнала, независимо от настройки. Может кто подскажет достаточно точную схему перехода через 0. Используемый код: Код (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(); } Проверял отдельно на кнопке работу прерывания, работает правильно.
По Вашей схеме переход через 0 - импульс высокого уровня. Какова его длительность? И насколько круты фронт и спад? Все элементы можно использовать smd? ЗЫ: Я на другом форуме создавал тему, подсказали с реализацией кода. Но из-за отсутствия нормальных таймеров в ESP невозможно организовать более одного канала диммера, плюс непонятки с отслеживанием перехода через 0. Попробую на макетке собрать Вашу схему. Просто хочу данный димер поместить в монтажную коробку д.100 мм и имеет значение размер схемы.
Зависит от соотношения емкости конденсатора, токоограничивающего резистора и прямого тока светодиода оптрона. Я реагирую на передний фронт. Передний фронт возникает при напряжении в сети менее 20 вольт. Этого достаточно, чтобы уйти на прерывание и попасть прямо в ноль. Если не получается попасть ровно в ноль, ничто не мешает включать программную корректировку (при необходимости). Не измерял. Спад не крутой. В общем случае зависит от коэффициента передачи тока оптрона. У применённого мной этот параметр имеет разброс от 100 и до 300%. у меня только smd. Вводные резисторы из-за высокой загруженности по напряжению я использовал MELF на 250В.
Мы же знаем частоту сети, кто мешает после срабатывания прерывания игнорировать все импульсы в течение 7,5-8мс? Не, у меня диммер не на ESP. Сам диммер на ATtiny85 влезает и в ATtiny45. А вот тинькой управляет ESP8266 по I2C. Мне кажется так правильней.
Согласен с Вами 100%. Но есть два "но". Первое - важен минимальный габарит платы диммера, а дополнительные элементы этот размер увеличивают. Второе: вроде бы разобрался как реализовать на ESP управление диммером, прошивку через OTA. Если добавить контроллер для реализации управления симисторами, то усложняется код программы ESP, необходимо организовать обмен данными между ESP и AVRа если организовывать прошивку обоих контроллеров по воздуху, то все становится еще сложней. Нашел интересный проект esp-link, который позволяет такое сделать, но расстраивает его надежная работа.
Ну тут хозяин - барин. По поводу кода на ESP - так он проще намного. Там управление - три команды: Код (C++): Wire.beginTransmission(0x26); Wire.write(Level); Wire.endTransmission(); Level - значение яркости от 0 до 100 (%) Первый канал - просто значение яркости. Второй канал - значение яркости + взведен старший бит. ( Level = Level | 0x80; ) На самом деле после исправления недоработки со сбросом предделителей таймера (перед сбросом таймера, в прерывании от Zero-Cross). Пропали мизерные, и до этого почти не ощутимые на вгляд, подрагивания яркости. От покупного, высококачественного - не отличить. Раньше грешил на нестабильность работы Zero-Cross, но все оказалось гораздо проще! С 2018-го два таких работают в санузлах, и перепрошивать тиньку необходимости не возникло.
Мне коллега тоже советует, не парься с ESP, делай реализацию диммера наTiny и поднимай вэб-интерфейс на ESP. Но я для себя прикидываю - обвязка AVR, разъем для программирования обоих контроллеров. Это все место на плате. Короче нужно проектировать плату, и смотреть как впишется в габариты монтажной коробки. Самое что интересное, при использовании кода выше в теме, мерцания диммера нет в принципе на ESP. Но если использовать библиотеку robotdyn или dimmer arduino, то в нем появляются мерцания. Я пока так и не понял, в чем может быть проблема. Но есть мысль, что в коде выше симистор открывается импульсом 20 мкс. А в библиотеках симистор получает импульс управления до конца полупериода. PS:делал диммер чисто на AVR - одно удовольствие, работа так как запрограммировал.
А насколько критичны номиналы R4, R5, R7, R8? Есть просто smd 2512 100к - достаточно поставить пару, вместо четырех 1206?
А такой вопрос, собрал по такой схеме Но импульс низкого уровня, возникающий при переходе через 0, не дотягивает до 0. С высокого уровня падает где-то на 500 мВ. Это из-за того, что стабилитрон на 5В? Правда вместо РС817 поставил 4N35.
Слишком велика емкость конденсатора и сопротивление токоограничивающего резистора. Энергия, запасаемая конденсатором, пропорциональна квадрату напряжения. Поэтому лучше увеличивать напряжение в схеме, чем увеличивать ток.
Можно и на 15 вольт. Тогда фронт импульса будет ещё ближе к истинному переходу через ноль. Всё остальное оставить из оригинальной схемы.