ZCD correction

This commit is contained in:
Heuideog Yi @ PC RnD1 2026-05-01 16:49:55 +09:00
parent 95cbe9f950
commit b187b66ed6
6 changed files with 73 additions and 78 deletions

View File

@ -232,7 +232,6 @@ void core0Task(void *pvParameters);
// Status // Status
extern STATUS_TYPE status; extern STATUS_TYPE status;
// Time // Time
extern volatile unsigned short g_nYear, g_nMonth, g_nDay, g_nHour, g_nMinute, g_nSecond; extern volatile unsigned short g_nYear, g_nMonth, g_nDay, g_nHour, g_nMinute, g_nSecond;
@ -242,4 +241,5 @@ extern const char *COMPANY_NAME;
extern const char *SERVICE_NAME; extern const char *SERVICE_NAME;
extern const char *HC__VERSION; extern const char *HC__VERSION;
extern volatile uint32_t g_millis; extern volatile uint32_t g_millis;
#endif #endif

View File

@ -48,7 +48,6 @@ void controlLight(short hour, short min, unsigned long tick);
void controlFanDuty(); void controlFanDuty();
void controlMotorDuty(); void controlMotorDuty();
void controlLightDuty(); void controlLightDuty();
void setACLoadStatus(uint32_t tNow);
// ================================================================================== // ==================================================================================
@ -57,20 +56,23 @@ void setACLoadStatus(uint32_t tNow);
// //
// ================================================================================== // ==================================================================================
MY_IRAM_ATTR void loop() { MY_IRAM_ATTR void loop() {
static unsigned long lastTickSecond = 0; static uint32_t lastTickSecond = 0;
static uint8_t lastSecond = -1; static uint8_t lastSecond = -1;
// Read timer from TG0-Timer0 // Read timer from TG0-Timer1 (1MHz)
tg0->hw_timer[1].update.val = 1; tg0->hw_timer[1].update.val = 1;
uint32_t tNow = (uint32_t)timer_ll_get_counter_value(tg0, 1); uint64_t g_microsec = (uint64_t)timer_ll_get_counter_value(tg0, 1);
g_millis = (uint32_t) (g_microsec / 1000);
g_millis = (uint32_t) (tNow / 10); uint32_t tickSecond = g_microsec / 1000000;
unsigned long tickMillis = g_millis;
unsigned long tickSecond = tickMillis / 1000;
// Un-Conditional Loop // Un-Conditional Loop
{ {
ui.loopButton(tickMillis); // Cease-Fire on Heater Triac's
ceaseFire(g_microsec);
setACLoadStatus(g_microsec);
ui.loopButton(g_millis);
} }
// Every Second // Every Second
@ -79,7 +81,6 @@ MY_IRAM_ATTR void loop() {
lastTickSecond = tickSecond; lastTickSecond = tickSecond;
// Time and ZCD // Time and ZCD
setACLoadStatus(tNow);
setTime(); setTime();
// Temperature and Humidity // Temperature and Humidity

View File

@ -17,7 +17,7 @@
// OTA // OTA
// //
// ============================================================== // ==============================================================
const char *HC__VERSION = "20260424001"; const char *HC__VERSION = "20260501005";
#define UPDATE_PORT ((uint16_t) 443) #define UPDATE_PORT ((uint16_t) 443)
const char *url = "visionsoft.kr"; const char *url = "visionsoft.kr";
const char *uri = "/sc/pages/firmware_download.php"; const char *uri = "/sc/pages/firmware_download.php";

View File

@ -200,7 +200,7 @@ void setupTimers() {
.intr_type = TIMER_INTR_LEVEL, .intr_type = TIMER_INTR_LEVEL,
.counter_dir = TIMER_COUNT_UP, .counter_dir = TIMER_COUNT_UP,
.auto_reload = (timer_autoreload_t) TIMER_AUTORELOAD_DIS, .auto_reload = (timer_autoreload_t) TIMER_AUTORELOAD_DIS,
.divider = 8000 // 10KHz (100us tick) .divider = 80 // 10KHz (100us tick)
}; };
esp_err_t err; esp_err_t err;

92
zcd.cpp
View File

@ -44,6 +44,8 @@ volatile uint8_t ac2ControlMode;
volatile uint8_t fireStatusTimer0; volatile uint8_t fireStatusTimer0;
volatile uint8_t fireStatusTimer1; volatile uint8_t fireStatusTimer1;
volatile uint64_t fireTriggerTime0;
volatile uint64_t fireTriggerTime1;
timg_dev_t *tg0; timg_dev_t *tg0;
timg_dev_t *tg1; timg_dev_t *tg1;
@ -172,49 +174,26 @@ MY_IRAM_ATTR void setHeater2Duty(short duty) {
} }
void IRAM_ATTR timer0ISR(void *) { void IRAM_ATTR timer0ISR(void *) {
#ifdef DEBUG_ZCD
zcdLoadISRCount++;
#endif
//timer_group_clr_intr_status_in_isr(TIMER_GROUP_1, TIMER_0);
TIMERG1.int_clr_timers.t0_int_clr = 1; TIMERG1.int_clr_timers.t0_int_clr = 1;
if (fire_enable_1) {
if (fireStatusTimer0 == 0) { // Fire
gpio_set_level((gpio_num_t)PIN_HEATER1, 1); gpio_set_level((gpio_num_t)PIN_HEATER1, 1);
// Record Fire Status
fireStatusTimer0 = 1; fireStatusTimer0 = 1;
fireTriggerTime0 = (uint64_t)timer_ll_get_counter_value(tg0, 1);
// Set next timer
timer_set_counter_value(TIMER_GROUP_1, TIMER_0, 0);
timer_set_alarm_value(TIMER_GROUP_1, TIMER_0, 18);
timer_set_alarm(TIMER_GROUP_1, TIMER_0, TIMER_ALARM_EN);
} else {
gpio_set_level((gpio_num_t)PIN_HEATER1, 0);
// Suspend Timer until next zcdACISR
fire_enable_1 = false;
}
}
} }
void IRAM_ATTR timer1ISR(void *) void IRAM_ATTR timer1ISR(void *)
{ {
//timer_group_clr_intr_status_in_isr(TIMER_GROUP_1, TIMER_1);
TIMERG1.int_clr_timers.t1_int_clr = 1; TIMERG1.int_clr_timers.t1_int_clr = 1;
if (fire_enable_2) {
if (fireStatusTimer1 == 0) { // Fire
gpio_set_level((gpio_num_t)PIN_HEATER2, 1); gpio_set_level((gpio_num_t)PIN_HEATER2, 1);
// Record Fire Status
fireStatusTimer1 = 1; fireStatusTimer1 = 1;
fireTriggerTime1 = (uint64_t)timer_ll_get_counter_value(tg0, 1);
// Set next timer
timer_set_counter_value(TIMER_GROUP_1, TIMER_1, 0);
timer_set_alarm_value(TIMER_GROUP_1, TIMER_1, 18);
timer_set_alarm(TIMER_GROUP_1, TIMER_1, TIMER_ALARM_EN);
} else {
gpio_set_level((gpio_num_t)PIN_HEATER2, 0);
// Suspend Timer until next zcdACISR
fire_enable_2 = false;
}
}
} }
// Zero-Cross Detection Interrupt Service Routine // Zero-Cross Detection Interrupt Service Routine
@ -222,6 +201,9 @@ void IRAM_ATTR zcdACISR(void *) {
// 1. Power side AC ZCD Count // 1. Power side AC ZCD Count
zcdACISRCount = zcdACISRCount + 1; zcdACISRCount = zcdACISRCount + 1;
// 강제 Cease-fire (혹시 루프에서 처리 못했을 경우를 대비)
gpio_set_level((gpio_num_t)PIN_HEATER1, 0);
gpio_set_level((gpio_num_t)PIN_HEATER2, 0);
fireStatusTimer0 = 0; fireStatusTimer0 = 0;
fireStatusTimer1 = 0; fireStatusTimer1 = 0;
@ -231,13 +213,12 @@ void IRAM_ATTR zcdACISR(void *) {
timer_set_counter_value(TIMER_GROUP_1, TIMER_0, 0); timer_set_counter_value(TIMER_GROUP_1, TIMER_0, 0);
timer_set_alarm_value(TIMER_GROUP_1, TIMER_0, (uint64_t) LEADING_ZCD_COUNT); timer_set_alarm_value(TIMER_GROUP_1, TIMER_0, (uint64_t) LEADING_ZCD_COUNT);
timer_set_alarm(TIMER_GROUP_1, TIMER_0, TIMER_ALARM_EN); timer_set_alarm(TIMER_GROUP_1, TIMER_0, TIMER_ALARM_EN);
fire_enable_1 = true;
} }
} else if ( dutyHeater1 >= LEADING_PULSE_COUNT){ } else // PHASE_CONTROL
if ( dutyHeater1 >= LEADING_PULSE_COUNT){
timer_set_counter_value(TIMER_GROUP_1, TIMER_0, 0); timer_set_counter_value(TIMER_GROUP_1, TIMER_0, 0);
timer_set_alarm_value(TIMER_GROUP_1, TIMER_0, (uint64_t) dutyHeater1); timer_set_alarm_value(TIMER_GROUP_1, TIMER_0, (uint64_t) dutyHeater1);
timer_set_alarm(TIMER_GROUP_1, TIMER_0, TIMER_ALARM_EN); timer_set_alarm(TIMER_GROUP_1, TIMER_0, TIMER_ALARM_EN);
fire_enable_1 = true;
} }
// 4. Heater 2 // 4. Heater 2
@ -246,13 +227,12 @@ void IRAM_ATTR zcdACISR(void *) {
timer_set_counter_value(TIMER_GROUP_1, TIMER_1, 0); timer_set_counter_value(TIMER_GROUP_1, TIMER_1, 0);
timer_set_alarm_value(TIMER_GROUP_1, TIMER_1, (uint64_t)LEADING_ZCD_COUNT); timer_set_alarm_value(TIMER_GROUP_1, TIMER_1, (uint64_t)LEADING_ZCD_COUNT);
timer_set_alarm(TIMER_GROUP_1, TIMER_1, TIMER_ALARM_EN); timer_set_alarm(TIMER_GROUP_1, TIMER_1, TIMER_ALARM_EN);
fire_enable_2 = true;
} }
} else if (dutyHeater2 >= LEADING_PULSE_COUNT) { } else // PHASE_CONTROL
if (dutyHeater2 >= LEADING_PULSE_COUNT) {
timer_set_counter_value(TIMER_GROUP_1, TIMER_1, 0); timer_set_counter_value(TIMER_GROUP_1, TIMER_1, 0);
timer_set_alarm_value(TIMER_GROUP_1, TIMER_1, (uint64_t)dutyHeater2); timer_set_alarm_value(TIMER_GROUP_1, TIMER_1, (uint64_t)dutyHeater2);
timer_set_alarm(TIMER_GROUP_1, TIMER_1, TIMER_ALARM_EN); timer_set_alarm(TIMER_GROUP_1, TIMER_1, TIMER_ALARM_EN);
fire_enable_2 = true;
} }
seqStep = (seqStep + 1) & 0x0F; seqStep = (seqStep + 1) & 0x0F;
} }
@ -285,37 +265,47 @@ void setupZCD() {
ac2ControlMode = config.ac2ControlMode; ac2ControlMode = config.ac2ControlMode;
} }
void setACLoadStatus(uint32_t tNow) { void setACLoadStatus(uint64_t tNow) {
static uint32_t lastTick = 0; static uint64_t lastTick = 0;
//static uint64_t lastNonZero = 0;
// --- 1. Process AC/Load Window (Every 1s) --- // --- 1. Process AC/Load Window (Every 1s) ---
if (tNow - lastTick >= 10000) { if (tNow - lastTick >= 1000000) {
zcdACCount = zcdACISRCount; zcdACCount = zcdACISRCount;
zcdLoadCount = zcdLoadISRCount; zcdLoadCount = zcdLoadISRCount;
zcdACISRCount = 0; zcdACISRCount = 0;
zcdLoadISRCount = 0; zcdLoadISRCount = 0;
lastTick = tNow; lastTick = tNow;
}
// Safety: If no ISR has fired in over 1.5 seconds, force count to 0
if (tNow - lastTick > 15000) {
zcdACCount = 0;
zcdLoadCount = 0;
}
// ZCD // ZCD
status.zcdAC = zcdACCount; status.zcdAC = zcdACCount;
status.zcdLoad = zcdLoadCount; status.zcdLoad = zcdLoadCount;
if (status.zcdAC < 119 || status.zcdAC > 121) { if (status.zcdAC < 118 || status.zcdAC > 122) {
status.nFlags |= FLAG_ZCD_AC; status.nFlags |= FLAG_ZCD_AC;
} }
else { else {
status.nFlags &= ~FLAG_ZCD_AC; status.nFlags &= ~FLAG_ZCD_AC;
} }
if (status.zcdLoad < 6 || status.zcdLoad > 181) { if (status.zcdLoad < 118 || status.zcdLoad > 122) {
status.nFlags |= FLAG_ZCD_LOAD; status.nFlags |= FLAG_ZCD_LOAD;
} }
else { else {
status.nFlags &= ~FLAG_ZCD_LOAD; status.nFlags &= ~FLAG_ZCD_LOAD;
} }
} }
}
void ceaseFire(uint64_t tNow) {
// Heater 1 Cease-Fire 체크
if (fireStatusTimer0 && (tNow - fireTriggerTime0 >= 8)) {
gpio_set_level((gpio_num_t)PIN_HEATER1, 0);
fireStatusTimer0 = 0;
}
// Heater 2 Cease-Fire 체크
if (fireStatusTimer1 && (tNow - fireTriggerTime1 >= 8)) {
gpio_set_level((gpio_num_t)PIN_HEATER2, 0);
fireStatusTimer1 = 0;
}
}

4
zcd.h
View File

@ -6,12 +6,16 @@ void setupZCD();
short getHeater1Duty(); short getHeater1Duty();
void setHeater1Duty(short duty); void setHeater1Duty(short duty);
void setHeater2Duty(short duty); void setHeater2Duty(short duty);
void ceaseFire(uint32_t now);
void zcdACISR(void *); void zcdACISR(void *);
void zcdLoadISR(void *); void zcdLoadISR(void *);
void timer0ISR(void *); void timer0ISR(void *);
void timer1ISR(void *); void timer1ISR(void *);
void ceaseFire(uint64_t tNow);
void setACLoadStatus(uint64_t tNow);
//#define DEBUG_ZCD //#define DEBUG_ZCD
#if defined(ESP8266) #if defined(ESP8266)