From 124fbf8dcbf4a062a78d51ba7e6f11951fac705e Mon Sep 17 00:00:00 2001 From: stefanbode Date: Sun, 15 Oct 2023 18:40:26 +0200 Subject: [PATCH] fix shutterfrequency change on mutiple channels (#19737) * fix shutterfrequency change on mutiple channels * LEDC channel management for stepper shutter LEDC channels dynamically assigned to ensure up to 16 shutters can be defined. Number of simultaneous moving shutters is limited by number of LEDC channels. * bugfix >= --- .../xdrv_27_esp32_shutter.ino | 65 ++++++++----------- 1 file changed, 27 insertions(+), 38 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_27_esp32_shutter.ino b/tasmota/tasmota_xdrv_driver/xdrv_27_esp32_shutter.ino index 67e9ae81e805..a0b447e396c2 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_27_esp32_shutter.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_27_esp32_shutter.ino @@ -23,6 +23,7 @@ * Shutter or Blind support using two consecutive relays * Shutters for ESP32 with max eight shutters using more RAM and Settings from filesystem \*********************************************************************************************/ +#include "soc/soc_caps.h" #define XDRV_27 27 #ifndef SHUTTER_STEPPER @@ -178,6 +179,7 @@ struct SHUTTER { uint16_t last_reported_time = 0; // get information on skipped 50ms loop() slots uint32_t last_stop_time = 0; // record the last time the relay was switched off uint8_t button_simu_pressed = 0; // record if both button where pressed simultanously + uint8_t ledc_channel = 0; // current used channel for PWM } Shutter[MAX_SHUTTERS_ESP32]; struct SHUTTERGLOBAL { @@ -469,9 +471,6 @@ int32_t ShutterCalculatePosition(uint32_t i) void ShutterDecellerateForStop(uint8_t i) { -#ifdef ESP32 - bool pwm_apply = false; // ESP32 only, do we need to apply PWM changes -#endif switch (ShutterGlobal.position_mode) { case SHT_PWM_VALUE: case SHT_COUNTER: @@ -491,13 +490,10 @@ void ShutterDecellerateForStop(uint8_t i) //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Remain %d count %d -> target %d, dir %d"), missing_steps, RtcSettings.pulse_counter[i], (uint32_t)(Shutter[i].target_position-Shutter[i].start_position)*Shutter[i].direction*ShutterGlobal.open_velocity_max/RESOLUTION/STEPS_PER_SECOND, Shutter[i].direction); while (RtcSettings.pulse_counter[i] < (uint32_t)(Shutter[i].target_position-Shutter[i].start_position)*Shutter[i].direction*ShutterGlobal.open_velocity_max/RESOLUTION/STEPS_PER_SECOND && missing_steps > 0) { } -#ifdef ESP8266 - analogWrite(Pin(GPIO_PWM1, i), 0); // removed with 8.3 because of reset caused by watchog -#endif -#ifdef ESP32 TasmotaGlobal.pwm_value[i] = 0; - pwm_apply = true; -#endif // ESP32 + ledcWrite(Shutter[i].ledc_channel, 0); + ledcAttachPin(Pin(GPIO_PWM1, i), SOC_LEDC_CHANNEL_NUM); + Shutter[i].ledc_channel = 0; Shutter[i].real_position = ShutterCalculatePosition(i); //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Remain steps %d"), missing_steps); AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Real %d, Pulsecount %d, tobe %d, Start %d"), Shutter[i].real_position,RtcSettings.pulse_counter[i], (uint32_t)(Shutter[i].target_position-Shutter[i].start_position)*Shutter[i].direction*ShutterGlobal.open_velocity_max/RESOLUTION/STEPS_PER_SECOND, Shutter[i].start_position); @@ -506,9 +502,6 @@ void ShutterDecellerateForStop(uint8_t i) Shutter[i].pwm_velocity = 0; break; } -#ifdef ESP32 - if (pwm_apply) { PwmApplyGPIO(false); } -#endif } uint16_t ShutterGetCycleTime(uint8_t i, uint8_t max_runtime) { @@ -539,6 +532,20 @@ uint16_t ShutterGetCycleTime(uint8_t i, uint8_t max_runtime) { return cycle_time; } +uint8_t ShutterGetFreeChannel() { + uint8_t nextFreeChannel = 0; + for (uint8_t i = 0; i < MAX_SHUTTERS_ESP32; i++) { + //SOC_LEDC_CHANNEL_NUM + nextFreeChannel = tmax(nextFreeChannel, Shutter[i].ledc_channel); + } + if (nextFreeChannel >= SOC_LEDC_CHANNEL_NUM) { + AddLog(LOG_LEVEL_ERROR, PSTR("SHT: All PWM channel busy. Open issue-ticket.")); + } else { + AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Use channel %d"), nextFreeChannel+1); + } + return nextFreeChannel++; +} + uint8_t ShutterGetOptions(uint8_t index) { return ShutterSettings.shutter_options[index]; } @@ -964,9 +971,6 @@ void ShutterReportPosition(bool always, uint32_t index) void ShutterRtc50mS(void) { -#ifdef ESP32 - bool pwm_apply = false; // ESP32 only, do we need to apply PWM changes -#endif // No Logging allowed. RTC Timer for (uint8_t i = 0; i < TasmotaGlobal.shutters_present; i++) { if (Shutter[i].direction) { @@ -987,25 +991,15 @@ void ShutterRtc50mS(void) //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Accelerator i=%d -> %d"),i, Shutter[i].accelerator); ShutterUpdateVelocity(i); digitalWrite(Pin(GPIO_PWM1, i), LOW); - #ifdef ESP8266 - // Convert frequency into clock cycles - uint32_t cc = microsecondsToClockCycles(1000000UL) / Shutter[i].pwm_velocity; - startWaveformClockCycles(Pin(GPIO_PWM1, i), cc/2, cc/2, 0, -1, 0, false); - #endif // ESP8266 - #ifdef ESP32 - ledcWriteTone(i, Shutter[i].pwm_velocity); // - ledcWrite(i, 512); // Setzt den PWM-Wert auf 0 + + ledcWriteTone(Shutter[i].ledc_channel, Shutter[i].pwm_velocity); // + //ledcWrite(i, 512); // Setzt den PWM-Wert auf 0 TasmotaGlobal.pwm_value[i] = 512; - pwm_apply = true; - #endif // ESP32 } break; } } // if (Shutter[i].direction) } -#ifdef ESP32 - if (pwm_apply) { PwmApplyGPIO(false); } -#endif } void ShutterSetPosition(uint32_t device, uint32_t position) @@ -1172,16 +1166,11 @@ void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos) switch (ShutterGlobal.position_mode) { #ifdef SHUTTER_STEPPER case SHT_COUNTER: -#ifdef ESP8266 - analogWriteFreq(Shutter[i].pwm_velocity); - analogWrite(Pin(GPIO_PWM1, i), 0); -#endif -#ifdef ESP32 - ledcSetup(i, Shutter[i].pwm_velocity, 8); - ledcAttachPin(Pin(GPIO_PWM1, i), i); // Nehmen Sie an, dass GPIO_PWM1 der gewünschte GPIO-Pin ist. - ledcWriteTone(i, Shutter[i].pwm_velocity); // - ledcWrite(i, 0); // Setzt den PWM-Wert auf 0 -#endif + Shutter[i].ledc_channel = ShutterGetFreeChannel(); + ledcSetup(Shutter[i].ledc_channel, Shutter[i].pwm_velocity, 8); + ledcAttachPin(Pin(GPIO_PWM1, i), Shutter[i].ledc_channel); + ledcWriteTone(Shutter[i].ledc_channel, Shutter[i].pwm_velocity); + ledcWrite(Shutter[i].ledc_channel, 0); // Setzt den PWM-Wert auf 0 RtcSettings.pulse_counter[i] = 0; break; #endif