Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Zero-Cross Dimmer for ESP32 with Core3 #19929

Merged
merged 3 commits into from
Nov 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ All notable changes to this project will be documented in this file.

### Fixed
- Scripter timer issue (#19914)
- Fix Zero-Cross Dimmer for ESP32 with Core3

### Removed

Expand Down
2 changes: 1 addition & 1 deletion tasmota/include/tasmota_configurations_ESP32.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@

// -- Optional modules ----------------------------
#undef USE_SHUTTER // Disable Shutter support for up to 4 shutter with different motortypes (+6k code)
#undef USE_AC_ZERO_CROSS_DIMMER // Disable support for AC_ZERO_CROSS_DIMMER
#define USE_AC_ZERO_CROSS_DIMMER // Enable support for AC_ZERO_CROSS_DIMMER

#define USE_IR_REMOTE // Enable IR driver

Expand Down
111 changes: 64 additions & 47 deletions tasmota/tasmota_xdrv_driver/xdrv_68_zerocrossDimmer.ino
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@

#define XDRV_68 68


#if !defined(ESP32) || (ESP_IDF_VERSION_MAJOR < 5) // temporarily disable for IDF 5.0

static const uint8_t TRIGGER_PERIOD = 75;

#define ZCDIMMERSET_SHOW 1
Expand Down Expand Up @@ -64,7 +61,7 @@ void (* const ZCDimmerCommand[])(void) PROGMEM = {
&CmndZCDimmerSet//,&CmndZCGateEnableTime
};

void IRAM_ATTR ACDimmerZeroCross(uint32_t time) {
extern "C" void IRAM_ATTR ACDimmerZeroCross(uint32_t time) {
ac_zero_cross_dimmer.dimmer_in_use = false;
ac_zero_cross_dimmer.cycle_time_us = time - ac_zero_cross_dimmer.crossed_zero_at;
ac_zero_cross_dimmer.crossed_zero_at = time;
Expand All @@ -76,12 +73,6 @@ void IRAM_ATTR ACDimmerZeroCross(uint32_t time) {
}
}

uint32_t IRAM_ATTR ACDimmerTimer_intr_ESP8266() {
//ACDimmerTimer_intr();
ACDimmerTimer_intr();
return ac_zero_cross_dimmer.actual_tigger_Period * 80;
}

void ACDimmerInit()
{
for (uint8_t i = 0 ; i < 5; i++) {
Expand All @@ -90,40 +81,7 @@ void ACDimmerInit()
}
}

void ACDimmerInterruptDisable(bool disable)
{
AddLog(LOG_LEVEL_INFO, PSTR("ZCD: Zero-CrossDimmer enabled: %d"),!disable);
ac_zero_cross_dimmer.timer_iterrupt_started = !disable;
if (disable) {
//stop the interrupt
#ifdef ESP32
if (dimmer_timer != nullptr) {
timerAlarmDisable(dimmer_timer);
}
#endif
} else {
for (uint8_t i = 0 ; i < MAX_PWMS; i++) {
if (Pin(GPIO_PWM1, i) != -1) {
pinMode(Pin(GPIO_PWM1, i), OUTPUT);
AddLog(LOG_LEVEL_INFO, PSTR("ZCD: Zero-CrossDimmer Pin %d set"),Pin(GPIO_PWM1, i));
}
}
#ifdef ESP32
if (dimmer_timer == nullptr) {
// 80 Divider -> 1 count=1µs
dimmer_timer = timerBegin(0, 80, true);
timerAttachInterrupt(dimmer_timer, &ACDimmerTimer_intr, true);
// For ESP32, we can't use dynamic interval calculation because the timerX functions
// are not callable from ISR (placed in flash storage).
// Here we just use an interrupt firing every 75 µs.
timerAlarmWrite(dimmer_timer, TRIGGER_PERIOD , true);
}
timerAlarmEnable(dimmer_timer);
#endif
}
}

void IRAM_ATTR ACDimmerTimer_intr() {
extern "C" void IRAM_ATTR ACDimmerTimer_intr() {

uint32_t time_since_zc = micros() - ac_zero_cross_dimmer.crossed_zero_at;
// If no ZC signal received yet.
Expand Down Expand Up @@ -165,6 +123,62 @@ void IRAM_ATTR ACDimmerTimer_intr() {
}
}

#ifdef ESP8266
extern "C" uint32_t IRAM_ATTR ACDimmerTimer_intr_ESP8266() {
ACDimmerTimer_intr();
return ac_zero_cross_dimmer.actual_tigger_Period * 80;
}
#endif // ESP8266

void ACDimmerInterruptDisable(bool disable)
{
AddLog(LOG_LEVEL_INFO, PSTR("ZCD: Zero-CrossDimmer enabled: %d"),!disable);
ac_zero_cross_dimmer.timer_iterrupt_started = !disable;
if (disable) {
//stop the interrupt
#ifdef ESP32
if (dimmer_timer != nullptr) {
#if ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 3) )
timerStop(dimmer_timer);
#else // ESP_ARDUINO_VERSION_MAJOR >= 3
timerAlarmDisable(dimmer_timer);
#endif // ESP_ARDUINO_VERSION_MAJOR >= 3
}
#endif
} else {
for (uint8_t i = 0 ; i < MAX_PWMS; i++) {
if (Pin(GPIO_PWM1, i) != -1) {
pinMode(Pin(GPIO_PWM1, i), OUTPUT);
AddLog(LOG_LEVEL_INFO, PSTR("ZCD: Zero-CrossDimmer Pin %d set"),Pin(GPIO_PWM1, i));
}
}
#ifdef ESP32
#if ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 3) )
if (dimmer_timer == nullptr) {
dimmer_timer = timerBegin(1000000); // 1 MHz
timerAttachInterrupt(dimmer_timer, &ACDimmerTimer_intr);
// For ESP32, we can't use dynamic interval calculation because the timerX functions
// are not callable from ISR (placed in flash storage).
// Here we just use an interrupt firing every 75 µs.
timerAlarm(dimmer_timer, TRIGGER_PERIOD, true, 0);
}
timerStart(dimmer_timer);
#else // ESP_ARDUINO_VERSION_MAJOR >= 3
if (dimmer_timer == nullptr) {
// 80 Divider -> 1 count=1µs
dimmer_timer = timerBegin(0, 80, true);
timerAttachInterrupt(dimmer_timer, &ACDimmerTimer_intr, true);
// For ESP32, we can't use dynamic interval calculation because the timerX functions
// are not callable from ISR (placed in flash storage).
// Here we just use an interrupt firing every 75 µs.
timerAlarmWrite(dimmer_timer, TRIGGER_PERIOD , true);
}
timerAlarmEnable(dimmer_timer);
#endif // ESP_ARDUINO_VERSION_MAJOR >= 3
#endif
}
}

void ACDimmerControllTrigger(void) {
#ifdef ESP32
if (ac_zero_cross_dimmer.timer_iterrupt_started != ac_zero_cross_dimmer.dimmer_in_use) {
Expand Down Expand Up @@ -204,10 +218,15 @@ void ACDimmerLogging(void)
bool alarmEnabled = false;
uint32_t timercounter = ac_zero_cross_dimmer.intr_counter;

#ifdef ESP32
#ifdef ESP32
if (dimmer_timer != nullptr) {
#if ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 3) )
alarmEnabled = true; // we assume it's started, there is no API to check whether it's running
timercounter = (uint32_t)timerRead(dimmer_timer);
#else // ESP_ARDUINO_VERSION_MAJOR >= 3
alarmEnabled = timerAlarmEnabled(dimmer_timer);
timercounter = (uint32_t)timerRead(dimmer_timer);
#endif // ESP_ARDUINO_VERSION_MAJOR >= 3
}
#endif

Expand Down Expand Up @@ -302,6 +321,4 @@ bool Xdrv68(uint32_t function)
return result;
}

#endif // !enabled(ESP32) || (ESP_IDF_VERSION_MAJOR < 5)

#endif // USE_AC_ZERO_CROSS_DIMMER