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 * Shutter or Blind support using two consecutive relays
* Shutters for ESP32 with max eight shutters using more RAM and Settings from filesystem * Shutters for ESP32 with max eight shutters using more RAM and Settings from filesystem
\*********************************************************************************************/ \*********************************************************************************************/
#include "soc/soc_caps.h"
#define XDRV_27 27 #define XDRV_27 27
#ifndef SHUTTER_STEPPER #ifndef SHUTTER_STEPPER
@ -178,6 +179,7 @@ struct SHUTTER {
uint16_t last_reported_time = 0; // get information on skipped 50ms loop() slots 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 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 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]; } Shutter[MAX_SHUTTERS_ESP32];
struct SHUTTERGLOBAL { struct SHUTTERGLOBAL {
@ -469,9 +471,6 @@ int32_t ShutterCalculatePosition(uint32_t i)
void ShutterDecellerateForStop(uint8_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) { switch (ShutterGlobal.position_mode) {
case SHT_PWM_VALUE: case SHT_PWM_VALUE:
case SHT_COUNTER: 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); //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) { 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; TasmotaGlobal.pwm_value[i] = 0;
pwm_apply = true; ledcWrite(Shutter[i].ledc_channel, 0);
#endif // ESP32 ledcAttachPin(Pin(GPIO_PWM1, i), SOC_LEDC_CHANNEL_NUM);
Shutter[i].ledc_channel = 0;
Shutter[i].real_position = ShutterCalculatePosition(i); 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: 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); 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; Shutter[i].pwm_velocity = 0;
break; break;
} }
#ifdef ESP32
if (pwm_apply) { PwmApplyGPIO(false); }
#endif
} }
uint16_t ShutterGetCycleTime(uint8_t i, uint8_t max_runtime) { 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; 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) { uint8_t ShutterGetOptions(uint8_t index) {
return ShutterSettings.shutter_options[index]; return ShutterSettings.shutter_options[index];
} }
@ -964,9 +971,6 @@ void ShutterReportPosition(bool always, uint32_t index)
void ShutterRtc50mS(void) void ShutterRtc50mS(void)
{ {
#ifdef ESP32
bool pwm_apply = false; // ESP32 only, do we need to apply PWM changes
#endif
// No Logging allowed. RTC Timer // No Logging allowed. RTC Timer
for (uint8_t i = 0; i < TasmotaGlobal.shutters_present; i++) { for (uint8_t i = 0; i < TasmotaGlobal.shutters_present; i++) {
if (Shutter[i].direction) { 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); //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Accelerator i=%d -> %d"),i, Shutter[i].accelerator);
ShutterUpdateVelocity(i); ShutterUpdateVelocity(i);
digitalWrite(Pin(GPIO_PWM1, i), LOW); digitalWrite(Pin(GPIO_PWM1, i), LOW);
#ifdef ESP8266
// Convert frequency into clock cycles ledcWriteTone(Shutter[i].ledc_channel, Shutter[i].pwm_velocity); //
uint32_t cc = microsecondsToClockCycles(1000000UL) / Shutter[i].pwm_velocity; //ledcWrite(i, 512); // Setzt den PWM-Wert auf 0
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
TasmotaGlobal.pwm_value[i] = 512; TasmotaGlobal.pwm_value[i] = 512;
pwm_apply = true;
#endif // ESP32
} }
break; break;
} }
} // if (Shutter[i].direction) } // if (Shutter[i].direction)
} }
#ifdef ESP32
if (pwm_apply) { PwmApplyGPIO(false); }
#endif
} }
void ShutterSetPosition(uint32_t device, uint32_t position) 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) { switch (ShutterGlobal.position_mode) {
#ifdef SHUTTER_STEPPER #ifdef SHUTTER_STEPPER
case SHT_COUNTER: case SHT_COUNTER:
#ifdef ESP8266 Shutter[i].ledc_channel = ShutterGetFreeChannel();
analogWriteFreq(Shutter[i].pwm_velocity); ledcSetup(Shutter[i].ledc_channel, Shutter[i].pwm_velocity, 8);
analogWrite(Pin(GPIO_PWM1, i), 0); ledcAttachPin(Pin(GPIO_PWM1, i), Shutter[i].ledc_channel);
#endif ledcWriteTone(Shutter[i].ledc_channel, Shutter[i].pwm_velocity);
#ifdef ESP32 ledcWrite(Shutter[i].ledc_channel, 0); // Setzt den PWM-Wert auf 0
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
RtcSettings.pulse_counter[i] = 0; RtcSettings.pulse_counter[i] = 0;
break; break;
#endif #endif