mirror of https://github.com/arendst/Tasmota.git
Enhance ZC-Dimmer for falling and leading edge dimmer (#19054)
* Update tasmota_types.h * Update xdrv_68_zerocrossDimmer.ino
This commit is contained in:
parent
5c9c4e6dad
commit
8ce7cb4ccd
|
@ -188,7 +188,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
|
|||
uint32_t bistable_single_pin : 1; // bit 6 (v12.5.0.1) - SetOption152 - (Power) Switch between two (0) or one (1) pin bistable relay control
|
||||
uint32_t berry_no_autoexec : 1; // bit 7 (v12.5.0.3) - SetOption153 - (Berry) Disable autoexec.be on restart (1)
|
||||
uint32_t berry_light_scheme : 1; // bit 8 (v12.5.0.3) - SetOption154 - (Berry) Handle berry led using RMT0 as additional WS2812 scheme
|
||||
uint32_t spare09 : 1; // bit 9
|
||||
uint32_t zcfallingedge : 1; // bit 9 (v12.5.0.4) - SetOption155 - ZC Dimmer enable rare falling Edge dimmer instead of leading edge
|
||||
uint32_t spare10 : 1; // bit 10
|
||||
uint32_t spare11 : 1; // bit 11
|
||||
uint32_t spare12 : 1; // bit 12
|
||||
|
@ -778,8 +778,9 @@ typedef struct {
|
|||
int8_t temp_comp; // E9E
|
||||
uint8_t weight_change; // E9F
|
||||
uint8_t web_color2[2][3]; // EA0 Needs to be on integer / 3 distance from web_color
|
||||
uint16_t zcdimmerset[5]; // EA6
|
||||
|
||||
uint8_t free_ea6[32]; // EA6
|
||||
uint8_t free_eb0[22]; // EB0 22 bytes
|
||||
|
||||
uint8_t shift595_device_count; // EC6
|
||||
uint8_t sta_config; // EC7
|
||||
|
|
|
@ -24,9 +24,6 @@
|
|||
|
||||
#define XDRV_68 68
|
||||
|
||||
static const uint8_t GATE_ENABLE_TIME = 100;
|
||||
static const uint8_t MIN_PERCENT = 5;
|
||||
static const uint8_t MAX_PERCENT = 99;
|
||||
static const uint8_t TRIGGER_PERIOD = 75;
|
||||
|
||||
#define ZCDIMMERSET_SHOW 1
|
||||
|
@ -37,13 +34,11 @@ struct AC_ZERO_CROSS_DIMMER {
|
|||
uint32_t crossed_zero_at; // Time (in micros()) of last ZC signal
|
||||
bool timer_iterrupt_started = false; // verification of the interrupt running
|
||||
bool dimmer_in_use = false; // Check if interrupt has to be run. Is stopped if all lights off
|
||||
bool fallingEdgeDimmer = false; // Work as a fallwing edge dimmer
|
||||
uint32_t enable_time_us[MAX_PWMS]; // Time since last ZC pulse to enable gate pin. 0 means no disable.
|
||||
uint32_t disable_time_us[MAX_PWMS]; // Time since last ZC pulse to disable gate pin. 0 means no disable.
|
||||
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]; // Store the light value. Set 1 if controlled through ZCDimmerSet
|
||||
uint16_t detailpower[MAX_PWMS]; // replaces dimmer and light controll 0..10000. required savedata 0.
|
||||
uint32_t accurracy[MAX_PWMS]; // offset of the time to fire the triac and the real time when it fired
|
||||
uint8_t triggertime = GATE_ENABLE_TIME; // copy of the Time for the gate keep open to start TRIAC
|
||||
uint32_t intr_counter = 0; // counter internally on interrerupt calls
|
||||
uint32_t missed_zero_cross; // count up all missed Zero-cross events.
|
||||
uint8_t actual_tigger_Period = TRIGGER_PERIOD; // copy of tigger period to change during runtime
|
||||
|
@ -70,17 +65,8 @@ void IRAM_ATTR ACDimmerZeroCross(uint32_t time) {
|
|||
ac_zero_cross_dimmer.crossed_zero_at = time;
|
||||
for (uint8_t i=0; i < MAX_PWMS; i++) {
|
||||
if (Pin(GPIO_PWM1, i) == -1) continue;
|
||||
digitalWrite(Pin(GPIO_PWM1, i), LOW ^ ac_zero_cross_dimmer.fallingEdgeDimmer);
|
||||
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] > MAX_PERCENT * 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] < MIN_PERCENT * ac_zero_cross_dimmer.cycle_time_us) {
|
||||
ac_zero_cross_dimmer.current_state_in_phase[i] = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,6 +76,14 @@ uint32_t IRAM_ATTR ACDimmerTimer_intr_ESP8266() {
|
|||
return ac_zero_cross_dimmer.actual_tigger_Period * 80;
|
||||
}
|
||||
|
||||
void ACDimmerInit()
|
||||
{
|
||||
for (uint8_t i = 0 ; i < 5; i++) {
|
||||
ac_zero_cross_dimmer.detailpower[i] = Settings->zcdimmerset[i];
|
||||
ac_zero_cross_dimmer.fallingEdgeDimmer = Settings->flag6.zcfallingedge;
|
||||
}
|
||||
}
|
||||
|
||||
void ACDimmerInterruptDisable(bool disable)
|
||||
{
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("ZCD: Zero-CrossDimmer enabled: %d"),!disable);
|
||||
|
@ -133,7 +127,6 @@ void IRAM_ATTR ACDimmerTimer_intr() {
|
|||
ac_zero_cross_dimmer.intr_counter++;
|
||||
// Check for missed Zero-Cross event. Single failure will correct
|
||||
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;
|
||||
ac_zero_cross_dimmer.missed_zero_cross++;
|
||||
time_since_zc += ac_zero_cross_dimmer.cycle_time_us;
|
||||
|
@ -142,37 +135,25 @@ void IRAM_ATTR ACDimmerTimer_intr() {
|
|||
ac_zero_cross_dimmer.actual_tigger_Period = TRIGGER_PERIOD;
|
||||
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:
|
||||
// Switch off does not need high accuracy. Happens at the next 75µs trigger
|
||||
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 + TRIGGER_PERIOD >= ac_zero_cross_dimmer.enable_time_us[i]){
|
||||
// Very close to the fire event. Loop the last µseconds to wait.
|
||||
|
||||
if (time_since_zc + TRIGGER_PERIOD >= ac_zero_cross_dimmer.enable_time_us[i]){
|
||||
// Very close to the fire event. Loop the last µseconds to wait.
|
||||
#ifdef ESP8266
|
||||
// on ESP8266 we can change dynamically the trigger interval
|
||||
ac_zero_cross_dimmer.actual_tigger_Period = tmin(ac_zero_cross_dimmer.actual_tigger_Period,tmax(5,ac_zero_cross_dimmer.enable_time_us[i] - time_since_zc));
|
||||
// on ESP8266 we can change dynamically the trigger interval
|
||||
ac_zero_cross_dimmer.actual_tigger_Period = tmin(ac_zero_cross_dimmer.actual_tigger_Period,tmax(5,ac_zero_cross_dimmer.enable_time_us[i] - time_since_zc));
|
||||
#endif
|
||||
#ifdef ESP32
|
||||
while (time_since_zc < ac_zero_cross_dimmer.enable_time_us[i]) {
|
||||
time_since_zc = micros() - ac_zero_cross_dimmer.crossed_zero_at;
|
||||
}
|
||||
while (time_since_zc < ac_zero_cross_dimmer.enable_time_us[i]) {
|
||||
time_since_zc = micros() - ac_zero_cross_dimmer.crossed_zero_at;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
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]++;
|
||||
#ifdef ZC_DEBUG
|
||||
ac_zero_cross_dimmer.accurracy[i] = time_since_zc-ac_zero_cross_dimmer.enable_time_us[i];
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (time_since_zc >= ac_zero_cross_dimmer.enable_time_us[i]) {
|
||||
digitalWrite(Pin(GPIO_PWM1, i), HIGH ^ ac_zero_cross_dimmer.fallingEdgeDimmer );
|
||||
#ifdef ZC_DEBUG
|
||||
ac_zero_cross_dimmer.accurracy[i] = time_since_zc-ac_zero_cross_dimmer.enable_time_us[i];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -202,8 +183,6 @@ void ACDimmerControllTrigger(void) {
|
|||
ac_zero_cross_dimmer.enable_time_us[i] = (uint32_t)state;
|
||||
}
|
||||
#endif
|
||||
|
||||
ac_zero_cross_dimmer.disable_time_us[i] = ac_zero_cross_dimmer.enable_time_us[i] + ac_zero_cross_dimmer.triggertime;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -226,9 +205,9 @@ void ACDimmerLogging(void)
|
|||
);
|
||||
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, acc: %ld"),
|
||||
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],
|
||||
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("ZCD: PWM[%d] en: %ld µs, fade: %d, cur: %d, end: %d, lastlight: %d, acc: %ld"),
|
||||
i+1, ac_zero_cross_dimmer.enable_time_us[i],
|
||||
Light.fade_cur_10[i], Light.fade_start_10[i], Light.fade_end_10[i], ac_zero_cross_dimmer.lastlight[i],
|
||||
ac_zero_cross_dimmer.accurracy[i]
|
||||
);
|
||||
}
|
||||
|
@ -258,20 +237,12 @@ 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));
|
||||
Settings->zcdimmerset[XdrvMailbox.index-1] = 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);
|
||||
}
|
||||
}
|
||||
|
||||
/* void CmndZCGateEnableTime(void)
|
||||
{
|
||||
if (XdrvMailbox.payload > 0) {
|
||||
ac_zero_cross_dimmer.triggertime = XdrvMailbox.payload;
|
||||
}
|
||||
ResponseCmndNumber(ac_zero_cross_dimmer.triggertime);
|
||||
} */
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
@ -282,6 +253,7 @@ bool Xdrv68(uint32_t function)
|
|||
if (Settings->flag4.zerocross_dimmer) {
|
||||
switch (function) {
|
||||
case FUNC_INIT:
|
||||
ACDimmerInit();
|
||||
#ifdef ESP32
|
||||
//ACDimmerInterruptDisable(false);
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue