ZCD and timers for millis and fire/cease triac trigger
This commit is contained in:
parent
97e9e68d35
commit
1dd537b5d0
3
Config.h
3
Config.h
|
|
@ -92,7 +92,8 @@ typedef struct CONFIG_STRUCT {
|
|||
uint64_t nBLESensorAddr2;
|
||||
uint8_t nBLESensorAddrBytes2[8];
|
||||
};
|
||||
char bExtra[64 - 8 * sizeof(bool) - 4 * sizeof(uint8_t) - 6 * sizeof(float) - sizeof(uint64_t)];
|
||||
uint8_t ac1ControlMode, ac2ControlMode; // ZCD_CONTROL || PHASE_CONTROL
|
||||
char bExtra[64 - 8 * sizeof(bool) - 4 * sizeof(uint8_t) - 6 * sizeof(float) - sizeof(uint64_t) - 2 * sizeof(uint8_t)];
|
||||
|
||||
// Block 2 - Sensor and TargetTemperature and Himidity
|
||||
// Offset 64 + 2
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ void WiFiEvent(WiFiEvent_t event) {
|
|||
case IP_EVENT_STA_GOT_IP:
|
||||
DPRINTF("WiFi connected, IP: %s\n", WiFi.localIP().toString().c_str());
|
||||
g_bWiFiHasBeenConnected = true;
|
||||
ledcWrite(PIN_LED_WIFI, PWM_FULL * 9 / 10); // LED_OFF
|
||||
ledcWrite(PIN_LED_WIFI, PWM_FULL * 19 / 20); // LED_OFF
|
||||
if (!g_bWiFiSetupExecuted) setupPostWiFi(false);
|
||||
break;
|
||||
case WIFI_EVENT_STA_DISCONNECTED:
|
||||
|
|
@ -74,7 +74,7 @@ void checkWiFi(unsigned long tickMillis) {
|
|||
if (status == WL_DISCONNECTED && g_bWiFiHasBeenConnected) {
|
||||
DPRINTLN("Attempting WiFi reconnection...");
|
||||
WiFi.reconnect();
|
||||
ledcWrite(PIN_LED_WIFI, PWM_FULL * 4 / 5); // Light Blink
|
||||
ledcWrite(PIN_LED_WIFI, PWM_FULL * 19 / 20); // Light Blink
|
||||
lastAttempt = tickMillis;
|
||||
bConnecting = true;
|
||||
}
|
||||
|
|
@ -93,7 +93,7 @@ void checkWiFi(unsigned long tickMillis) {
|
|||
DPRINTF(" WiFi.Begin(%s,%s) returned %d\n", config.ssid, config.pw, ret);
|
||||
lastAttempt = tickMillis;
|
||||
|
||||
ledcWrite(PIN_LED_WIFI, PWM_FULL * 4 / 5); // Light Blink
|
||||
ledcWrite(PIN_LED_WIFI, PWM_FULL / 10); // Light Blink
|
||||
lastAttempt = tickMillis;
|
||||
bConnecting = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
#ifndef DEBUG
|
||||
#define DEBUG 1 // Set to 0 to disable debug output
|
||||
#endif
|
||||
#undef DEBUG
|
||||
//#undef DEBUG
|
||||
|
||||
|
||||
//#define BLE_DEBUG
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include "BLEScan.h"
|
||||
#include "hal/timer_ll.h"
|
||||
|
||||
|
||||
#if defined(ESP32)
|
||||
#include "esp_wifi.h"
|
||||
#endif
|
||||
|
|
@ -22,7 +23,8 @@ STATUS_TYPE status;
|
|||
// Time
|
||||
volatile unsigned short g_nYear, g_nMonth, g_nDay, g_nHour, g_nMinute, g_nSecond;
|
||||
volatile uint32_t g_millis = 0l;
|
||||
extern timg_dev_t *tg1;
|
||||
extern timg_dev_t *tg0;
|
||||
|
||||
|
||||
// Environment
|
||||
bool bShowSensor = false;
|
||||
|
|
@ -39,6 +41,7 @@ void controlLight(short hour, short min, unsigned long tick);
|
|||
void controlFanDuty();
|
||||
void controlMotorDuty();
|
||||
void controlLightDuty();
|
||||
void setACLoadStatus(uint32_t tNow);
|
||||
|
||||
|
||||
// ==================================================================================
|
||||
|
|
@ -49,32 +52,29 @@ void controlLightDuty();
|
|||
MY_IRAM_ATTR void loop() {
|
||||
static unsigned long lastTickSecond = 0;
|
||||
static uint8_t lastSecond = -1;
|
||||
g_millis = (uint32_t)timer_ll_get_counter_value(tg1, 1);
|
||||
|
||||
// Read timer from TG0-Timer0
|
||||
tg0->hw_timer[0].update.val = 1;
|
||||
uint32_t tNow = tg0->hw_timer[0].lo.val;
|
||||
|
||||
g_millis = (uint32_t) (tNow / 10);
|
||||
unsigned long tickMillis = g_millis;
|
||||
unsigned long tickSecond = tickMillis / 1000;
|
||||
|
||||
// Un-Conditional Loop
|
||||
{
|
||||
//ESP_LOGI(TAG_MAIN,"Checking WiFi2");
|
||||
//checkWiFi(tickMillis);
|
||||
|
||||
//ESP_LOGI(TAG_MAIN,"Host Loop");
|
||||
//host.Loop(tickMillis);
|
||||
|
||||
// UI Button Check
|
||||
ui.loopButton(tickMillis);
|
||||
ui.loopButton(tickMillis);
|
||||
}
|
||||
|
||||
// Every Second
|
||||
if (tickSecond != lastTickSecond)
|
||||
{
|
||||
// Time and ZCD
|
||||
setZCD();
|
||||
setACLoadStatus(tNow);
|
||||
setTime();
|
||||
|
||||
// Temperature and Humidity
|
||||
readSensors();
|
||||
//ble.loop(tickMillis);
|
||||
|
||||
// Fan, Motor, Light Duties
|
||||
controlFanDuty();
|
||||
|
|
@ -664,23 +664,3 @@ inline void setTime() {
|
|||
g_nYear = timeinfo.tm_year + 1900;
|
||||
|
||||
}
|
||||
|
||||
inline void setZCD() {
|
||||
// ZCD
|
||||
status.zcdAC = zcdACCount;
|
||||
zcdACCount = 0;
|
||||
status.zcdLoad = zcdLoadCount;
|
||||
zcdLoadCount = 0;
|
||||
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;
|
||||
}
|
||||
}
|
||||
52
LED0.cpp
52
LED0.cpp
|
|
@ -1,52 +0,0 @@
|
|||
#include "LED0.h"
|
||||
|
||||
CLED0 led0;
|
||||
|
||||
void CLED0::setup(uint8_t _pin, uint16_t _freq, uint16_t _channel) {
|
||||
freq = _freq;
|
||||
channel = _channel;
|
||||
pin = _pin;
|
||||
bPWMMode = true;
|
||||
bAC = false;
|
||||
bLoad = false;
|
||||
duty = 0;
|
||||
|
||||
ledcAttachChannel(pin, _freq, PWM_RESOLUTION, channel);
|
||||
setDuty(duty);
|
||||
};
|
||||
|
||||
void CLED0::setFreq(uint16_t _freq) {
|
||||
if (freq != _freq) {
|
||||
if (_freq == 0) {
|
||||
ledcDetach(pin);
|
||||
pinMode(pin, OUTPUT);
|
||||
digitalWrite(pin, LED_OFF);
|
||||
bPWMMode = false;
|
||||
}
|
||||
else {
|
||||
ledcAttachChannel(pin, _freq, PWM_RESOLUTION, channel);
|
||||
bPWMMode = true;
|
||||
}
|
||||
freq = _freq;
|
||||
}
|
||||
}
|
||||
|
||||
void CLED0::setDuty() {
|
||||
uint16_t _duty;
|
||||
|
||||
if (bAC) _duty = LED0_DUTY_AC;
|
||||
else if (bLoad) _duty = LED0_DUTY_LOAD;
|
||||
else _duty = duty;
|
||||
|
||||
ledcWrite(PIN_LED_WIFI, PWM_FULL * (100 - _duty) / 100); // Light Blink
|
||||
}
|
||||
|
||||
void CLED0::setDuty(uint16_t _duty) {
|
||||
if (duty != _duty) {
|
||||
if (bPWMMode)
|
||||
ledcWrite(PIN_LED_WIFI, PWM_FULL * (100 - _duty) / 100); // Light Blink
|
||||
else
|
||||
digitalWrite(pin, _duty ? LED_ON : LED_OFF);
|
||||
duty = _duty;
|
||||
}
|
||||
};
|
||||
38
LED0.h
38
LED0.h
|
|
@ -1,38 +0,0 @@
|
|||
#ifndef __LED0_H
|
||||
#define __LED0_H
|
||||
|
||||
#ifndef __HERMIT_CRAB_H
|
||||
#include "HermitCrab.h"
|
||||
#endif
|
||||
|
||||
#define LED0_DUTY_BOOT 20
|
||||
#define LED0_DUTY_CONNECTED 0
|
||||
#define LED0_DUTY_CONNECTING 5
|
||||
#define LED0_DUTY_SMART_CONFIG 100
|
||||
#define LED0_DUTY_CLIENT 1
|
||||
#define LED0_DUTY_AC 90
|
||||
#define LED0_DUTY_LOAD 80
|
||||
|
||||
class CLED0 {
|
||||
public:
|
||||
void setup(uint8_t _pin, uint16_t _freq, uint16_t _channel);
|
||||
void loop();
|
||||
void setFreq(uint16_t _freq);
|
||||
void setDuty(uint16_t _duty);
|
||||
void setDuty();
|
||||
inline void setAC() { bAC = true; };
|
||||
inline void clearAC() { bAC = false; };
|
||||
inline void setLoad() { bLoad = true; };
|
||||
inline void clearLoad() { bLoad = false; };
|
||||
|
||||
private:
|
||||
uint16_t channel;
|
||||
uint16_t freq;
|
||||
uint16_t duty;
|
||||
uint8_t pin;
|
||||
bool bPWMMode;
|
||||
bool bAC, bLoad;
|
||||
};
|
||||
|
||||
extern CLED0 led0;
|
||||
#endif
|
||||
2
OTA.cpp
2
OTA.cpp
|
|
@ -17,7 +17,7 @@
|
|||
// OTA
|
||||
//
|
||||
// ==============================================================
|
||||
const char *HC__VERSION = "20260416002";
|
||||
const char *HC__VERSION = "2026041814";
|
||||
#define UPDATE_PORT ((uint16_t) 443)
|
||||
const char *url = "visionsoft.kr";
|
||||
const char *uri = "/sc/pages/firmware_download.php";
|
||||
|
|
|
|||
19
Setup.cpp
19
Setup.cpp
|
|
@ -12,7 +12,7 @@
|
|||
#include "BLEScan.h"
|
||||
#include <esp_wifi.h>
|
||||
#include "esp_coexist.h"
|
||||
#include "hal/timer_ll.h"
|
||||
|
||||
|
||||
#define TAG_SETUP "TAG_SETUP"
|
||||
// Task handle
|
||||
|
|
@ -23,7 +23,6 @@ bool g_bWiFiHasBeenConnected = false;
|
|||
|
||||
extern STATUS_TYPE status;
|
||||
extern CHistory history;
|
||||
extern timg_dev_t *tg1;
|
||||
|
||||
void setupConfig();
|
||||
void setupStatus();
|
||||
|
|
@ -37,14 +36,6 @@ void setup_BLE();
|
|||
void scanI2C();
|
||||
|
||||
void setup() {
|
||||
timer_ll_set_clock_prescale(tg1, 1, 80000);
|
||||
timer_ll_set_count_direction(tg1, 1, GPTIMER_COUNT_UP);
|
||||
tg1->hw_timer[1].loadhi.val = 0UL;
|
||||
tg1->hw_timer[1].loadlo.val = 0UL;
|
||||
tg1->hw_timer[1].load.val = 1UL;
|
||||
timer_ll_enable_alarm(tg1, 1, false); // No ISR needed for watchdog
|
||||
timer_ll_enable_counter(tg1, 1, true);
|
||||
|
||||
// put your setup code here, to run once:
|
||||
#ifdef DEBUG
|
||||
Serial.begin(115200);
|
||||
|
|
@ -149,7 +140,7 @@ void setupWiFi() {
|
|||
DPRINTLN();
|
||||
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
ledcWrite(PIN_LED_WIFI, PWM_FULL); // LED_OFF
|
||||
ledcWrite(PIN_LED_WIFI, PWM_FULL * 9 / 10); // LED_OFF
|
||||
ui.message(0, (char *) "WiFi...OK!");
|
||||
DPRINTLN("WiFi - Connected at SETUP");
|
||||
DPRINTF("WiFi - SSID(%s) PW(%s) IP(%s)\n", config.ssid, config.pw, WiFi.localIP().toString().c_str());
|
||||
|
|
@ -179,8 +170,10 @@ void setupPostWiFi(bool bBoot = false) {
|
|||
DPRINTLN("Setup - TimeManager.begin()");
|
||||
DPRINTLN("\n===============================\n");
|
||||
DPRINTLN(" Trying OTA");
|
||||
ui.message(2, (char *) "Update check...");
|
||||
ui.message(2, (char *) "Update check...");
|
||||
ledcWrite(PIN_LED_WIFI, PWM_FULL / 20);
|
||||
checkOTA(true);
|
||||
ledcWrite(PIN_LED_WIFI, PWM_FULL * 19 / 20);
|
||||
ui.message(2, (char *) "Update OK!");
|
||||
DPRINTLN(" OTA Process completed!");
|
||||
DPRINTLN("===============================\n");
|
||||
|
|
@ -228,7 +221,7 @@ void setupPins() {
|
|||
ledcWrite(PIN_FAN, PWM_OFF);
|
||||
ledcWrite(PIN_LIGHT, PWM_OFF);
|
||||
ledcWrite(PIN_MIST, PWM_OFF);
|
||||
ledcWrite(PIN_LED_WIFI, (PWM_FULL * 4) / 5); // 80% Initial Blink
|
||||
ledcWrite(PIN_LED_WIFI, PWM_FULL / 10); // 80% Initial Blink
|
||||
|
||||
// Heaters (Inverted logic for MOSFET safety)
|
||||
ledcWrite(PIN_LED_HEATER1, PWM_FULL - PWM_OFF);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ MY_IRAM_ATTR void core0Task(void *pvParameters) {
|
|||
ESP_LOGI(TAG_TASK0,"Core 0 Task Started");
|
||||
DPRINTLN("Core 0 Task Started");
|
||||
wl_status_t lastWiFiStatus = WL_DISCONNECTED;
|
||||
unsigned long tickMillis = g_millis;
|
||||
unsigned long tickMillis;
|
||||
unsigned long tickSecond;
|
||||
uint8_t slot;
|
||||
uint8_t lastSlot = 255;
|
||||
|
|
@ -36,7 +36,7 @@ MY_IRAM_ATTR void core0Task(void *pvParameters) {
|
|||
|
||||
while (true) {
|
||||
esp_task_wdt_reset();
|
||||
tickMillis = g_millis;
|
||||
tickMillis = millis();
|
||||
tickSecond = tickMillis / 1000;
|
||||
slot = (tickMillis % 1000) / 50;
|
||||
|
||||
|
|
|
|||
6
UI.cpp
6
UI.cpp
|
|
@ -1135,18 +1135,18 @@ void CUI::checkButtonStates(unsigned long currentMillis) {
|
|||
// ISR for the Set button handling
|
||||
ARDUINO_ISR_ATTR void buttonSetISR() {
|
||||
// Record the time of the button interrupt and set a flag
|
||||
ui.buttonSetChangeTime = g_millis;
|
||||
ui.buttonSetChangeTime = millis();
|
||||
ui.bButtonSetChanged = true; // Flag for main loop to process
|
||||
}
|
||||
|
||||
// ISR for the Up button handling
|
||||
ARDUINO_ISR_ATTR void buttonUpISR() {
|
||||
ui.buttonUpChangeTime = g_millis;
|
||||
ui.buttonUpChangeTime = millis();
|
||||
ui.bButtonUpChanged = true; // Flag for main loop to process
|
||||
}
|
||||
|
||||
// ISR for the Down button handling
|
||||
ARDUINO_ISR_ATTR void buttonDownISR() {
|
||||
ui.buttonDownChangeTime = g_millis;
|
||||
ui.buttonDownChangeTime = millis();
|
||||
ui.bButtonDownChanged = true; // Flag for main loop to process
|
||||
}
|
||||
|
|
@ -188,7 +188,7 @@ void CWiFiHost::Loop(unsigned long clock)
|
|||
m_bClientConnected = true;
|
||||
m_bHelloSent = false;
|
||||
m_nMode = MODE_PACKET;
|
||||
ledcWrite(PIN_LED_WIFI, PWM_FULL - 10);
|
||||
ledcWrite(PIN_LED_WIFI, PWM_FULL * 9 / 10);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -198,7 +198,7 @@ void CWiFiHost::Loop(unsigned long clock)
|
|||
if (!wifiClient || !wifiClient.connected()) {
|
||||
m_bClientConnected = false;
|
||||
m_nMode = MODE_WAITING;
|
||||
ledcWrite(PIN_LED_WIFI, PWM_FULL - 2);
|
||||
ledcWrite(PIN_LED_WIFI, PWM_FULL / 10 );
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -397,7 +397,7 @@ void CWiFiHost::ProcessPacket(TCP_PACKET& pkt)
|
|||
{
|
||||
// System
|
||||
case CMD_HEARTBEAT:
|
||||
m_nLastReceivedTime = g_millis;
|
||||
m_nLastReceivedTime = millis();
|
||||
//ESP_LOGI(TAG_WIFI_HOST,"H");
|
||||
break;
|
||||
case CMD_HELLO:
|
||||
|
|
|
|||
295
zcd.cpp
295
zcd.cpp
|
|
@ -4,36 +4,39 @@
|
|||
#include <math.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include <driver/gptimer.h>
|
||||
|
||||
// Timer Headers
|
||||
#include "hal/timer_ll.h"
|
||||
#include "hal/timer_types.h"
|
||||
#include "driver/timer.h" // Needed for timer_isr_register
|
||||
#include "rom/ets_sys.h"
|
||||
|
||||
|
||||
// Assuming tg0 is defined as: timg_dev_t *tg0 = &TIMG0;
|
||||
timg_dev_t *tg0 = &TIMERG0;
|
||||
timg_dev_t *tg1 = &TIMERG1;
|
||||
|
||||
#define SET_TIMER_1(duty) do { \
|
||||
timer_ll_enable_counter(tg0, 0, false); \
|
||||
tg0->hw_timer[0].loadhi.val = 0; \
|
||||
tg0->hw_timer[0].loadlo.val = 0; \
|
||||
tg0->hw_timer[0].load.val = 1; \
|
||||
timer_ll_set_alarm_value(tg0, 0, duty); \
|
||||
timer_ll_enable_alarm(tg0, 0, true); \
|
||||
timer_ll_enable_counter(tg0, 0, true); \
|
||||
timer_ll_enable_counter(tg1, 0, false); \
|
||||
tg1->hw_timer[0].loadhi.val = 0; \
|
||||
tg1->hw_timer[0].loadlo.val = 0; \
|
||||
tg1->hw_timer[0].load.val = 1; \
|
||||
timer_ll_set_alarm_value(tg1, 0, duty); \
|
||||
timer_ll_enable_alarm(tg1, 0, true); \
|
||||
timer_ll_enable_counter(tg1, 0, true); \
|
||||
} while(0)
|
||||
|
||||
#define SET_TIMER_2(duty) do { \
|
||||
timer_ll_enable_counter(tg0, 1, false); \
|
||||
tg0->hw_timer[1].loadhi.val = 0; \
|
||||
tg0->hw_timer[1].loadlo.val = 0; \
|
||||
tg0->hw_timer[1].load.val = 1; \
|
||||
timer_ll_set_alarm_value(tg0, 1, duty); \
|
||||
timer_ll_enable_alarm(tg0, 1, true); \
|
||||
timer_ll_enable_counter(tg0, 1, true); \
|
||||
timer_ll_enable_counter(tg1, 1, false); \
|
||||
tg1->hw_timer[1].loadhi.val = 0; \
|
||||
tg1->hw_timer[1].loadlo.val = 0; \
|
||||
tg1->hw_timer[1].load.val = 1; \
|
||||
timer_ll_set_alarm_value(tg1, 1, duty); \
|
||||
timer_ll_enable_alarm(tg1, 1, true); \
|
||||
timer_ll_enable_counter(tg1, 1, true); \
|
||||
} while(0)
|
||||
|
||||
#define ESP_INTR_FLAG_LEVEL3 (1<<3)
|
||||
#define ESP_INTR_FLAG_LEVEL1 (1<<1)
|
||||
|
||||
#define TAG_ZCD "ZCD"
|
||||
// Constants
|
||||
|
|
@ -48,6 +51,7 @@ const uint32_t AC_CYCLE_TIME_CLOCKS = 8333; // Half cycle of 60Hz AC in clock cy
|
|||
const uint32_t EFFECTIVE_HALF_CYCLE = EFFECTIVE_POWER * AC_CYCLE_TIME_CLOCKS; // Effective half cycle in clock cycles
|
||||
const uint32_t LEADING_PULSE_COUNT = EFFECTIVE_HALF_CYCLE * LEADING_TIME_RATIO; // Leading pulse count
|
||||
const uint32_t MAX_PULSE_COUNT = LEADING_PULSE_COUNT + EFFECTIVE_HALF_CYCLE; // Maximum valid pulse count
|
||||
const uint32_t LEADING_ZCD_COUNT = LEADING_PULSE_COUNT / 2;
|
||||
|
||||
|
||||
volatile uint32_t dutyHeater1; // Calculated timerHeater1 count for TRIAC firing
|
||||
|
|
@ -65,18 +69,33 @@ volatile uint8_t fireStatusTimer2 = 0;
|
|||
hw_timer_t *timerHeater1;
|
||||
hw_timer_t *timerHeater2;
|
||||
|
||||
const char fireTable[9][8] { {0, 0, 0, 0, 0, 0, 0, 0}, // 0 - 0%
|
||||
{1, 0, 0, 0, 0, 0, 0, 0}, // 1 - 12.5%
|
||||
{1, 0, 0, 0, 1, 0, 0, 0}, // 2 - 25%
|
||||
{1, 0, 0, 1, 0, 0, 1, 0}, // 3 - 37.5%
|
||||
{1, 0, 1, 0, 1, 0, 1, 0}, // 4 - 50%
|
||||
{1, 1, 0, 1, 1, 0, 1, 0}, // 5 - 62.5%
|
||||
{1, 1, 1, 0, 1, 1, 1, 0}, // 6 - 75%
|
||||
{1, 1, 1, 1, 1, 1, 1, 0}, // 7 - 87.5%
|
||||
{1, 1, 1, 1, 1, 1, 1, 1}}; // 8 - 100%
|
||||
const char fireTable[17][16] {
|
||||
{0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0}, // 0 0%
|
||||
{1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0}, // 1 6.25% (Dist: 16)
|
||||
{1,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0}, // 2 12.5% (Dist: 8, 8)
|
||||
{1,0,0,0, 0,1,0,0, 0,0,0,1, 0,0,0,0}, // 3 18.75% (Dist: 5, 6, 5)
|
||||
{1,0,0,0, 1,0,0,0, 1,0,0,0, 1,0,0,0}, // 4 25% (Dist: 4, 4, 4, 4)
|
||||
{1,0,0,1, 0,0,1,0, 0,1,0,0, 1,0,0,0}, // 5 31.25% (Dist: 3, 3, 3, 3, 4)
|
||||
{1,0,1,0, 0,1,0,0, 1,0,1,0, 0,1,0,0}, // 6 37.5% (Dist: 2, 3, 3, 2, 3, 3)
|
||||
{1,0,1,0, 1,0,0,1, 0,1,0,1, 0,1,0,0}, // 7 43.75% (Dist: 2, 2, 3, 2, 2, 2, 3)
|
||||
{1,0,1,0, 1,0,1,0, 1,0,1,0, 1,0,1,0}, // 8 50% (Perfect Toggle)
|
||||
{0,1,0,1, 0,1,1,0, 1,0,1,0, 1,0,1,1}, // 9 56.25% (Inv 7: spaced 0s)
|
||||
{0,1,0,1, 1,0,1,1, 0,1,0,1, 1,0,1,1}, // 10 62.5% (Inv 6: spaced 0s)
|
||||
{0,1,1,0, 1,1,0,1, 1,0,1,1, 0,1,1,1}, // 11 68.75% (Inv 5: spaced 0s)
|
||||
{0,1,1,1, 0,1,1,1, 0,1,1,1, 0,1,1,1}, // 12 75% (Inv 4: spaced 0s)
|
||||
{0,1,1,1, 1,0,1,1, 1,1,0,1, 1,1,1,0}, // 13 81.25% (Inv 3: spaced 0s)
|
||||
{0,1,1,1, 1,1,1,1, 0,1,1,1, 1,1,1,1}, // 14 87.5% (Inv 2: spaced 0s)
|
||||
{0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1}, // 15 93.75% (Inv 1: spaced 0s)
|
||||
{1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1} // 16 100%
|
||||
};
|
||||
|
||||
uint8_t seqStep = 0;
|
||||
uint8_t dutyAC1 = 0;
|
||||
uint8_t dutyAC2 = 0;
|
||||
uint8_t dutyAC1TableIndex = 0;
|
||||
uint8_t dutyAC2TableIndex = 0;
|
||||
|
||||
// AC Frequency and health status
|
||||
volatile uint8_t zcdACISRCount = 0;
|
||||
volatile uint8_t zcdLoadISRCount = 0;
|
||||
|
||||
void setAC1ControlMode(uint8_t mode) { ac1ControlMode = mode; }
|
||||
void setAC2ControlMode(uint8_t mode) { ac2ControlMode = mode; }
|
||||
|
|
@ -96,7 +115,8 @@ short getHeater2Duty() {
|
|||
// Function to set the duty based on percentage (0 to 10000)
|
||||
ARDUINO_ISR_ATTR void setHeater1Duty(short duty) {
|
||||
if (ac1ControlMode == ZCD_CONTROL) {
|
||||
dutyAC1 = (uint8_t)((duty + 10000/16)/1250);
|
||||
if (duty > 10000) duty = 10000;
|
||||
dutyAC1TableIndex = (uint8_t)((duty + 10000/32)/625);
|
||||
} else {
|
||||
if (duty <= 0) {
|
||||
dutyHeater1 = 0; // If 0% duty, no pulse (turn off TRIAC)
|
||||
|
|
@ -135,102 +155,91 @@ ARDUINO_ISR_ATTR void setHeater2Duty(short duty) {
|
|||
}
|
||||
dutyHeater2 = 0;
|
||||
} else {
|
||||
if (duty <= 0) {
|
||||
dutyHeater2 = 0; // If 0% duty, no pulse (turn off TRIAC)
|
||||
} else if (duty >= 10000) {
|
||||
// 100% duty corresponds to the leading pulse + full effective half cycle
|
||||
dutyHeater2 = LEADING_PULSE_COUNT;
|
||||
if (ac2ControlMode == ZCD_CONTROL) {
|
||||
if (duty > 10000) duty = 10000;
|
||||
dutyAC2TableIndex = (uint8_t)((duty + 10000/32)/625);
|
||||
} else {
|
||||
// Map duty to power ratio (0 to 1)
|
||||
float powerRatio = (float) duty / 10000.0f;
|
||||
if (duty <= 0) {
|
||||
dutyHeater2 = 0; // If 0% duty, no pulse (turn off TRIAC)
|
||||
} else if (duty >= 10000) {
|
||||
// 100% duty corresponds to the leading pulse + full effective half cycle
|
||||
dutyHeater2 = LEADING_PULSE_COUNT;
|
||||
} else {
|
||||
// Map duty to power ratio (0 to 1)
|
||||
float powerRatio = (float) duty / 10000.0f;
|
||||
|
||||
// Calculate the angle in radians using the inverse cosine directly
|
||||
float angleRadians = acosf(1.0f - 2.0f * powerRatio);
|
||||
// Calculate the angle in radians using the inverse cosine directly
|
||||
float angleRadians = acosf(1.0f - 2.0f * powerRatio);
|
||||
|
||||
// Convert angle to time delay (in clock cycles)
|
||||
// Normalized angle (0 to PI) maps to half-cycle (0 to EFFECTIVE_HALF_CYCLE)
|
||||
uint32_t pulseCount = (angleRadians / M_PI) * EFFECTIVE_HALF_CYCLE;
|
||||
// Convert angle to time delay (in clock cycles)
|
||||
// Normalized angle (0 to PI) maps to half-cycle (0 to EFFECTIVE_HALF_CYCLE)
|
||||
uint32_t pulseCount = (angleRadians / M_PI) * EFFECTIVE_HALF_CYCLE;
|
||||
|
||||
dutyHeater2 = LEADING_PULSE_COUNT + EFFECTIVE_HALF_CYCLE - pulseCount;
|
||||
dutyHeater2 = LEADING_PULSE_COUNT + EFFECTIVE_HALF_CYCLE - pulseCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t nDuty = duty * PWM_FULL / 10000;
|
||||
ledcWrite(PIN_LED_HEATER2, PWM_FULL - nDuty);
|
||||
ESP_LOGD(TAG_ZCD,"Set Duty: %.2f%%, Timer Count: %u clock cycles\n", duty, dutyHeater1);
|
||||
ESP_LOGD(TAG_ZCD,"Set Duty: %.2f%%, Timer Count: %u clock cycles\n", duty, dutyHeater2);
|
||||
}
|
||||
|
||||
|
||||
void ARDUINO_ISR_ATTR onTimer1(void *) {
|
||||
if (fireStatusTimer1) {
|
||||
REG_WRITE(GPIO_OUT1_W1TC_REG, (1UL << (PIN_HEATER1 - 32))); // Clear (Low)
|
||||
} else {
|
||||
REG_WRITE(GPIO_OUT1_W1TS_REG, (1UL << (PIN_HEATER1 - 32))); // Set (High)
|
||||
tg1->int_clr_timers.t0_int_clr = 1; // Clear Interrupt
|
||||
|
||||
if (fireStatusTimer1 == 0) {
|
||||
// First Trigger: Turn ON
|
||||
REG_WRITE(GPIO_OUT1_W1TS_REG, (1UL << (PIN_HEATER1 - 32)));
|
||||
fireStatusTimer1 = 1;
|
||||
SET_TIMER_1(8); // 8 us
|
||||
SET_TIMER_1(8); // Schedule OFF pulse 8us later
|
||||
} else {
|
||||
// Second Trigger: Turn OFF
|
||||
REG_WRITE(GPIO_OUT1_W1TC_REG, (1UL << (PIN_HEATER1 - 32)));
|
||||
}
|
||||
}
|
||||
|
||||
void ARDUINO_ISR_ATTR onTimer2(void *) {
|
||||
if (fireStatusTimer2) {
|
||||
REG_WRITE(GPIO_OUT1_W1TC_REG, (1UL << (PIN_HEATER2 - 32))); // Clear (Low)
|
||||
} else {
|
||||
REG_WRITE(GPIO_OUT1_W1TS_REG, (1UL << (PIN_HEATER2 - 32))); // Set (High)
|
||||
tg1->int_clr_timers.t1_int_clr = 1;
|
||||
|
||||
if (fireStatusTimer2 == 0) {
|
||||
REG_WRITE(GPIO_OUT1_W1TS_REG, (1UL << (PIN_HEATER2 - 32)));
|
||||
fireStatusTimer2 = 1;
|
||||
SET_TIMER_2(8); // 8 us
|
||||
SET_TIMER_2(8);
|
||||
} else {
|
||||
REG_WRITE(GPIO_OUT1_W1TC_REG, (1UL << (PIN_HEATER2 - 32)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Zero-Cross Detection Interrupt Service Routine
|
||||
void ARDUINO_ISR_ATTR zcdACISR() {
|
||||
// 1. Check the dedicated Watchdog Timer (Group 1)
|
||||
uint32_t elapsed = timer_ll_get_counter_value(tg1, 0);
|
||||
if (elapsed < 8000) return; // Reject noise based on absolute time since last ZCD
|
||||
tg1->hw_timer[0].loadhi.val = 0UL;
|
||||
tg1->hw_timer[0].loadlo.val = 0UL;
|
||||
tg1->hw_timer[0].load.val = 1UL;
|
||||
|
||||
zcdACCount++;
|
||||
void ARDUINO_ISR_ATTR zcdACISR(void *) {
|
||||
// 1. Power side AC ZCD Count
|
||||
zcdACISRCount++;
|
||||
|
||||
fireStatusTimer1 = 0;
|
||||
fireStatusTimer2 = 0;
|
||||
|
||||
// Heater 1
|
||||
// 3. Heater 1
|
||||
if (ac1ControlMode == ZCD_CONTROL) {
|
||||
if (fireTable[dutyAC1][seqStep]) {
|
||||
onTimer1(NULL);
|
||||
}
|
||||
} else {
|
||||
if (dutyHeater1 >= LEADING_PULSE_COUNT && dutyHeater1 < MAX_PULSE_COUNT) {
|
||||
// Stop the timer, configure new alarm, then explicitly start
|
||||
SET_TIMER_1(dutyHeater1); // Set alarm with updated duty
|
||||
}
|
||||
else if (dutyHeater1 == MAX_PULSE_COUNT) {
|
||||
onTimer1(NULL);
|
||||
}
|
||||
if (fireTable[dutyAC1TableIndex][seqStep]) SET_TIMER_1(LEADING_ZCD_COUNT);
|
||||
} else if ( dutyHeater1 >= LEADING_PULSE_COUNT){
|
||||
SET_TIMER_1(dutyHeater1);
|
||||
}
|
||||
|
||||
// Heater 2
|
||||
// 4. Heater 2
|
||||
if (ac2ControlMode == ZCD_CONTROL) {
|
||||
if (fireTable[dutyAC2][seqStep]) {
|
||||
onTimer2(NULL);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (dutyHeater2 >= LEADING_PULSE_COUNT && dutyHeater2 < MAX_PULSE_COUNT) {
|
||||
// Stop the timer, configure new alarm, then explicitly start
|
||||
SET_TIMER_2(dutyHeater2); // Set alarm with updated duty
|
||||
}
|
||||
else if (dutyHeater2 == MAX_PULSE_COUNT) {
|
||||
onTimer2(NULL);
|
||||
}
|
||||
if (fireTable[dutyAC2TableIndex][seqStep]) SET_TIMER_2(LEADING_ZCD_COUNT);
|
||||
} else if (dutyHeater2 >= LEADING_PULSE_COUNT) {
|
||||
SET_TIMER_2(dutyHeater2);
|
||||
}
|
||||
|
||||
seqStep = ++seqStep & 0x07;
|
||||
seqStep = ++seqStep & 0x0F;
|
||||
}
|
||||
|
||||
void ARDUINO_ISR_ATTR zcdLoadISR() {
|
||||
++zcdLoadCount;
|
||||
void ARDUINO_ISR_ATTR zcdLoadISR(void *) {
|
||||
// Load side AC ZCD Count
|
||||
zcdLoadISRCount++;
|
||||
}
|
||||
|
||||
void setupZCD() {
|
||||
|
|
@ -238,6 +247,8 @@ void setupZCD() {
|
|||
pinMode(PIN_ZCD_LOAD, INPUT);
|
||||
pinMode(PIN_HEATER1, OUTPUT);
|
||||
pinMode(PIN_HEATER2, OUTPUT);
|
||||
digitalWrite(PIN_HEATER1, HEATER_OFF);
|
||||
digitalWrite(PIN_HEATER2, HEATER_OFF);
|
||||
|
||||
dutyHeater1 = 0; // Calculated timerHeater1 count for TRIAC firing
|
||||
dutyHeater2 = 0; // Calculated timerZCD count for TRIAC firing
|
||||
|
|
@ -245,28 +256,94 @@ void setupZCD() {
|
|||
zcdLoadCount = 0;
|
||||
timerHeater1 = NULL;
|
||||
|
||||
// --- 1. Basic Hardware Config for TG0 (Heaters) ---
|
||||
// Timer 0
|
||||
timer_ll_set_clock_prescale(tg0, 0, 80);
|
||||
// Test
|
||||
config.ac1ControlMode = PHASE_CONTROL;
|
||||
config.ac2ControlMode = PHASE_CONTROL;
|
||||
|
||||
ac1ControlMode = config.ac1ControlMode;
|
||||
ac2ControlMode = config.ac2ControlMode;
|
||||
|
||||
// --- 0. Hardware Config for TG0-Timer0 (g_millis)
|
||||
timer_ll_set_clock_prescale(tg0, 0, 8000); // 10KHz
|
||||
timer_ll_set_count_direction(tg0, 0, GPTIMER_COUNT_UP);
|
||||
timer_ll_enable_alarm(tg0, 0, true);
|
||||
tg0->hw_timer[0].loadhi.val = 0UL;
|
||||
tg0->hw_timer[0].loadlo.val = 0UL;
|
||||
tg0->hw_timer[0].load.val = 1UL;
|
||||
timer_ll_enable_alarm(tg0, 0, false); // No ISR needed for g_millis
|
||||
timer_ll_enable_counter(tg0, 0, true);
|
||||
|
||||
// --- 1. Hardware Config for TG0-Timer1 (Watchdog) ---
|
||||
tg0->hw_timer[1].loadhi.val = 0UL;
|
||||
tg0->hw_timer[1].loadlo.val = 0UL;
|
||||
tg0->hw_timer[1].load.val = 1UL;
|
||||
timer_ll_set_clock_prescale(tg0, 1, 80); // 1MHz
|
||||
timer_ll_set_count_direction(tg0, 1, GPTIMER_COUNT_UP);
|
||||
timer_ll_enable_alarm(tg0, 1, false); // No ISR needed for zcdACISR Watchdog
|
||||
timer_ll_enable_counter(tg0, 1, true);
|
||||
|
||||
// --- 2. Basic Hardware Config for TG1 (Heaters) ---
|
||||
// Timer 0
|
||||
timer_ll_set_clock_prescale(tg1, 0, 80);
|
||||
timer_ll_set_count_direction(tg1, 0, GPTIMER_COUNT_UP);
|
||||
timer_ll_enable_alarm(tg1, 0, true);
|
||||
|
||||
// Timer 1
|
||||
timer_ll_set_clock_prescale(tg0, 1, 80);
|
||||
timer_ll_set_count_direction(tg0, 1, GPTIMER_COUNT_UP);
|
||||
timer_ll_enable_alarm(tg0, 1, true);
|
||||
timer_ll_set_clock_prescale(tg1, 1, 80);
|
||||
timer_ll_set_count_direction(tg1, 1, GPTIMER_COUNT_UP);
|
||||
timer_ll_enable_alarm(tg1, 1, true);
|
||||
|
||||
// --- 2. Manual ISR Registration ---
|
||||
// ESP_INTR_FLAG_IRAM ensures the ISR stays in IRAM for fast context switching.
|
||||
timer_isr_register((timer_group_t)0, (timer_idx_t)0, onTimer1, NULL, ESP_INTR_FLAG_IRAM, NULL);
|
||||
timer_isr_register((timer_group_t)0, (timer_idx_t)1, onTimer2, NULL, ESP_INTR_FLAG_IRAM, NULL);
|
||||
// --- 3. Manual ISR Registration ---
|
||||
esp_intr_alloc(ETS_TG1_T0_LEVEL_INTR_SOURCE, ESP_INTR_FLAG_IRAM, onTimer1, NULL, NULL);
|
||||
esp_intr_alloc(ETS_TG1_T1_LEVEL_INTR_SOURCE, ESP_INTR_FLAG_IRAM, onTimer2, NULL, NULL);
|
||||
|
||||
// --- 3. Hardware Config for TG1 (Watchdog) ---
|
||||
timer_ll_set_clock_prescale(tg1, 0, 80000);
|
||||
timer_ll_set_count_direction(tg1, 0, GPTIMER_COUNT_UP);
|
||||
tg1->hw_timer[0].loadhi.val = 0UL;
|
||||
tg1->hw_timer[0].loadlo.val = 0UL;
|
||||
tg1->hw_timer[0].load.val = 1UL;
|
||||
timer_ll_enable_alarm(tg1, 0, false); // No ISR needed for watchdog
|
||||
timer_ll_enable_counter(tg1, 0, true);
|
||||
tg0->hw_timer[0].update.val = 1;
|
||||
uint32_t startupTime = timer_ll_get_counter_value(tg0, 0);
|
||||
|
||||
zcdACISRCount = 0;
|
||||
zcdLoadISRCount = 0;
|
||||
|
||||
// --- 4. Hardware Trigger ISR Registration ---
|
||||
//attachInterrupt(PIN_ZCD_AC, zcdACISR, CHANGE); // Attach zero-cross detection ISR
|
||||
//attachInterrupt(PIN_ZCD_LOAD, zcdLoadISR, CHANGE); // Attach zero-cross detection ISR
|
||||
|
||||
// Attach Load ISR with higher priority
|
||||
esp_intr_alloc(ETS_GPIO_INTR_SOURCE, ESP_INTR_FLAG_LEVEL3, zcdLoadISR, NULL, NULL);
|
||||
|
||||
// Attach AC ISR with normal/lower priority
|
||||
esp_intr_alloc(ETS_GPIO_INTR_SOURCE, ESP_INTR_FLAG_LEVEL1, zcdACISR, NULL, NULL);
|
||||
}
|
||||
|
||||
void setACLoadStatus(uint32_t tNow) {
|
||||
static uint32_t lastTick = 0;
|
||||
// --- 1. Process AC/Load Window (Every 1s) ---
|
||||
if (tNow - lastTick >= 9999) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user