diff --git a/tasmota/include/tasmota_globals.h b/tasmota/include/tasmota_globals.h
index 187209279..3518899b0 100644
--- a/tasmota/include/tasmota_globals.h
+++ b/tasmota/include/tasmota_globals.h
@@ -45,6 +45,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack
extern "C" void resetPins();
extern "C" int startWaveformClockCycles(uint8_t pin, uint32_t highCcys, uint32_t lowCcys,
uint32_t runTimeCcys, int8_t alignPhase, uint32_t phaseOffsetCcys, bool autoPwm);
+extern "C" void setTimer1Callback(uint32_t (*fn)());
#ifdef USE_SERIAL_BRIDGE
void SerialBridgePrintf(PGM_P formatP, ...);
#endif
diff --git a/tasmota/tasmota_xdrv_driver/xdrv_04_light_utils.ino b/tasmota/tasmota_xdrv_driver/xdrv_04_light_utils.ino
index 9567fdd48..0e214b977 100644
--- a/tasmota/tasmota_xdrv_driver/xdrv_04_light_utils.ino
+++ b/tasmota/tasmota_xdrv_driver/xdrv_04_light_utils.ino
@@ -40,7 +40,7 @@ const gamma_table_t ac_dimmer_table[] = { // don't put in PROGMEM for performa
{ 900, 704 },
{ 950, 748 },
{ 990, 850 },
- { 1024, 1024 },
+ { 1023, 1023 },
{ 0xFFFF, 0xFFFF } // fail-safe if out of range
};
diff --git a/tasmota/tasmota_xdrv_driver/xdrv_68_zerocrossDimmer.ino b/tasmota/tasmota_xdrv_driver/xdrv_68_zerocrossDimmer.ino
new file mode 100644
index 000000000..307fabc00
--- /dev/null
+++ b/tasmota/tasmota_xdrv_driver/xdrv_68_zerocrossDimmer.ino
@@ -0,0 +1,276 @@
+/*
+ xdrv_68_zerocrossdimmer.ino - Zero-Cross Dimmer support for Tasmota
+
+ Copyright (C) 2023 Stefan Bode
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifdef USE_AC_ZERO_CROSS_DIMMER
+/*********************************************************************************************\
+ * Zero-Cross AC Dimmer PMM 1..xx use
+\*********************************************************************************************/
+
+#define XDRV_68 68
+
+static const uint32_t GATE_ENABLE_TIME = 100;
+
+struct AC_ZERO_CROSS_DIMMER {
+ uint32_t cycle_time_us;
+ /// Time (in micros()) of last ZC signal
+ uint32_t crossed_zero_at;
+ /// Time since last ZC pulse to enable gate pin. 0 means not set.
+ bool timer_iterrupt_started = false;
+ bool dimmer_in_use = false;
+ // Check if 50µs timer is running.
+ uint32_t enable_time_us[MAX_PWMS];
+ /// Time since last ZC pulse to disable gate pin. 0 means no disable.
+ uint32_t disable_time_us[MAX_PWMS];
+ uint8_t current_state_in_phase[MAX_PWMS]; // 0=before fire HIGH, 1=HIGH, 2=after setting LOW, 3=before HIGH without setting LOW (POWER ON)
+ uint32_t lastlight[MAX_PWMS];
+ uint16_t detailpower[MAX_PWMS]; // replaces dimmer and light controll 0..10000. required savedata 0.
+ uint32_t intr_counter = 0;
+} ac_zero_cross_dimmer;
+
+
+#ifdef ESP32
+ static hw_timer_t *dimmer_timer = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
+#endif
+
+#define D_PRFX_ZCDIMMER "ZCDimmer"
+#define D_CMND_DIMMERSET "Set"
+
+const char kZCDimmerCommands[] PROGMEM = D_PRFX_ZCDIMMER "|" D_CMND_DIMMERSET;
+
+void (* const ZCDimmerCommand[])(void) PROGMEM = {
+ &CmndZCDimmerSet
+ };
+
+void IRAM_ATTR ACDimmerZeroCross(uint32_t time) {
+ ac_zero_cross_dimmer.dimmer_in_use = false;
+ ac_zero_cross_dimmer.cycle_time_us = time - ac_zero_cross_dimmer.crossed_zero_at;
+ ac_zero_cross_dimmer.crossed_zero_at = time;
+ for (uint8_t i=0; i < MAX_PWMS; i++) {
+ if (Pin(GPIO_PWM1, i) == -1) continue;
+ ac_zero_cross_dimmer.dimmer_in_use |= ac_zero_cross_dimmer.lastlight[i] > 0;
+ // Dimmer is physically off. Skip swich on
+ ac_zero_cross_dimmer.current_state_in_phase[i] = 0;
+ if (100 * ac_zero_cross_dimmer.enable_time_us[i] > 95 * ac_zero_cross_dimmer.cycle_time_us ) {
+ ac_zero_cross_dimmer.current_state_in_phase[i] = 1;
+ ac_zero_cross_dimmer.disable_time_us[i] = ac_zero_cross_dimmer.cycle_time_us / 2;
+ }
+ // If full cycle is required keep pin HIGH, skip LOW by skipping phase
+ if (100 * ac_zero_cross_dimmer.enable_time_us[i] < 15 * ac_zero_cross_dimmer.cycle_time_us) {
+ ac_zero_cross_dimmer.current_state_in_phase[i] = 3;
+ }
+ }
+}
+
+uint32_t IRAM_ATTR ACDimmerTimer_intr_ESP8266() {
+ //ACDimmerTimer_intr();
+ ACDimmerTimer_intr();
+ return 4000;
+}
+
+void ACDimmerInterruptDisable(bool disable)
+{
+ AddLog(LOG_LEVEL_INFO, PSTR("ZCD: Zero-CrossDimmer enabled: %d"),!disable);
+ ac_zero_cross_dimmer.timer_iterrupt_started = !disable;
+ if (disable) {
+ //stop the interrupt
+#ifdef ESP32
+ if (dimmer_timer != nullptr) {
+ timerAlarmDisable(dimmer_timer);
+ }
+#endif
+#ifdef ESP8266
+ //setTimer1Callback(NULL);
+#endif
+ } else {
+ for (uint8_t i = 0 ; i < MAX_PWMS; i++) {
+ if (Pin(GPIO_PWM1, i) != -1) {
+ pinMode(Pin(GPIO_PWM1, i), OUTPUT);
+ AddLog(LOG_LEVEL_INFO, PSTR("ZCD: Zero-CrossDimmer Pin %d set"),Pin(GPIO_PWM1, i));
+ }
+ }
+#ifdef ESP32
+ if (dimmer_timer == nullptr) {
+ // 80 Divider -> 1 count=1µs
+ dimmer_timer = timerBegin(0, 80, true);
+ timerAttachInterrupt(dimmer_timer, &ACDimmerTimer_intr, true);
+ // For ESP32, we can't use dynamic interval calculation because the timerX functions
+ // are not callable from ISR (placed in flash storage).
+ // Here we just use an interrupt firing every 75 µs.
+ if (Settings->save_data == 0) {
+ AddLog(LOG_LEVEL_INFO, PSTR("ZCD: Save disabled. High frequency scan enabled. DO NOT USE SAVEDATA if channel is on"));
+ timerAlarmWrite(dimmer_timer, 30, true);
+ } else {
+ AddLog(LOG_LEVEL_INFO, PSTR("ZCD: Save on. 75µs scan enabled"));
+ timerAlarmWrite(dimmer_timer, 75, true);
+ }
+ }
+ timerAlarmEnable(dimmer_timer);
+#endif
+
+#ifdef ESP8266
+ // Uses ESP8266 waveform (soft PWM) class
+ // PWM and AcDimmer can even run at the same time this way
+ //setTimer1Callback(&ACDimmerTimer_intr_ESP8266);
+#endif
+ }
+}
+
+void IRAM_ATTR ACDimmerTimer_intr() {
+ // If no ZC signal received yet.
+ uint32_t now = micros();
+ ac_zero_cross_dimmer.intr_counter++;
+ if (ac_zero_cross_dimmer.crossed_zero_at == 0)
+ return;
+
+ uint32_t time_since_zc = now - ac_zero_cross_dimmer.crossed_zero_at;
+ if (time_since_zc > 10100) {
+ memset(&ac_zero_cross_dimmer.current_state_in_phase, 0x00, sizeof(ac_zero_cross_dimmer.current_state_in_phase));
+ ac_zero_cross_dimmer.crossed_zero_at += ac_zero_cross_dimmer.cycle_time_us;
+ time_since_zc = now - ac_zero_cross_dimmer.crossed_zero_at;
+ }
+
+ for (uint8_t i = 0 ; i < MAX_PWMS; i++ ) {
+ if (Pin(GPIO_PWM1, i) == -1) continue;
+ switch (ac_zero_cross_dimmer.current_state_in_phase[i]) {
+ case 1:
+ if (time_since_zc >= ac_zero_cross_dimmer.disable_time_us[i]) {
+ digitalWrite(Pin(GPIO_PWM1, i), LOW);
+ ac_zero_cross_dimmer.current_state_in_phase[i]++;
+ }
+ break;
+ case 0:
+ case 3:
+ if (time_since_zc >= ac_zero_cross_dimmer.enable_time_us[i]) {
+ digitalWrite(Pin(GPIO_PWM1, i), HIGH);
+ ac_zero_cross_dimmer.current_state_in_phase[i]++;
+ }
+ break;
+ }
+ }
+}
+
+void ACDimmerControllTrigger(void) {
+
+ if (ac_zero_cross_dimmer.timer_iterrupt_started != ac_zero_cross_dimmer.dimmer_in_use) {
+ AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("ZCD: ZeroEnable %d --> %d ... change..."),ac_zero_cross_dimmer.timer_iterrupt_started, ac_zero_cross_dimmer.dimmer_in_use);
+ ACDimmerInterruptDisable(!ac_zero_cross_dimmer.dimmer_in_use);
+ }
+ for (uint8_t i = 0; i < MAX_PWMS; i++){
+ if (Pin(GPIO_PWM1, i) == -1) continue;
+ ac_zero_cross_dimmer.lastlight[i] = Light.fade_running ? Light.fade_cur_10[i] : Light.fade_start_10[i];
+ ac_zero_cross_dimmer.enable_time_us[i] = (ac_zero_cross_dimmer.cycle_time_us * (1023 - ac_zero_cross_power(ac_zero_cross_dimmer.lastlight[i]))) / 1023;
+
+#ifdef ESP32
+ if (ac_zero_cross_dimmer.detailpower[i]){
+ float state = (float)(1 - (ac_zero_cross_dimmer.detailpower[i]/10000.0));
+ //state = std::acos(1 - (2 * state)) / 3.14159 * ac_zero_cross_dimmer.cycle_time_us;
+ state = std::acos(1 - (2 * state)) / 3.14159 * 10000;
+ //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("ZCD: Float2: %*_f"),0,&state);
+ ac_zero_cross_dimmer.enable_time_us[i] = (uint32_t)state;
+ ac_zero_cross_dimmer.lastlight[i] = 1;
+ }
+#endif
+
+ ac_zero_cross_dimmer.disable_time_us[i] = ac_zero_cross_dimmer.enable_time_us[i] + GATE_ENABLE_TIME;
+ }
+
+}
+
+void ACDimmerLogging(void)
+{
+ bool alarmEnabled = false;
+ uint32_t timercounter = ac_zero_cross_dimmer.intr_counter;
+
+#ifdef ESP32
+ if (dimmer_timer != nullptr) {
+ alarmEnabled = timerAlarmEnabled(dimmer_timer);
+ timercounter = (uint32_t)timerRead(dimmer_timer);
+ }
+#endif
+
+ AddLog(LOG_LEVEL_DEBUG, PSTR("ZCD: ZeroEnable %d -> %d, Alarm %d, intr: %ld, cycle time: %ld µs"),
+ ac_zero_cross_dimmer.dimmer_in_use, ac_zero_cross_dimmer.timer_iterrupt_started, alarmEnabled, timercounter, ac_zero_cross_dimmer.cycle_time_us
+ );
+ for (uint8_t i = 0; i < MAX_PWMS; i++){
+ if (Pin(GPIO_PWM1, i) == -1) continue;
+ AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("ZCD: PWM[%d] en: %ld µs, dis: %ld µs, state %d, fade: %d, cur: %d, end: %d, lastlight: %d"),
+ i+1, ac_zero_cross_dimmer.enable_time_us[i], ac_zero_cross_dimmer.disable_time_us[i],
+ ac_zero_cross_dimmer.current_state_in_phase[i], Light.fade_cur_10[i], Light.fade_start_10[i], Light.fade_end_10[i], ac_zero_cross_dimmer.lastlight[i]
+ );
+ }
+
+}
+
+
+/*********************************************************************************************\
+ * Commands
+\*********************************************************************************************/
+
+void CmndZCDimmerSet(void)
+{
+ if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_PWMS)) {
+ if (XdrvMailbox.data_len > 0) {
+ ac_zero_cross_dimmer.detailpower[XdrvMailbox.index-1] = (uint16_t)(100 * CharToFloat(XdrvMailbox.data));
+ }
+ ResponseCmndIdxFloat((float)(ac_zero_cross_dimmer.detailpower[XdrvMailbox.index-1]) / 100, 2);
+ }
+}
+
+/*********************************************************************************************\
+ * Interface
+\*********************************************************************************************/
+
+bool Xdrv68(uint32_t function)
+{
+ bool result = false;
+ if (Settings->flag4.zerocross_dimmer) {
+ switch (function) {
+ case FUNC_INIT:
+#ifdef ESP32
+ //ACDimmerInterruptDisable(false);
+#endif
+#ifdef ESP8266
+ setTimer1Callback(&ACDimmerTimer_intr_ESP8266);
+#endif
+ break;
+ case FUNC_EVERY_SECOND:
+ ACDimmerLogging();
+ break;
+ case FUNC_EVERY_100_MSECOND:
+ ACDimmerControllTrigger();
+ break;
+ case FUNC_INTERRUPT_STOP:
+ AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("ZCD: FUNC_INTERRUPT_STOP"));
+ ACDimmerInterruptDisable(true);
+ break;
+ case FUNC_INTERRUPT_START:
+ AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("ZCD: FUNC_INTERRUPT_START"));
+ ACDimmerInterruptDisable(false);
+ break;
+ case FUNC_COMMAND:
+ result = DecodeCommand(kZCDimmerCommands, ZCDimmerCommand);
+ //result = DecodeCommand(kShutterCommands, ShutterCommand);
+
+ break;
+ }
+ }
+ return result;
+}
+
+#endif // USE_AC_ZERO_CROSS_DIMMER
diff --git a/tasmota/tasmota_xsns_sensor/xsns_01_counter.ino b/tasmota/tasmota_xsns_sensor/xsns_01_counter.ino
index d427cc7db..b23870503 100644
--- a/tasmota/tasmota_xsns_sensor/xsns_01_counter.ino
+++ b/tasmota/tasmota_xsns_sensor/xsns_01_counter.ino
@@ -2,7 +2,6 @@
xsns_01_counter.ino - Counter sensors (water meters, electricity meters etc.) sensor support for Tasmota
Copyright (C) 2021 Maarten Damen and Theo Arends
- Stefan Bode (Zero-Cross Dimmer)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -48,22 +47,6 @@ struct COUNTER {
} Counter;
-#ifdef USE_AC_ZERO_CROSS_DIMMER
-struct AC_ZERO_CROSS_DIMMER {
- bool startReSync = false; // set to TRUE if zero-cross event occurs
- bool startMeasurePhase[MAX_COUNTERS] ; // set to TRUE if channel is ON and zero-cross occurs to initiate phase measure on channel
- bool pwm_defined[MAX_COUNTERS]; // check if all GPIO are set and zerocross enabled. Then ADD dimmer.
- bool PWM_ON[MAX_COUNTERS] ; // internal ON/OFF of the channel
- uint32_t current_cycle_ClockCycles = 0; // amount of clock cycles between two zero-cross events.
- uint32_t currentPWMCycleCount[MAX_COUNTERS] ; // clock cycle time of PWM channel, required to measure actual phase. [3] is phase of zero-cross
- int16_t currentShiftClockCycle[MAX_COUNTERS]; // dynamic phase correction per channel in clock cycles
- uint32_t tobe_cycle_timeClockCycles = 0; // clock cycles between zero-cross events. Depend on main frequency and CPU speed
- uint32_t lastCycleCount = 0; // Last value of GetCycleCount during zero-cross sychronisation
- uint32_t currentSteps = 100; // dynamic value of zero-crosses between two sychronisation intervalls (default=20 == 200ms at 100Hz)
- uint32_t high; // cycle counts for PWM high vaule. needs long enough (4µs) to secure fire TRIAC
-} ac_zero_cross_dimmer;
-#endif //USE_AC_ZERO_CROSS_DIMMER
-
void IRAM_ATTR CounterIsrArg(void *arg) {
uint32_t index = *static_cast(arg);
@@ -93,27 +76,7 @@ void IRAM_ATTR CounterIsrArg(void *arg) {
// restart PWM each second (german 50Hz has to up to 0.01% deviation)
// restart initiated by setting Counter.startReSync = true;
#ifdef USE_AC_ZERO_CROSS_DIMMER
- // if zero-cross events occur ond channel is on. phase on PWM must be measured
- if ( ac_zero_cross_dimmer.startMeasurePhase[index] == true ) {
- ac_zero_cross_dimmer.currentPWMCycleCount[index] = ESP.getCycleCount();
- ac_zero_cross_dimmer.startMeasurePhase[index] = false;
- }
- // if zero-cross event occurs (200ms window, 5-times a second) and device is online for >10sec
- if (index == 3 && RtcSettings.pulse_counter[index]%(Settings->pwm_frequency / 5) == 0 && ac_zero_cross_dimmer.pwm_defined[index] && millis() > 10000) {
- ac_zero_cross_dimmer.currentPWMCycleCount[index] = ESP.getCycleCount();
-
- if (ac_zero_cross_dimmer.lastCycleCount > 0) {
- // start phase measure on PWM channels and initiate phase sync with zero-cross.
- ac_zero_cross_dimmer.startReSync = true;
- for (uint8_t k=0; k < MAX_COUNTERS-1; k++ ) {
- if (ac_zero_cross_dimmer.PWM_ON[k] == true) ac_zero_cross_dimmer.startMeasurePhase[k] = true;
- }
- ac_zero_cross_dimmer.currentSteps = (ac_zero_cross_dimmer.currentPWMCycleCount[index]-ac_zero_cross_dimmer.lastCycleCount+(ac_zero_cross_dimmer.tobe_cycle_timeClockCycles/2))/(ac_zero_cross_dimmer.tobe_cycle_timeClockCycles);
- ac_zero_cross_dimmer.current_cycle_ClockCycles = (ac_zero_cross_dimmer.currentPWMCycleCount[index]-ac_zero_cross_dimmer.lastCycleCount)/ac_zero_cross_dimmer.currentSteps;
- }
- ac_zero_cross_dimmer.lastCycleCount = ac_zero_cross_dimmer.currentPWMCycleCount[index];
- }
-
+ if (index == 3) ACDimmerZeroCross(time);
#endif //USE_AC_ZERO_CROSS_DIMMER
return;
}
@@ -162,26 +125,9 @@ bool CounterPinState(void)
void CounterInit(void)
{
+
for (uint32_t i = 0; i < MAX_COUNTERS; i++) {
if (PinUsed(GPIO_CNTR1, i)) {
-#ifdef USE_AC_ZERO_CROSS_DIMMER
- if (Settings->flag4.zerocross_dimmer) {
- ac_zero_cross_dimmer.current_cycle_ClockCycles = ac_zero_cross_dimmer.tobe_cycle_timeClockCycles = microsecondsToClockCycles(1000000 / Settings->pwm_frequency);
- // short fire on PWM to ensure not to hit next sinus curve but trigger the TRIAC. 0.78% of duty cycle (10ms) ~4µs
- ac_zero_cross_dimmer.high = ac_zero_cross_dimmer.current_cycle_ClockCycles / 256;
-
- // Support for dimmer 1-3. Counter4 reseverd for zero-cross signal
- if ((i < MAX_COUNTERS-1 && PinUsed(GPIO_PWM1, i)) || ( i == MAX_COUNTERS-1) ) {
- ac_zero_cross_dimmer.pwm_defined[i] = true;
- if (i == 3) {
- AddLog(LOG_LEVEL_INFO, PSTR("ZeroCross initialized"));
- } else {
- AddLog(LOG_LEVEL_INFO, PSTR("Dimmer: [%d] initialized. READY. Dimmer %d"), i+1, Light.fade_running ? Light.fade_cur_10[i] : Light.fade_start_10[i]);
- }
-
- }
- }
-#endif //USE_AC_ZERO_CROSS_DIMMER
Counter.any_counter = true;
pinMode(Pin(GPIO_CNTR1, i), bitRead(Counter.no_pullup, i) ? INPUT : INPUT_PULLUP);
if ((0 == Settings->pulse_counter_debounce_low) && (0 == Settings->pulse_counter_debounce_high) && !Settings->flag4.zerocross_dimmer) {
@@ -260,78 +206,6 @@ void CounterShow(bool json)
}
}
-#ifdef USE_AC_ZERO_CROSS_DIMMER
-void SyncACDimmer(void)
-{
- if (ac_zero_cross_dimmer.startReSync ) {
- // currently only support one AC Dimmer PWM. Plan to support up to 4 Dimmer on same Phase.
- for (uint32_t i = 0; i < MAX_COUNTERS-1; i++) {
- if (Light.fade_start_10[i] == 0 && Light.fade_cur_10[i] == 0 && ac_zero_cross_dimmer.PWM_ON[i]==false ) continue;
- if (ac_zero_cross_dimmer.pwm_defined[i] && (ac_zero_cross_dimmer.startMeasurePhase[i] == 0 || ac_zero_cross_dimmer.PWM_ON[i] == false ) )
- {
- uint32_t phaseStart_ActualClockCycles; // As-Is positon of PWM after Zero Cross
- uint32_t phaseStart_ToBeClockCycles; // To be position after zero-cross to fire PWM start
- int16_t phaseShift_ClockCycles; //
-
-
- // reset trigger for PWM sync
- ac_zero_cross_dimmer.startReSync = false;
- // calculate timeoffset to fire PWM based on Dimmer
- phaseStart_ToBeClockCycles = (ac_zero_cross_dimmer.tobe_cycle_timeClockCycles * (1024 - ac_zero_cross_power(Light.fade_running ? Light.fade_cur_10[i] : Light.fade_start_10[i]))) / 1024;
-
- // Limit range to avoid overshoot and undershoot
- phaseStart_ToBeClockCycles = tmin(tmax(phaseStart_ToBeClockCycles, 160000), 0.95* ac_zero_cross_dimmer.tobe_cycle_timeClockCycles);
-
- // Switch OFF dimmer
- if (Light.fade_start_10[i] == 0 && !Light.fade_running) {
- ac_zero_cross_dimmer.PWM_ON[i]=false;
- Light.fade_cur_10[i] = 0;
- digitalWrite(Pin(GPIO_PWM1, i), LOW);
- //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("CNT2: [%d], curr: %d, final: %d, fading: %d, phase-shift: %d, ON/OFF: %d"),i, Light.fade_cur_10[i], Light.fade_start_10[i], Light.fade_running, phaseStart_ToBeClockCycles,ac_zero_cross_dimmer.PWM_ON[i]);
- continue;
- }
- // Calculyte clockcycles between zero-cross [3] and start of the current PWM signal [i]
- phaseStart_ActualClockCycles = ac_zero_cross_dimmer.currentPWMCycleCount[i]-ac_zero_cross_dimmer.currentPWMCycleCount[3];
-
- // Calulate additional or less clockcycles to move current phase position to should be position
- phaseShift_ClockCycles = (int32_t)((int32_t)phaseStart_ToBeClockCycles-(int32_t)phaseStart_ActualClockCycles)/100;
-
- if ( ac_zero_cross_dimmer.PWM_ON[i] == 0 ) {
- // because in LOOP calculate the timelag to fire PWM correctly with zero-cross
- uint32_t timelag_ClockCycles = (ESP.getCycleCount() - ac_zero_cross_dimmer.currentPWMCycleCount[3])%ac_zero_cross_dimmer.tobe_cycle_timeClockCycles;
- timelag_ClockCycles = ((phaseStart_ToBeClockCycles + ac_zero_cross_dimmer.tobe_cycle_timeClockCycles) - timelag_ClockCycles)%ac_zero_cross_dimmer.tobe_cycle_timeClockCycles;
-
- delayMicroseconds(clockCyclesToMicroseconds(timelag_ClockCycles));
- ac_zero_cross_dimmer.PWM_ON[i]=true;
- pinMode(Pin(GPIO_PWM1, i), OUTPUT);
- } else {
- // currentShiftClockCycle is an I-Controller (not PID) to realign the phase. grace time are 5 clock cycles
- ac_zero_cross_dimmer.currentShiftClockCycle[i] += phaseShift_ClockCycles > 5 ? 1 : (phaseShift_ClockCycles < -5 ? -1 : 0);
- ac_zero_cross_dimmer.current_cycle_ClockCycles += ac_zero_cross_dimmer.currentShiftClockCycle[i]+phaseShift_ClockCycles;
- }
-#ifdef ESP8266
- // Find the first GPIO being generated by checking GCC's find-first-set (returns 1 + the bit of the first 1 in an int32_t
- startWaveformClockCycles(Pin(GPIO_PWM1, i), ac_zero_cross_dimmer.high, ac_zero_cross_dimmer.current_cycle_ClockCycles - ac_zero_cross_dimmer.high, 0, -1, 0, true);
-#endif // ESP8266
-#ifdef ESP32
- // Under investigation. Still not working
- double esp32freq = 1000000.0 / clockCyclesToMicroseconds(ac_zero_cross_dimmer.current_cycle_ClockCycles);
- ledcSetup(i, esp32freq, 10);
- ledcAttachPin(Pin(GPIO_PWM1, i), i);
- ledcWrite(i, 5);
-
-#endif // ESP32
-
- AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("CNT: [%d], shift: %d, dimm_time_CCs %d, phaseShift_CCs %d, currentPWMcylce: %lu, current_cycle_CC: %lu, lastcc %lu, currentSteps %lu, currDIM %lu, last delta:%lu"),
- i, ac_zero_cross_dimmer.currentShiftClockCycle[i], phaseStart_ToBeClockCycles,phaseShift_ClockCycles,ac_zero_cross_dimmer.currentPWMCycleCount[i],ac_zero_cross_dimmer.current_cycle_ClockCycles , ac_zero_cross_dimmer.lastCycleCount, ac_zero_cross_dimmer.currentSteps, Light.fade_cur_10[i],phaseStart_ActualClockCycles); // Light fading
- //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("CNT: [%d], curr: %d, final: %d, fading: %d, phase-shift: %d, ON/OFF: %d"),i, Light.fade_cur_10[i], Light.fade_start_10[i], Light.fade_running, phaseStart_ToBeClockCycles,ac_zero_cross_dimmer.PWM_ON[i]);
-
- } // do sync onchannel
- } // loop on counter
- } // zero cross detected
-} // end SyncACDimmer
-#endif //USE_AC_ZERO_CROSS_DIMMER
-
/*********************************************************************************************\
* Commands
\*********************************************************************************************/
@@ -406,11 +280,6 @@ bool Xsns01(uint32_t function)
case FUNC_JSON_APPEND:
CounterShow(1);
break;
-#ifdef USE_AC_ZERO_CROSS_DIMMER
- case FUNC_EVERY_50_MSECOND:
- SyncACDimmer();
- break;
-#endif //USE_AC_ZERO_CROSS_DIMMER
#ifdef USE_WEBSERVER
case FUNC_WEB_SENSOR:
CounterShow(0);