mirror of https://github.com/arendst/Tasmota.git
Fixed Tilt Movement + Enhancement PWM Servo
Optimized venetian tilt operation when position was not exactly captured during operation. Shutter tried to find correct position and moves up and down because of the tilt. Enhancement to PWM Servos. no minimum movement is required. Every Position can be reached directly
This commit is contained in:
parent
5a4838bb50
commit
48685c2d42
|
@ -95,10 +95,13 @@ struct SHUTTER {
|
|||
int32_t accelerator; // speed of ramp-up, ramp down of shutters with velocity control. Steppers and Servos only
|
||||
int8_t tilt_config[5]; // tilt_min, tilt_max, duration, tilt_closed_value, tilt_opened_value
|
||||
int8_t tilt_real_pos; // -90 to 90
|
||||
int16_t tilt_target_pos;
|
||||
int16_t tilt_start_pos;
|
||||
int8_t tilt_target_pos; // target positon for movements of the tilt
|
||||
int8_t tilt_start_pos; // saved start position before shutter moves
|
||||
uint8_t tilt_velocity; // degree rotation per step 0.05sec
|
||||
int8_t tiltmoving; // 0 operating move, 1 = operating tilt
|
||||
uint16_t venetian_delay = 0; // Delay in steps before venetian shutter start physical moving. Based on tilt position
|
||||
uint16_t min_realPositionChange = 0; // minimum change of the position before the shutter operates. different for PWM and time based operations
|
||||
uint16_t min_TiltChange = 0; // minimum change of the tilt before the shutter operates. different for PWM and time based operations
|
||||
} Shutter[MAX_SHUTTERS];
|
||||
|
||||
struct SHUTTERGLOBAL {
|
||||
|
@ -108,8 +111,7 @@ struct SHUTTERGLOBAL {
|
|||
uint8_t position_mode = 0; // how to calculate actual position: SHT_TIME, SHT_COUNTER, SHT_PWM_VALUE, SHT_PWM_TIME
|
||||
uint8_t skip_relay_change; // avoid overrun at endstops
|
||||
uint8_t start_reported = 0; // indicates of the shutter start was reported through MQTT JSON
|
||||
uint16_t open_velocity_max = 1000; // maximum of PWM change during opening. Defines velocity on opening. Steppers and Servos only
|
||||
uint16_t venetian_delay = 0;
|
||||
uint16_t open_velocity_max = RESOLUTION; // maximum of PWM change during opening. Defines velocity on opening. Steppers and Servos only
|
||||
} ShutterGlobal;
|
||||
|
||||
#define SHT_DIV_ROUND(__A, __B) (((__A) + (__B)/2) / (__B))
|
||||
|
@ -327,6 +329,10 @@ void ShutterInit(void)
|
|||
Shutter[i].tilt_real_pos = Settings->shutter_tilt_pos[i];
|
||||
Shutter[i].tilt_velocity = Shutter[i].tilt_config[2] > 0 ? (Shutter[i].tilt_config[1]-Shutter[i].tilt_config[0])/Shutter[i].tilt_config[2] : 1;
|
||||
|
||||
Shutter[i].close_velocity_max = ShutterGlobal.open_velocity_max*Shutter[i].open_time / Shutter[i].close_time;
|
||||
|
||||
Shutter[i].min_realPositionChange = 2 * tmax(ShutterGlobal.open_velocity_max, Shutter[i].close_velocity_max);
|
||||
Shutter[i].min_TiltChange = 2 * Shutter[i].tilt_velocity;
|
||||
|
||||
switch (ShutterGlobal.position_mode) {
|
||||
case SHT_PWM_VALUE:
|
||||
|
@ -334,14 +340,15 @@ void ShutterInit(void)
|
|||
// Initiate pwm range with defaults if not already set.
|
||||
Settings->shutter_pwmrange[0][i] = Settings->shutter_pwmrange[0][i] > 0 ? Settings->shutter_pwmrange[0][i] : pwm_servo_min;
|
||||
Settings->shutter_pwmrange[1][i] = Settings->shutter_pwmrange[1][i] > 0 ? Settings->shutter_pwmrange[1][i] : pwm_servo_max;
|
||||
Shutter[i].min_realPositionChange = 0;
|
||||
Shutter[i].min_TiltChange = 0;
|
||||
break;
|
||||
}
|
||||
Shutter[i].close_velocity_max = ShutterGlobal.open_velocity_max*Shutter[i].open_time / Shutter[i].close_time;
|
||||
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Shtr%d min realpos_chg: %d, min tilt_chg %d"),i+1,Shutter[i].min_realPositionChange,Shutter[i].min_TiltChange);
|
||||
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d Openvel %d, Closevel: %d"),i, ShutterGlobal.open_velocity_max, Shutter[i].close_velocity_max);
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Shtr%d Init. Pos %d, Inverted %d, Locked %d, End stop time enabled %d, webButtons inverted %d, delay: %d"),
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Shtr%d Init. Pos %d, Inv %d, Locked %d, Endstop enab %d, webButt inv %d, Motordel: %d"),
|
||||
i+1, Shutter[i].real_position,
|
||||
(Settings->shutter_options[i]&1) ? 1 : 0, (Settings->shutter_options[i]&2) ? 1 : 0, (Settings->shutter_options[i]&4) ? 1 : 0, (Settings->shutter_options[i]&8) ? 1 : 0), Shutter[i].motordelay;
|
||||
(Settings->shutter_options[i]&1) ? 1 : 0, (Settings->shutter_options[i]&2) ? 1 : 0, (Settings->shutter_options[i]&4) ? 1 : 0, (Settings->shutter_options[i]&8) ? 1 : 0, Shutter[i].motordelay);
|
||||
|
||||
} else {
|
||||
// terminate loop at first INVALID Shutter[i].
|
||||
|
@ -380,7 +387,8 @@ void ShutterReportPosition(bool always, uint32_t index)
|
|||
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: rules_flag.shutter_moving: %d, moved %d"), TasmotaGlobal.rules_flag.shutter_moving, TasmotaGlobal.rules_flag.shutter_moved);
|
||||
}
|
||||
|
||||
void ShutterLimitRealAndTargetPositions(uint32_t i) {
|
||||
void ShutterLimitRealAndTargetPositions(uint32_t i)
|
||||
{
|
||||
if (Shutter[i].real_position<0) Shutter[i].real_position = 0;
|
||||
if (Shutter[i].real_position>Shutter[i].open_max) Shutter[i].real_position = Shutter[i].open_max;
|
||||
if (Shutter[i].target_position<0) Shutter[i].target_position = 0;
|
||||
|
@ -461,7 +469,8 @@ void ShutterDecellerateForStop(uint8_t i)
|
|||
}
|
||||
}
|
||||
|
||||
void ShutterPowerOff(uint8_t i) {
|
||||
void ShutterPowerOff(uint8_t i)
|
||||
{
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Stop Shutter %d. Switchmode %d"), i+1,Shutter[i].switch_mode); // fix log to indicate correct shutter number
|
||||
ShutterDecellerateForStop(i);
|
||||
switch (Shutter[i].switch_mode) {
|
||||
|
@ -490,6 +499,9 @@ void ShutterPowerOff(uint8_t i) {
|
|||
// Store current PWM value to ensure proper position after reboot.
|
||||
switch (ShutterGlobal.position_mode) {
|
||||
case SHT_PWM_VALUE:
|
||||
Shutter[i].pwm_value = SHT_DIV_ROUND((Settings->shutter_pwmrange[1][i]-Settings->shutter_pwmrange[0][i]) * Shutter[i].target_position , Shutter[i].open_max)+Settings->shutter_pwmrange[0][i];
|
||||
analogWrite(Pin(GPIO_PWM1, i), Shutter[i].pwm_value);
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: PWM final %d"),Shutter[i].pwm_value);
|
||||
char scmnd[20];
|
||||
#ifdef SHUTTER_CLEAR_PWM_ONSTOP
|
||||
// free the PWM servo lock on stop.
|
||||
|
@ -497,7 +509,7 @@ void ShutterPowerOff(uint8_t i) {
|
|||
#else
|
||||
snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_PWM "%d %d" ), i+1,Shutter[i].pwm_value);
|
||||
#endif
|
||||
ExecuteCommand(scmnd, SRC_BUTTON);
|
||||
//ExecuteCommand(scmnd, SRC_BUTTON);
|
||||
break;
|
||||
}
|
||||
if (Shutter[i].direction !=0) {
|
||||
|
@ -508,7 +520,6 @@ void ShutterPowerOff(uint8_t i) {
|
|||
|
||||
void ShutterUpdatePosition(void)
|
||||
{
|
||||
|
||||
char scommand[CMDSZ];
|
||||
char stopic[TOPSZ];
|
||||
for (uint32_t i = 0; i < TasmotaGlobal.shutters_present; i++) {
|
||||
|
@ -518,12 +529,13 @@ void ShutterUpdatePosition(void)
|
|||
XdrvRulesProcess(0);
|
||||
ShutterGlobal.start_reported = 1;
|
||||
}
|
||||
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Time %d, cStop %d, cVelo %d, mVelo %d, aVelo %d, mRun %d, aPos %d, aPos2 %d, nStop %d, Trgt %d, mVelo %d, Dir %d, Tilt %d"),
|
||||
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Time %d, cStop %d, cVelo %d, mVelo %d, aVelo %d, mRun %d, aPos %d, aPos2 %d, nStop %d, Trgt %d, mVelo %d, Dir %d, Tilt %d, TrgtTilt: %d, Tiltmove: %d"),
|
||||
Shutter[i].time, current_stop_way, current_pwm_velocity, velocity_max, Shutter[i].accelerator, min_runtime_ms, current_real_position,Shutter[i].real_position,
|
||||
next_possible_stop_position, Shutter[i].target_position, velocity_change_per_step_max, Shutter[i].direction,Shutter[i].tilt_real_pos);
|
||||
next_possible_stop_position, Shutter[i].target_position, velocity_change_per_step_max, Shutter[i].direction,Shutter[i].tilt_real_pos, Shutter[i].tilt_target_pos,
|
||||
Shutter[i].tiltmoving);
|
||||
|
||||
if ( (Shutter[i].real_position * Shutter[i].direction >= Shutter[i].target_position * Shutter[i].direction &&
|
||||
Shutter[i].tilt_real_pos * Shutter[i].direction * Shutter[i].tilt_config[2] >= Shutter[i].tilt_target_pos * Shutter[i].direction * Shutter[i].tilt_config[2])
|
||||
if ( ((Shutter[i].real_position * Shutter[i].direction >= Shutter[i].target_position * Shutter[i].direction && Shutter[i].tiltmoving==0) ||
|
||||
((int16_t)Shutter[i].tilt_real_pos * Shutter[i].direction * Shutter[i].tilt_config[2] >= (int16_t)Shutter[i].tilt_target_pos * Shutter[i].direction * Shutter[i].tilt_config[2] && Shutter[i].tiltmoving==1))
|
||||
|| (ShutterGlobal.position_mode == SHT_COUNTER && Shutter[i].accelerator <0 && Shutter[i].pwm_velocity+Shutter[i].accelerator<PWM_MIN)) {
|
||||
if (Shutter[i].direction != 0) {
|
||||
Shutter[i].lastdirection = Shutter[i].direction;
|
||||
|
@ -536,12 +548,16 @@ void ShutterUpdatePosition(void)
|
|||
// manage venetian blinds
|
||||
Shutter[i].tilt_target_pos = Settings->shutter_position[i] == 0 ? Shutter[i].tilt_config[0] : Shutter[i].tilt_target_pos;
|
||||
Shutter[i].tilt_target_pos = Settings->shutter_position[i] == 100 ? Shutter[i].tilt_config[1] : Shutter[i].tilt_target_pos;
|
||||
if (abs(Shutter[i].tilt_real_pos - Shutter[i].tilt_target_pos) > 10) {
|
||||
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Tilt does not match akt %d, target %d"),Shutter[i].tilt_real_pos,Shutter[i].tilt_target_pos);
|
||||
if (abs(Shutter[i].tilt_real_pos - Shutter[i].tilt_target_pos) > Shutter[i].min_TiltChange) {
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("SHT: Tilt not match %d -> %d"),Shutter[i].tilt_real_pos,Shutter[i].tilt_target_pos);
|
||||
XdrvMailbox.payload = -99;
|
||||
XdrvMailbox.index = i+1;
|
||||
Shutter[i].tiltmoving = 1;
|
||||
CmndShutterPosition();
|
||||
return;
|
||||
} else {
|
||||
Settings->shutter_tilt_pos[i] = Shutter[i].tilt_real_pos;
|
||||
Shutter[i].tiltmoving = 0;
|
||||
}
|
||||
ShutterLogPos(i);
|
||||
|
||||
|
@ -558,7 +574,8 @@ void ShutterUpdatePosition(void)
|
|||
}
|
||||
}
|
||||
|
||||
bool ShutterState(uint32_t device) {
|
||||
bool ShutterState(uint32_t device)
|
||||
{
|
||||
if (device > 4) { return false; }
|
||||
device--;
|
||||
device &= 3;
|
||||
|
@ -583,9 +600,10 @@ void ShutterAllowPreStartProcedure(uint8_t i)
|
|||
|
||||
void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos)
|
||||
{
|
||||
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: dir %d, delta1 %d, delta2 %d, grant %d"),direction, (Shutter[i].open_max - Shutter[i].real_position) / Shutter[i].close_velocity, Shutter[i].real_position / Shutter[i].close_velocity, 2+Shutter[i].motordelay);
|
||||
if ( ( ( (1 == direction) && ((Shutter[i].open_max - Shutter[i].real_position) / 100 <= 2))
|
||||
|| ( (-1 == direction) && (Shutter[i].real_position / Shutter[i].close_velocity <= 2)) ) && abs(Shutter[i].tilt_real_pos-Shutter[i].tilt_target_pos)/Shutter[i].tilt_velocity <= 2) {
|
||||
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: dir %d, delta1 %d, delta2 %d"),direction, (Shutter[i].open_max - Shutter[i].real_position) / Shutter[i].close_velocity, Shutter[i].real_position / Shutter[i].close_velocity);
|
||||
if ( ( ( (1 == direction) && ((Shutter[i].open_max - Shutter[i].real_position) <= Shutter[i].min_realPositionChange))
|
||||
|| ( (-1 == direction) && (Shutter[i].real_position <= Shutter[i].min_realPositionChange)) )
|
||||
&& abs(Shutter[i].tilt_real_pos-Shutter[i].tilt_target_pos) <= Shutter[i].min_TiltChange) {
|
||||
ShutterGlobal.skip_relay_change = 1;
|
||||
} else {
|
||||
Shutter[i].pwm_velocity = 0;
|
||||
|
@ -617,7 +635,7 @@ void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos)
|
|||
// i, Shutter[i].venetian_delay, Shutter[i].tilt_real_pos,Shutter[i].direction,(Shutter[i].tilt_config[1]-Shutter[i].tilt_config[0]), Shutter[i].tilt_config[2],Shutter[i].tilt_start_pos,Shutter[i].tilt_target_pos);
|
||||
}
|
||||
}
|
||||
//AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Start shtr%d from %d to %d in direction %d"), i, Shutter[i].start_position, Shutter[i].target_position, Shutter[i].direction);
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Start shtr%d from %d to %d in direction %d"), i, Shutter[i].start_position, Shutter[i].target_position, Shutter[i].direction);
|
||||
}
|
||||
|
||||
int32_t ShutterCalculatePosition(uint32_t i)
|
||||
|
@ -691,6 +709,7 @@ void ShutterRelayChanged(void)
|
|||
case SHT_COUNTER:
|
||||
case SHT_PWM_VALUE:
|
||||
case SHT_PWM_TIME:
|
||||
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: power off manual change"));
|
||||
ShutterPowerOff(i);
|
||||
switch (powerstate_local) {
|
||||
case 1:
|
||||
|
@ -734,7 +753,8 @@ void ShutterRelayChanged(void)
|
|||
} // for (uint32_t i = 0; i < TasmotaGlobal.shutters_present; i++)
|
||||
}
|
||||
|
||||
bool ShutterButtonIsSimultaneousHold(uint32_t button_index, uint32_t shutter_index) {
|
||||
bool ShutterButtonIsSimultaneousHold(uint32_t button_index, uint32_t shutter_index)
|
||||
{
|
||||
// check for simultaneous shutter button hold
|
||||
uint32 min_shutterbutton_hold_timer = -1; // -1 == max(uint32)
|
||||
for (uint32_t i = 0; i < MAX_SHUTTER_KEYS; i++) {
|
||||
|
@ -1074,7 +1094,6 @@ void CmndShutterIncDec(void)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void CmndShutterPosition(void)
|
||||
{
|
||||
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) {
|
||||
|
@ -1121,17 +1140,21 @@ void CmndShutterPosition(void)
|
|||
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: lastsource %d:, real %d, target %d, tiltreal: %d, tilttarget: %d, payload %d"), TasmotaGlobal.last_source, Shutter[index].real_position ,Shutter[index].target_position,Shutter[index].tilt_real_pos, Shutter[index].tilt_target_pos,target_pos_percent);
|
||||
}
|
||||
if ( (target_pos_percent >= 0) && (target_pos_percent <= 100) &&
|
||||
(abs(Shutter[index].target_position - Shutter[index].real_position ) / Shutter[index].close_velocity > 2 ||
|
||||
abs(Shutter[index].tilt_target_pos - Shutter[index].tilt_real_pos ) / Shutter[index].tilt_velocity > 2) ) {
|
||||
(abs(Shutter[index].target_position - Shutter[index].real_position ) > Shutter[index].min_realPositionChange ||
|
||||
abs(Shutter[index].tilt_target_pos - Shutter[index].tilt_real_pos ) > Shutter[index].min_TiltChange) ) {
|
||||
if (Settings->shutter_options[index] & 4) {
|
||||
if (0 == target_pos_percent) Shutter[index].target_position -= 1 * RESOLUTION * STEPS_PER_SECOND;
|
||||
if (100 == target_pos_percent) Shutter[index].target_position += 1 * RESOLUTION * STEPS_PER_SECOND;
|
||||
}
|
||||
int8_t new_shutterdirection = Shutter[index].real_position < Shutter[index].target_position ? 1 : -1;
|
||||
if (Shutter[index].real_position == Shutter[index].target_position) {
|
||||
int8_t new_shutterdirection;
|
||||
if (abs(Shutter[index].target_position - Shutter[index].real_position ) > Shutter[index].min_realPositionChange) {
|
||||
new_shutterdirection = Shutter[index].real_position < Shutter[index].target_position ? 1 : -1;
|
||||
} else {
|
||||
new_shutterdirection = Shutter[index].tilt_real_pos < Shutter[index].tilt_target_pos ? 1 : -1;
|
||||
}
|
||||
|
||||
if (Shutter[index].direction == -new_shutterdirection) {
|
||||
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Stop shutter to reverse direction"));
|
||||
ShutterPowerOff(index);
|
||||
}
|
||||
if (Shutter[index].direction != new_shutterdirection) {
|
||||
|
@ -1203,6 +1226,7 @@ void CmndShutterStopPosition(void)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CmndShutterOpenTime(void)
|
||||
{
|
||||
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) {
|
||||
|
@ -1423,8 +1447,8 @@ void CmndShutterSetHalfway(void)
|
|||
void CmndShutterSetTilt(void)
|
||||
{
|
||||
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) {
|
||||
if (XdrvMailbox.payload != -99 && XdrvMailbox.payload >= Shutter[XdrvMailbox.index -1].tilt_config[0] && XdrvMailbox.payload <= Shutter[XdrvMailbox.index -1].tilt_config[1] ) {
|
||||
Shutter[XdrvMailbox.index -1].tilt_target_pos = XdrvMailbox.payload;
|
||||
if (XdrvMailbox.payload != -99 ) {
|
||||
Shutter[XdrvMailbox.index -1].tilt_target_pos = tmin(tmax(XdrvMailbox.payload, Shutter[XdrvMailbox.index -1].tilt_config[0]), Shutter[XdrvMailbox.index -1].tilt_config[1]);
|
||||
XdrvMailbox.payload = -99;
|
||||
}
|
||||
if ((XdrvMailbox.data_len > 1) && (XdrvMailbox.payload <= 0)) {
|
||||
|
@ -1440,6 +1464,7 @@ void CmndShutterSetTilt(void)
|
|||
}
|
||||
XdrvMailbox.data[0] = '\0';
|
||||
ResponseCmndNumber(Shutter[XdrvMailbox.index -1].tilt_target_pos);
|
||||
Shutter[XdrvMailbox.index -1].tiltmoving = 1;
|
||||
CmndShutterPosition();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue