Shutter continuous improvement (#18701)

* Update xdrv_27_esp32_shutter.ino

* Update xdrv_27_shutter.ino

* Update xdrv_01_9_webserver.ino

* Update xdrv_12_discovery.ino

* shutterinvert

removed slider display to driver
fix wrong invert display

* codereduction+refactor slider

removed webui slider into driver
optimized code

* update slide, fix invert shutters

- refactor sliders into driver
- fix percent calculation on iverted shutters

* fix on realpercent if inverted shutter

* fix ShutterPercentToRealPosition

fix on inverted shutter

* added shutter to bootloop reset

* bugfix integration

* bugfix
This commit is contained in:
stefanbode 2023-05-21 12:25:11 +02:00 committed by GitHub
parent d5ad79985b
commit a76ebaae48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 94 additions and 75 deletions

View File

@ -578,6 +578,7 @@ void setup(void) {
}
if (RtcReboot.fast_reboot_count > Settings->param[P_BOOT_LOOP_OFFSET] +2) { // Restarted 4 times
Settings->rule_enabled = 0; // Disable all rules
Settings->flag3.shutter_mode = 0; // disable shutter support
TasmotaGlobal.no_autoexec = true;
}
if (RtcReboot.fast_reboot_count > Settings->param[P_BOOT_LOOP_OFFSET] +3) { // Restarted 5 times

View File

@ -264,9 +264,6 @@ const char HTTP_MSG_SLIDER_GRADIENT[] PROGMEM =
"<div id='%s' class='r' style='background-image:linear-gradient(to right,%s,%s);'>"
"<input id='sl%d' type='range' min='%d' max='%d' value='%d' onchange='lc(\"%c\",%d,value)'>"
"</div>";
const char HTTP_MSG_SLIDER_SHUTTER[] PROGMEM =
"<div><span class='p'>" D_CLOSE "</span><span class='q'>" D_OPEN "</span></div>"
"<div><input type='range' min='0' max='100' value='%d' onchange='lc(\"u\",%d,value)'></div>";
const char HTTP_MSG_RSTRT[] PROGMEM =
"<br><div style='text-align:center;'>" D_DEVICE_WILL_RESTART "</div><br>";
@ -1229,13 +1226,6 @@ void HandleRoot(void)
} // Settings->flag3.pwm_multi_channels
}
#endif // USE_LIGHT
#ifdef USE_SHUTTER
if (Settings->flag3.shutter_mode) { // SetOption80 - Enable shutter support
for (uint32_t i = 0; i < TasmotaGlobal.shutters_present; i++) {
WSContentSend_P(HTTP_MSG_SLIDER_SHUTTER, ShutterRealToPercentPosition(-9999, i), i+1);
}
}
#endif // USE_SHUTTER
WSContentSend_P(HTTP_TABLE100);
WSContentSend_P(PSTR("<tr>"));
#ifdef USE_SONOFF_IFAN
@ -1258,7 +1248,7 @@ void HandleRoot(void)
int32_t ShutterWebButton;
if (ShutterWebButton = IsShutterWebButton(idx)) {
WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / cols, idx,
(set_button) ? SettingsText(SET_BUTTON1 + idx -1) : ((Settings->shutter_options[abs(ShutterWebButton)-1] & 2) /* is locked */ ? "-" : ((Settings->shutter_options[abs(ShutterWebButton)-1] & 8) /* invert web buttons */ ? ((ShutterWebButton>0) ? "&#9660;" : "&#9650;") : ((ShutterWebButton>0) ? "&#9650;" : "&#9660;"))),
(set_button) ? SettingsText(SET_BUTTON1 + idx -1) : ((ShutterGetOptions(abs(ShutterWebButton)-1) & 2) /* is locked */ ? "-" : ((Settings->shutter_options[abs(ShutterWebButton)-1] & 8) /* invert web buttons */ ? ((ShutterWebButton>0) ? "&#9660;" : "&#9650;") : ((ShutterWebButton>0) ? "&#9650;" : "&#9660;"))),
"");
} else {
#endif // USE_SHUTTER
@ -1410,10 +1400,12 @@ bool HandleRootStatusRefresh(void)
#endif // USE_LIGHT
#ifdef USE_SHUTTER
for (uint32_t j = 1; j <= TasmotaGlobal.shutters_present; j++) {
uint8_t percent;
snprintf_P(webindex, sizeof(webindex), PSTR("u%d"), j);
WebGetArg(webindex, tmp, sizeof(tmp)); // 0 - 100 percent
percent = atoi(tmp);
if (strlen(tmp)) {
snprintf_P(svalue, sizeof(svalue), PSTR("ShutterPosition%d %s"), j, tmp);
snprintf_P(svalue, sizeof(svalue), PSTR("ShutterPosition%d %d"), j, (ShutterGetOptions(j-1) & 1) ? 100 - percent : percent);
ExecuteWebCommand(svalue);
}
}

View File

@ -200,9 +200,9 @@ void TasDiscoverMessage(void) {
light_controller_isCTRGBLinked,
light_subtype);
for (uint32_t i = 0; i < tmin(TasmotaGlobal.shutters_present, MAX_SHUTTERS); i++) {
for (uint32_t i = 0; i < TasmotaGlobal.shutters_present; i++) {
#ifdef USE_SHUTTER
ResponseAppend_P(PSTR("%s%d"), (i > 0 ? "," : ""), Settings->shutter_options[i]);
ResponseAppend_P(PSTR("%s%d"), (i > 0 ? "," : ""), ShutterGetOptions(i));
#else
ResponseAppend_P(PSTR("%s0"), (i > 0 ? "," : ""));
#endif // USE_SHUTTER
@ -210,7 +210,7 @@ void TasDiscoverMessage(void) {
ResponseAppend_P(PSTR("]," // Shutter Options (end)
"\"sht\":[")); // Shutter Tilt (start)
for (uint32_t i = 0; i < tmax(TasmotaGlobal.shutters_present, MAX_SHUTTERS); i++) {
for (uint32_t i = 0; i < TasmotaGlobal.shutters_present; i++) {
#ifdef USE_SHUTTER
ResponseAppend_P(PSTR("%s[%d,%d,%d]"), (i > 0 ? "," : ""),
ShutterGetTiltConfig(0,i),

View File

@ -54,7 +54,10 @@
#define D_ERROR_FILESYSTEM_NOT_READY "SHT: ERROR File system not enabled"
#define D_ERROR_FILE_NOT_FOUND "SHT: ERROR File system not ready or file not found"
//
const char HTTP_MSG_SLIDER_SHUTTER[] PROGMEM =
"<div><span class='p'>%s</span><span class='q'>%s</span></div>"
"<div><input type='range' min='0' max='100' value='%d' onchange='lc(\"u\",%d,value)'></div>";
const uint32_t SHUTTER_VERSION = 0x01010100; // Latest driver version (See settings deltas below)
typedef struct { // depreciated 2023-04-28
@ -364,7 +367,7 @@ bool ShutterStatus(void) {
"\"Mode\":\"%d\","
"\"TiltConfig\":[%d,%d,%d,%d,%d]}"),
i, ShutterSettings.shutter_startrelay[i], ShutterSettings.shutter_startrelay[i] +1, ShutterSettings.shutter_opentime[i], ShutterSettings.shutter_closetime[i],
ShutterSettings.shutter_set50percent[i], ShutterSettings.shutter_motordelay[i], GetBinary8(Settings->shutter_options[i], 4).c_str(),
ShutterSettings.shutter_set50percent[i], ShutterSettings.shutter_motordelay[i], GetBinary8(ShutterSettings.shutter_options[i], 4).c_str(),
ShutterSettings.shuttercoeff[0][i], ShutterSettings.shuttercoeff[1][i], ShutterSettings.shuttercoeff[2][i], ShutterSettings.shuttercoeff[3][i], ShutterSettings.shuttercoeff[4][i],
ShutterSettings.shutter_mode,
ShutterSettings.shutter_tilt_config[0][i], ShutterSettings.shutter_tilt_config[1][i], ShutterSettings.shutter_tilt_config[2][i], ShutterSettings.shutter_tilt_config[3][i], ShutterSettings.shutter_tilt_config[4][i]
@ -389,6 +392,10 @@ uint8_t ShutterGetStartRelay(uint8_t index) {
return ShutterSettings.shutter_startrelay[index];
}
uint8_t ShutterGetOptions(uint8_t index) {
return ShutterSettings.shutter_options[index];
}
int8_t ShutterGetTiltConfig(uint8_t config_idx,uint8_t index) {
return Shutter[index].tilt_config[config_idx];
}
@ -497,13 +504,13 @@ int32_t ShutterPercentToRealPosition(int16_t percent, uint32_t index)
uint8_t ShutterRealToPercentPosition(int32_t realpos, uint32_t index)
{
int64_t realpercent;
if (realpos == -9999) {
realpos = Shutter[index].real_position;
}
if (ShutterSettings.shutter_set50percent[index] != 50) {
return (ShutterSettings.shuttercoeff[2][index] * 5 > realpos/10) ? SHT_DIV_ROUND(realpos/10, ShutterSettings.shuttercoeff[2][index]) : SHT_DIV_ROUND(realpos/10-ShutterSettings.shuttercoeff[0][index]*10, ShutterSettings.shuttercoeff[1][index]);
realpercent = (ShutterSettings.shuttercoeff[2][index] * 5 > realpos/10) ? SHT_DIV_ROUND(realpos/10, ShutterSettings.shuttercoeff[2][index]) : SHT_DIV_ROUND(realpos/10-ShutterSettings.shuttercoeff[0][index]*10, ShutterSettings.shuttercoeff[1][index]);
} else {
int64_t realpercent;
for (uint32_t j = 0; j < 5; j++) {
if (realpos >= Shutter[index].open_max * calibrate_pos[j+1] / 100) {
realpercent = SHT_DIV_ROUND(ShutterSettings.shuttercoeff[j][index], 10);
@ -521,10 +528,10 @@ uint8_t ShutterRealToPercentPosition(int32_t realpos, uint32_t index)
break;
}
}
realpercent = realpercent < 0 ? 0 : realpercent;
// if inverted recalculate the percentposition
return (ShutterSettings.shutter_options[index] & 1) ? 100 - realpercent : realpercent;
}
realpercent = realpercent < 0 ? 0 : realpercent;
// if inverted recalculate the percentposition
return (ShutterSettings.shutter_options[index] & 1) ? 100 - realpercent : realpercent;
}
void ShutterInit(void)
@ -1127,8 +1134,8 @@ void ShutterRelayChanged(void)
// powerstate_local == 1 => direction=1, target=Shutter[i].open_max
// powerstate_local == 2 => direction=-1, target=0 // only happen on SHT_TIME
// powerstate_local == 3 => direction=-1, target=0 // only happen if NOT SHT_TIME
int direction = (powerstate_local == 0) ? 0 : (powerstate_local == 1) ? 1 : -1;
int target = (powerstate_local == 1) ? Shutter[i].open_max : 0;
int8_t direction = (powerstate_local == 0) ? 0 : (powerstate_local == 1) ? 1 : -1;
int8_t target = (powerstate_local == 1) ? Shutter[i].open_max : 0;
if (direction != 0) {
ShutterStartInit(i, direction, target);
@ -1318,6 +1325,11 @@ void ShutterToggle(bool dir)
}
}
void ShutterShow(){
for (uint32_t i = 0; i < TasmotaGlobal.shutters_present; i++) {
WSContentSend_P(HTTP_MSG_SLIDER_SHUTTER, (ShutterSettings.shutter_options[i] & 1) ? D_OPEN : D_CLOSE,(ShutterSettings.shutter_options[i] & 1) ? D_CLOSE : D_OPEN, ShutterRealToPercentPosition(-9999, i), i+1);
}
}
/*********************************************************************************************\
* Commands
\*********************************************************************************************/
@ -2328,6 +2340,11 @@ bool Xdrv27(uint32_t function)
result = false;
}
break;
#ifdef USE_WEBSERVER
case FUNC_WEB_SENSOR:
ShutterShow();
break;
#endif // USE_WEBSERVER
}
}
return result;

View File

@ -72,6 +72,10 @@ int32_t next_possible_stop_position = 0;
int32_t current_real_position = 0;
int32_t current_pwm_velocity = 0;
const char HTTP_MSG_SLIDER_SHUTTER[] PROGMEM =
"<div><span class='p'>%s</span><span class='q'>%s</span></div>"
"<div><input type='range' min='0' max='100' value='%d' onchange='lc(\"u\",%d,value)'></div>";
const uint8_t MAX_MODES = 8;
enum Shutterposition_mode {SHT_UNDEF, SHT_TIME, SHT_TIME_UP_DOWN, SHT_TIME_GARAGE, SHT_COUNTER, SHT_PWM_VALUE, SHT_PWM_TIME,SHT_AUTOCONFIG};
enum Shutterswitch_mode {SHT_SWITCH, SHT_PULSE,};
@ -189,6 +193,10 @@ uint8_t ShutterGetStartRelay(uint8_t index) {
return Settings->shutter_startrelay[index];
}
uint8_t ShutterGetOptions(uint8_t index) {
return Settings->shutter_options[index];
}
int8_t ShutterGetTiltConfig(uint8_t config_idx,uint8_t index) {
return Shutter[index].tilt_config[config_idx];
}
@ -259,6 +267,8 @@ void ShutterRtc50mS(void)
int32_t ShutterPercentToRealPosition(int16_t percent, uint32_t index)
{
// if inverted recalculate the percentposition
percent = (Settings->shutter_options[index] & 1) ? 100 - percent : percent;
if (Settings->shutter_set50percent[index] != 50) {
return (percent <= 5) ? Settings->shuttercoeff[2][index] * percent*10 : (Settings->shuttercoeff[1][index] * percent + (Settings->shuttercoeff[0][index]*10))*10;
} else {
@ -295,13 +305,13 @@ int32_t ShutterPercentToRealPosition(int16_t percent, uint32_t index)
uint8_t ShutterRealToPercentPosition(int32_t realpos, uint32_t index)
{
int64_t realpercent;
if (realpos == -9999) {
realpos = Shutter[index].real_position;
}
if (Settings->shutter_set50percent[index] != 50) {
return (Settings->shuttercoeff[2][index] * 5 > realpos/10) ? SHT_DIV_ROUND(realpos/10, Settings->shuttercoeff[2][index]) : SHT_DIV_ROUND(realpos/10-Settings->shuttercoeff[0][index]*10, Settings->shuttercoeff[1][index]);
realpercent = (Settings->shuttercoeff[2][index] * 5 > realpos/10) ? SHT_DIV_ROUND(realpos/10, Settings->shuttercoeff[2][index]) : SHT_DIV_ROUND(realpos/10-Settings->shuttercoeff[0][index]*10, Settings->shuttercoeff[1][index]);
} else {
int64_t realpercent;
for (uint32_t j = 0; j < 5; j++) {
if (realpos >= Shutter[index].open_max * calibrate_pos[j+1] / 100) {
realpercent = SHT_DIV_ROUND(Settings->shuttercoeff[j][index], 10);
@ -319,8 +329,10 @@ uint8_t ShutterRealToPercentPosition(int32_t realpos, uint32_t index)
break;
}
}
return realpercent < 0 ? 0 : realpercent;
}
realpercent = realpercent < 0 ? 0 : realpercent;
// if inverted recalculate the percentposition
return (Settings->shutter_options[index] & 1) ? 100 - realpercent : realpercent;
}
void ShutterInit(void)
@ -876,52 +888,38 @@ void ShutterRelayChanged(void)
Shutter[i].tiltmoving = 0;
}
switch (ShutterGlobal.position_mode) {
// enum Shutterposition_mode {SHT_TIME, SHT_TIME_UP_DOWN, SHT_TIME_GARAGE, SHT_COUNTER, SHT_PWM_VALUE, SHT_PWM_TIME,};
case SHT_TIME_UP_DOWN:
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:
ShutterStartInit(i, 1, Shutter[i].open_max);
break;
case 3:
ShutterStartInit(i, -1, 0);
break;
default:
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d Switch OFF motor."),i);
// enum Shutterposition_mode {SHT_TIME, SHT_TIME_UP_DOWN, SHT_TIME_GARAGE, SHT_COUNTER, SHT_PWM_VALUE, SHT_PWM_TIME,};
case SHT_TIME_UP_DOWN:
case SHT_COUNTER:
case SHT_PWM_VALUE:
case SHT_PWM_TIME:
case SHT_TIME: {
ShutterPowerOff(i);
// powerstate_local == 0 => direction=0, stop
// powerstate_local == 1 => direction=1, target=Shutter[i].open_max
// powerstate_local == 2 => direction=-1, target=0 // only happen on SHT_TIME
// powerstate_local == 3 => direction=-1, target=0 // only happen if NOT SHT_TIME
int8_t direction = (powerstate_local == 0) ? 0 : (powerstate_local == 1) ? 1 : -1;
int8_t target = (powerstate_local == 1) ? Shutter[i].open_max : 0;
if (direction != 0) {
ShutterStartInit(i, direction, target);
} else {
Shutter[i].target_position = Shutter[i].real_position;
Shutter[i].last_stop_time = millis();
}
break;
case SHT_TIME:
switch (powerstate_local) {
case 1:
ShutterStartInit(i, 1, Shutter[i].open_max);
break;
case 2:
ShutterStartInit(i, -1, 0);
break;
default:
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d Switch OFF motor."),i+1);
Shutter[i].target_position = Shutter[i].real_position;
Shutter[i].last_stop_time = millis();
break;
}
break;
case SHT_TIME_GARAGE:
switch (powerstate_local) {
case 1:
ShutterStartInit(i, Shutter[i].lastdirection*-1 , Shutter[i].lastdirection == 1 ? 0 : Shutter[i].open_max);
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d Garage. NewTarget %d"), i, Shutter[i].target_position);
break;
default:
Shutter[i].target_position = Shutter[i].real_position;
}
} // switch (ShutterGlobal.position_mode)
case SHT_TIME_GARAGE:
switch (powerstate_local) {
case 1:
ShutterStartInit(i, Shutter[i].lastdirection * -1, Shutter[i].lastdirection == 1 ? 0 : Shutter[i].open_max);
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d Garage. NewTarget %d"), i, Shutter[i].target_position);
break;
default:
Shutter[i].target_position = Shutter[i].real_position;
}
}
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d, Target %ld, Power: %d, tiltmv: %d"), i+1, Shutter[i].target_position, powerstate_local,Shutter[i].tiltmoving);
} // if (manual_relays_changed)
} // for (uint32_t i = 0; i < TasmotaGlobal.shutters_present; i++)
@ -940,11 +938,11 @@ bool ShutterButtonIsSimultaneousHold(uint32_t button_index, uint32_t shutter_ind
bool ShutterButtonHandler(void)
{
uint8_t buttonState = SHT_NOT_PRESSED;
uint8_t button = XdrvMailbox.payload;
uint8_t press_index;
uint8_t buttonState = SHT_NOT_PRESSED;
uint8_t button = XdrvMailbox.payload;
uint8_t press_index;
uint32_t button_index = XdrvMailbox.index;
uint8_t shutter_index = Settings->shutter_button[button_index] & 0x03;
uint8_t shutter_index = Settings->shutter_button[button_index] & 0x03;
uint16_t loops_per_second = 1000 / Settings->button_debounce; // ButtonDebounce (50)
if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) {
@ -976,8 +974,8 @@ bool ShutterButtonHandler(void)
Button.hold_timer[button_index] = 0;
} else {
Button.hold_timer[button_index]++;
if (!Settings->flag.button_single) { // SetOption13 (0) - Allow only single button press for immediate action
if (Settings->param[P_HOLD_IGNORE] > 0) { // SetOption40 (0) - Do not ignore button hold
if (!Settings->flag.button_single) { // SetOption13 (0) - Allow only single button press for immediate action
if (Settings->param[P_HOLD_IGNORE] > 0) { // SetOption40 (0) - Do not ignore button hold
if (Button.hold_timer[button_index] > loops_per_second * Settings->param[P_HOLD_IGNORE] / 10) {
Button.hold_timer[button_index] = 0; // Reset button hold counter to stay below hold trigger
Button.press_counter[button_index] = 0; // Discard button press to disable functionality
@ -1159,6 +1157,12 @@ void ShutterToggle(bool dir)
}
}
void ShutterShow(){
for (uint32_t i = 0; i < TasmotaGlobal.shutters_present; i++) {
WSContentSend_P(HTTP_MSG_SLIDER_SHUTTER, (Settings->shutter_options[i] & 1) ? D_OPEN : D_CLOSE,(Settings->shutter_options[i] & 1) ? D_CLOSE : D_OPEN, ShutterRealToPercentPosition(-9999, i), i+1);
}
}
/*********************************************************************************************\
* Commands
\*********************************************************************************************/
@ -1980,6 +1984,11 @@ bool Xdrv27(uint32_t function)
result = true;
}
break;
#ifdef USE_WEBSERVER
case FUNC_WEB_SENSOR:
ShutterShow();
break;
#endif // USE_WEBSERVER
}
}
return result;