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
extern STATUS_TYPE status;
// Time
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 *HC__VERSION;
extern volatile uint32_t g_millis;
#endif

View File

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

View File

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

View File

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

116
zcd.cpp
View File

@ -44,6 +44,8 @@ volatile uint8_t ac2ControlMode;
volatile uint8_t fireStatusTimer0;
volatile uint8_t fireStatusTimer1;
volatile uint64_t fireTriggerTime0;
volatile uint64_t fireTriggerTime1;
timg_dev_t *tg0;
timg_dev_t *tg1;
@ -172,49 +174,26 @@ MY_IRAM_ATTR void setHeater2Duty(short duty) {
}
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;
if (fire_enable_1) {
if (fireStatusTimer0 == 0) {
gpio_set_level((gpio_num_t)PIN_HEATER1, 1);
fireStatusTimer0 = 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);
// Fire
gpio_set_level((gpio_num_t)PIN_HEATER1, 1);
// Suspend Timer until next zcdACISR
fire_enable_1 = false;
}
}
// Record Fire Status
fireStatusTimer0 = 1;
fireTriggerTime0 = (uint64_t)timer_ll_get_counter_value(tg0, 1);
}
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;
if (fire_enable_2) {
if (fireStatusTimer1 == 0) {
gpio_set_level((gpio_num_t)PIN_HEATER2, 1);
fireStatusTimer1 = 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);
// Fire
gpio_set_level((gpio_num_t)PIN_HEATER2, 1);
// Suspend Timer until next zcdACISR
fire_enable_2 = false;
}
}
// Record Fire Status
fireStatusTimer1 = 1;
fireTriggerTime1 = (uint64_t)timer_ll_get_counter_value(tg0, 1);
}
// Zero-Cross Detection Interrupt Service Routine
@ -222,6 +201,9 @@ void IRAM_ATTR zcdACISR(void *) {
// 1. Power side AC ZCD Count
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;
fireStatusTimer1 = 0;
@ -231,13 +213,12 @@ void IRAM_ATTR zcdACISR(void *) {
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(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_alarm_value(TIMER_GROUP_1, TIMER_0, (uint64_t) dutyHeater1);
timer_set_alarm(TIMER_GROUP_1, TIMER_0, TIMER_ALARM_EN);
fire_enable_1 = true;
}
// 4. Heater 2
@ -246,13 +227,12 @@ void IRAM_ATTR zcdACISR(void *) {
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(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_alarm_value(TIMER_GROUP_1, TIMER_1, (uint64_t)dutyHeater2);
timer_set_alarm(TIMER_GROUP_1, TIMER_1, TIMER_ALARM_EN);
fire_enable_2 = true;
}
seqStep = (seqStep + 1) & 0x0F;
}
@ -285,37 +265,47 @@ void setupZCD() {
ac2ControlMode = config.ac2ControlMode;
}
void setACLoadStatus(uint32_t tNow) {
static uint32_t lastTick = 0;
void setACLoadStatus(uint64_t tNow) {
static uint64_t lastTick = 0;
//static uint64_t lastNonZero = 0;
// --- 1. Process AC/Load Window (Every 1s) ---
if (tNow - lastTick >= 10000) {
if (tNow - lastTick >= 1000000) {
zcdACCount = zcdACISRCount;
zcdLoadCount = zcdLoadISRCount;
zcdACISRCount = 0;
zcdLoadISRCount = 0;
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
status.zcdAC = zcdACCount;
status.zcdLoad = zcdLoadCount;
if (status.zcdAC < 119 || status.zcdAC > 121) {
status.nFlags |= FLAG_ZCD_AC;
}
else {
status.nFlags &= ~FLAG_ZCD_AC;
}
if (status.zcdLoad < 6 || status.zcdLoad > 181) {
status.nFlags |= FLAG_ZCD_LOAD;
}
else {
status.nFlags &= ~FLAG_ZCD_LOAD;
// ZCD
status.zcdAC = zcdACCount;
status.zcdLoad = zcdLoadCount;
if (status.zcdAC < 118 || status.zcdAC > 122) {
status.nFlags |= FLAG_ZCD_AC;
}
else {
status.nFlags &= ~FLAG_ZCD_AC;
}
if (status.zcdLoad < 118 || status.zcdLoad > 122) {
status.nFlags |= FLAG_ZCD_LOAD;
}
else {
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();
void setHeater1Duty(short duty);
void setHeater2Duty(short duty);
void ceaseFire(uint32_t now);
void zcdACISR(void *);
void zcdLoadISR(void *);
void timer0ISR(void *);
void timer1ISR(void *);
void ceaseFire(uint64_t tNow);
void setACLoadStatus(uint64_t tNow);
//#define DEBUG_ZCD
#if defined(ESP8266)