diff --git a/HermitCrab.h b/HermitCrab.h index 00259d9..6d4a8d6 100644 --- a/HermitCrab.h +++ b/HermitCrab.h @@ -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 diff --git a/HermitCrab.ino b/HermitCrab.ino index 5ca5ed5..aa75daf 100644 --- a/HermitCrab.ino +++ b/HermitCrab.ino @@ -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,29 +56,31 @@ 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 + // Every Second if (tickSecond != lastTickSecond) { lastTickSecond = tickSecond; // Time and ZCD - setACLoadStatus(tNow); setTime(); // Temperature and Humidity diff --git a/OTA.cpp b/OTA.cpp index 2ccceaa..6c8a6b5 100644 --- a/OTA.cpp +++ b/OTA.cpp @@ -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"; diff --git a/Setup.cpp b/Setup.cpp index c55390f..02314a3 100644 --- a/Setup.cpp +++ b/Setup.cpp @@ -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; diff --git a/zcd.cpp b/zcd.cpp index d46b2ec..d14f511 100644 --- a/zcd.cpp +++ b/zcd.cpp @@ -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; + + // Fire + gpio_set_level((gpio_num_t)PIN_HEATER1, 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; - } - } + // 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; + + // 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; } - // 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; + // Heater 2 Cease-Fire 체크 + if (fireStatusTimer1 && (tNow - fireTriggerTime1 >= 8)) { + gpio_set_level((gpio_num_t)PIN_HEATER2, 0); + fireStatusTimer1 = 0; } } \ No newline at end of file diff --git a/zcd.h b/zcd.h index 222dedc..45162b9 100644 --- a/zcd.h +++ b/zcd.h @@ -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)