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  >=
This commit is contained in:
stefanbode 2023-10-15 18:40:26 +02:00 committed by GitHub
parent 56314e5423
commit 124fbf8dcb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -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