Merge pull request #11019 from stefanbode/patch-12

Several bugfixes for stepper motors and buttons
This commit is contained in:
Theo Arends 2021-02-18 14:12:47 +01:00 committed by GitHub
commit dffdfafac1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 97 additions and 30 deletions

View File

@ -662,6 +662,7 @@
#define D_CMND_SHUTTER_ENABLEENDSTOPTIME "EnableEndStopTime" #define D_CMND_SHUTTER_ENABLEENDSTOPTIME "EnableEndStopTime"
#define D_CMND_SHUTTER_INVERTWEBBUTTONS "InvertWebButtons" #define D_CMND_SHUTTER_INVERTWEBBUTTONS "InvertWebButtons"
#define D_CMND_SHUTTER_PWMRANGE "PWMRange" #define D_CMND_SHUTTER_PWMRANGE "PWMRange"
#define D_CMND_SHUTTER_UNITTEST "UnitTest"
// Commands xdrv_32_hotplug.ino // Commands xdrv_32_hotplug.ino
#define D_CMND_HOTPLUG "HotPlug" #define D_CMND_HOTPLUG "HotPlug"

View File

@ -27,6 +27,8 @@
#define SHUTTER_STEPPER #define SHUTTER_STEPPER
#endif #endif
//#define SHUTTER_UNITTEST
#define D_SHUTTER "SHUTTER" #define D_SHUTTER "SHUTTER"
const uint16_t MOTOR_STOP_TIME = 500; // in mS const uint16_t MOTOR_STOP_TIME = 500; // in mS
@ -56,14 +58,16 @@ const char kShutterCommands[] PROGMEM = D_PRFX_SHUTTER "|"
D_CMND_SHUTTER_OPENTIME "|" D_CMND_SHUTTER_CLOSETIME "|" D_CMND_SHUTTER_RELAY "|" D_CMND_SHUTTER_MODE "|" D_CMND_SHUTTER_PWMRANGE "|" D_CMND_SHUTTER_OPENTIME "|" D_CMND_SHUTTER_CLOSETIME "|" D_CMND_SHUTTER_RELAY "|" D_CMND_SHUTTER_MODE "|" D_CMND_SHUTTER_PWMRANGE "|"
D_CMND_SHUTTER_SETHALFWAY "|" D_CMND_SHUTTER_SETCLOSE "|" D_CMND_SHUTTER_SETOPEN "|" D_CMND_SHUTTER_INVERT "|" D_CMND_SHUTTER_CLIBRATION "|" D_CMND_SHUTTER_SETHALFWAY "|" D_CMND_SHUTTER_SETCLOSE "|" D_CMND_SHUTTER_SETOPEN "|" D_CMND_SHUTTER_INVERT "|" D_CMND_SHUTTER_CLIBRATION "|"
D_CMND_SHUTTER_MOTORDELAY "|" D_CMND_SHUTTER_FREQUENCY "|" D_CMND_SHUTTER_BUTTON "|" D_CMND_SHUTTER_LOCK "|" D_CMND_SHUTTER_ENABLEENDSTOPTIME "|" D_CMND_SHUTTER_INVERTWEBBUTTONS "|" D_CMND_SHUTTER_MOTORDELAY "|" D_CMND_SHUTTER_FREQUENCY "|" D_CMND_SHUTTER_BUTTON "|" D_CMND_SHUTTER_LOCK "|" D_CMND_SHUTTER_ENABLEENDSTOPTIME "|" D_CMND_SHUTTER_INVERTWEBBUTTONS "|"
D_CMND_SHUTTER_STOPOPEN "|" D_CMND_SHUTTER_STOPCLOSE "|" D_CMND_SHUTTER_STOPTOGGLE "|" D_CMND_SHUTTER_STOPTOGGLEDIR "|" D_CMND_SHUTTER_STOPPOSITION "|" D_CMND_SHUTTER_INCDEC; D_CMND_SHUTTER_STOPOPEN "|" D_CMND_SHUTTER_STOPCLOSE "|" D_CMND_SHUTTER_STOPTOGGLE "|" D_CMND_SHUTTER_STOPTOGGLEDIR "|" D_CMND_SHUTTER_STOPPOSITION "|" D_CMND_SHUTTER_INCDEC "|"
D_CMND_SHUTTER_UNITTEST "|";
void (* const ShutterCommand[])(void) PROGMEM = { void (* const ShutterCommand[])(void) PROGMEM = {
&CmndShutterOpen, &CmndShutterClose, &CmndShutterToggle, &CmndShutterToggleDir, &CmndShutterStop, &CmndShutterPosition, &CmndShutterOpen, &CmndShutterClose, &CmndShutterToggle, &CmndShutterToggleDir, &CmndShutterStop, &CmndShutterPosition,
&CmndShutterOpenTime, &CmndShutterCloseTime, &CmndShutterRelay, &CmndShutterMode, &CmndShutterPwmRange, &CmndShutterOpenTime, &CmndShutterCloseTime, &CmndShutterRelay, &CmndShutterMode, &CmndShutterPwmRange,
&CmndShutterSetHalfway, &CmndShutterSetClose, &CmndShutterSetOpen, &CmndShutterInvert, &CmndShutterCalibration , &CmndShutterMotorDelay, &CmndShutterSetHalfway, &CmndShutterSetClose, &CmndShutterSetOpen, &CmndShutterInvert, &CmndShutterCalibration , &CmndShutterMotorDelay,
&CmndShutterFrequency, &CmndShutterButton, &CmndShutterLock, &CmndShutterEnableEndStopTime, &CmndShutterInvertWebButtons, &CmndShutterFrequency, &CmndShutterButton, &CmndShutterLock, &CmndShutterEnableEndStopTime, &CmndShutterInvertWebButtons,
&CmndShutterStopOpen, &CmndShutterStopClose, &CmndShutterStopToggle, &CmndShutterStopToggleDir, &CmndShutterStopPosition, &CmndShutterIncDec}; &CmndShutterStopOpen, &CmndShutterStopClose, &CmndShutterStopToggle, &CmndShutterStopToggleDir, &CmndShutterStopPosition, &CmndShutterIncDec,
&CmndShutterUnitTest};
const char JSON_SHUTTER_POS[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Position\":%d,\"Direction\":%d,\"Target\":%d}"; const char JSON_SHUTTER_POS[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Position\":%d,\"Direction\":%d,\"Target\":%d}";
const char JSON_SHUTTER_BUTTON[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Button%d\":%d}"; const char JSON_SHUTTER_BUTTON[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Button%d\":%d}";
@ -107,7 +111,7 @@ void ShutterLogPos(uint32_t i)
{ {
char stemp2[10]; char stemp2[10];
dtostrfd((float)Shutter[i].time / STEPS_PER_SECOND, 2, stemp2); dtostrfd((float)Shutter[i].time / STEPS_PER_SECOND, 2, stemp2);
AddLog_P(LOG_LEVEL_DEBUG, PSTR("SHT: Shtr%d Real %d, Start %d, Stop %d, Dir %d, Delay %d, Rtc %s [s], Freq %d, PWM %d"), AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Shtr%d Real %d, Start %d, Stop %d, Dir %d, Delay %d, Rtc %s [s], Freq %d, PWM %d"),
i+1, Shutter[i].real_position, Shutter[i].start_position, Shutter[i].target_position, Shutter[i].direction, Shutter[i].motordelay, stemp2, Shutter[i].pwm_velocity, Shutter[i].pwm_value); i+1, Shutter[i].real_position, Shutter[i].start_position, Shutter[i].target_position, Shutter[i].direction, Shutter[i].motordelay, stemp2, Shutter[i].pwm_velocity, Shutter[i].pwm_value);
} }
@ -123,6 +127,9 @@ void ShutterUpdateVelocity(uint8_t i)
// will be calles through RTC every 50ms. // will be calles through RTC every 50ms.
Shutter[i].pwm_velocity += Shutter[i].accelerator; Shutter[i].pwm_velocity += Shutter[i].accelerator;
Shutter[i].pwm_velocity = tmax(0,tmin(Shutter[i].direction==1 ? ShutterGlobal.open_velocity_max : Shutter[i].close_velocity_max,Shutter[i].pwm_velocity)); Shutter[i].pwm_velocity = tmax(0,tmin(Shutter[i].direction==1 ? ShutterGlobal.open_velocity_max : Shutter[i].close_velocity_max,Shutter[i].pwm_velocity));
if (ShutterGlobal.position_mode == SHT_COUNTER) {
Shutter[i].pwm_velocity = tmax(100,Shutter[i].pwm_velocity);
}
} }
void ShutterRtc50mS(void) void ShutterRtc50mS(void)
@ -173,15 +180,15 @@ int32_t ShutterPercentToRealPosition(int16_t percent, uint32_t index)
for (uint32_t k = 0; k < 5; k++) { for (uint32_t k = 0; k < 5; k++) {
if ((percent * 10) >= Settings.shuttercoeff[k][index]) { if ((percent * 10) >= Settings.shuttercoeff[k][index]) {
realpos = SHT_DIV_ROUND(Shutter[index].open_max * calibrate_pos[k+1], 100); realpos = SHT_DIV_ROUND(Shutter[index].open_max * calibrate_pos[k+1], 100);
//AddLog_P(LOG_LEVEL_ERROR, PSTR("SHT: Realposition TEMP1: %d, %d %%, coeff %d"), realpos, percent, Settings.shuttercoeff[k][index]); //AddLog(LOG_LEVEL_ERROR, PSTR("SHT: Realposition TEMP1: %d, %d %%, coeff %d"), realpos, percent, Settings.shuttercoeff[k][index]);
} else { } else {
//AddLog_P(LOG_LEVEL_ERROR, PSTR("SHT: Shutter[%d].open_max: %d"),index, Shutter[index].open_max); //AddLog(LOG_LEVEL_ERROR, PSTR("SHT: Shutter[%d].open_max: %d"),index, Shutter[index].open_max);
if (0 == k) { if (0 == k) {
realpos = SHT_DIV_ROUND((int64_t)percent * Shutter[index].open_max * calibrate_pos[k+1], Settings.shuttercoeff[k][index]*10 ); realpos = SHT_DIV_ROUND((int64_t)percent * Shutter[index].open_max * calibrate_pos[k+1], Settings.shuttercoeff[k][index]*10 );
//AddLog_P(LOG_LEVEL_ERROR, PSTR("SHT: Realposition TEMP3: %d, %d %%, coeff %d"), realpos, percent, Settings.shuttercoeff[k][index]); //AddLog(LOG_LEVEL_ERROR, PSTR("SHT: Realposition TEMP3: %d, %d %%, coeff %d"), realpos, percent, Settings.shuttercoeff[k][index]);
} else { } else {
//uint32_t addon = ( percent*10 - Settings.shuttercoeff[k-1][index] ) * Shutter[index].open_max * (calibrate_pos[k+1] - calibrate_pos[k]) / (Settings.shuttercoeff[k][index] -Settings.shuttercoeff[k-1][index]) / 100; //uint32_t addon = ( percent*10 - Settings.shuttercoeff[k-1][index] ) * Shutter[index].open_max * (calibrate_pos[k+1] - calibrate_pos[k]) / (Settings.shuttercoeff[k][index] -Settings.shuttercoeff[k-1][index]) / 100;
//AddLog_P(LOG_LEVEL_ERROR, PSTR("SHT: Realposition TEMP2: %d, %d %%, coeff %d"), addon, (calibrate_pos[k+1] - calibrate_pos[k]), (Settings.shuttercoeff[k][index] -Settings.shuttercoeff[k-1][index])); //AddLog(LOG_LEVEL_ERROR, PSTR("SHT: Realposition TEMP2: %d, %d %%, coeff %d"), addon, (calibrate_pos[k+1] - calibrate_pos[k]), (Settings.shuttercoeff[k][index] -Settings.shuttercoeff[k-1][index]));
realpos += SHT_DIV_ROUND(((int64_t)percent*10 - Settings.shuttercoeff[k-1][index] ) * Shutter[index].open_max * (calibrate_pos[k+1] - calibrate_pos[k]), (Settings.shuttercoeff[k][index] - Settings.shuttercoeff[k-1][index])*100); realpos += SHT_DIV_ROUND(((int64_t)percent*10 - Settings.shuttercoeff[k-1][index] ) * Shutter[index].open_max * (calibrate_pos[k+1] - calibrate_pos[k]), (Settings.shuttercoeff[k][index] - Settings.shuttercoeff[k-1][index])*100);
} }
break; break;
@ -200,15 +207,15 @@ uint8_t ShutterRealToPercentPosition(int32_t realpos, uint32_t index)
for (uint32_t j = 0; j < 5; j++) { for (uint32_t j = 0; j < 5; j++) {
if (realpos >= Shutter[index].open_max * calibrate_pos[j+1] / 100) { if (realpos >= Shutter[index].open_max * calibrate_pos[j+1] / 100) {
realpercent = SHT_DIV_ROUND(Settings.shuttercoeff[j][index], 10); realpercent = SHT_DIV_ROUND(Settings.shuttercoeff[j][index], 10);
//AddLog_P(LOG_LEVEL_ERROR, PSTR("SHT: Realpercent TEMP1: %d %%, %d, coeff %d"), realpercent, realpos, Shutter[index].open_max * calibrate_pos[j+1] / 100); //AddLog(LOG_LEVEL_ERROR, PSTR("SHT: Realpercent TEMP1: %d %%, %d, coeff %d"), realpercent, realpos, Shutter[index].open_max * calibrate_pos[j+1] / 100);
} else { } else {
//AddLog_P(LOG_LEVEL_ERROR, PSTR("SHT: Shutter[%d].open_max: %d"),index, Shutter[index].open_max); //AddLog(LOG_LEVEL_ERROR, PSTR("SHT: Shutter[%d].open_max: %d"),index, Shutter[index].open_max);
if (0 == j) { if (0 == j) {
realpercent = SHT_DIV_ROUND(((int64_t)realpos - SHT_DIV_ROUND(Shutter[index].open_max * calibrate_pos[j], 100)) * Settings.shuttercoeff[j][index], calibrate_pos[j+1]/10*Shutter[index].open_max); realpercent = SHT_DIV_ROUND(((int64_t)realpos - SHT_DIV_ROUND(Shutter[index].open_max * calibrate_pos[j], 100)) * Settings.shuttercoeff[j][index], calibrate_pos[j+1]/10*Shutter[index].open_max);
} else { } else {
//uint16_t addon = ( realpos - (Shutter[index].open_max * calibrate_pos[j] / 100) ) * 10 * (Settings.shuttercoeff[j][index] - Settings.shuttercoeff[j-1][index]) / (calibrate_pos[j+1] - calibrate_pos[j])/Shutter[index].open_max; //uint16_t addon = ( realpos - (Shutter[index].open_max * calibrate_pos[j] / 100) ) * 10 * (Settings.shuttercoeff[j][index] - Settings.shuttercoeff[j-1][index]) / (calibrate_pos[j+1] - calibrate_pos[j])/Shutter[index].open_max;
//uint16_t addon = ( realpercent*10 - Settings.shuttercoeff[j-1][index] ) * Shutter[index].open_max * (calibrate_pos[j+1] - calibrate_pos[j]) / (Settings.shuttercoeff[j][index] -Settings.shuttercoeff[j-1][index]) / 100; //uint16_t addon = ( realpercent*10 - Settings.shuttercoeff[j-1][index] ) * Shutter[index].open_max * (calibrate_pos[j+1] - calibrate_pos[j]) / (Settings.shuttercoeff[j][index] -Settings.shuttercoeff[j-1][index]) / 100;
//AddLog_P(LOG_LEVEL_ERROR, PSTR("SHT: Realpercent TEMP2: %d %%, delta %d, %d, coeff %d"), addon,( realpos - (Shutter[index].open_max * calibrate_pos[j] / 100) ) , (calibrate_pos[j+1] - calibrate_pos[j])* Shutter[index].open_max/100, (Settings.shuttercoeff[j][index] -Settings.shuttercoeff[j-1][index])); //AddLog(LOG_LEVEL_ERROR, PSTR("SHT: Realpercent TEMP2: %d %%, delta %d, %d, coeff %d"), addon,( realpos - (Shutter[index].open_max * calibrate_pos[j] / 100) ) , (calibrate_pos[j+1] - calibrate_pos[j])* Shutter[index].open_max/100, (Settings.shuttercoeff[j][index] -Settings.shuttercoeff[j-1][index]));
realpercent += SHT_DIV_ROUND(((int64_t)realpos - SHT_DIV_ROUND(Shutter[index].open_max * calibrate_pos[j], 100)) * (Settings.shuttercoeff[j][index] - Settings.shuttercoeff[j-1][index]), (calibrate_pos[j+1] - calibrate_pos[j])/10*Shutter[index].open_max) ; realpercent += SHT_DIV_ROUND(((int64_t)realpos - SHT_DIV_ROUND(Shutter[index].open_max * calibrate_pos[j], 100)) * (Settings.shuttercoeff[j][index] - Settings.shuttercoeff[j-1][index]), (calibrate_pos[j+1] - calibrate_pos[j])/10*Shutter[index].open_max) ;
} }
break; break;
@ -254,7 +261,7 @@ void ShutterInit(void)
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Mode undef.. calculate...")); AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Mode undef.. calculate..."));
for (uint32_t j = 0; j < MAX_INTERLOCKS * Settings.flag.interlock; j++) { // CMND_INTERLOCK - Enable/disable interlock for (uint32_t j = 0; j < MAX_INTERLOCKS * Settings.flag.interlock; j++) { // CMND_INTERLOCK - Enable/disable interlock
//AddLog_P(LOG_LEVEL_DEBUG, PSTR("SHT: Interlock state i=%d %d, flag %d, Shuttermask %d, MaskedIL %d"),i, Settings.interlock[i], Settings.flag.interlock,ShutterGlobal.RelayShutterMask, Settings.interlock[i]&ShutterGlobal.RelayShutterMask); //AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Interlock state i=%d %d, flag %d, Shuttermask %d, MaskedIL %d"),i, Settings.interlock[i], Settings.flag.interlock,ShutterGlobal.RelayShutterMask, Settings.interlock[i]&ShutterGlobal.RelayShutterMask);
if (Settings.interlock[j] && (Settings.interlock[j] & ShutterGlobal.RelayShutterMask)) { if (Settings.interlock[j] && (Settings.interlock[j] & ShutterGlobal.RelayShutterMask)) {
//AddLog_P(LOG_LEVEL_DEBUG, PSTR("SHT: Relay in Interlock group")); //AddLog_P(LOG_LEVEL_DEBUG, PSTR("SHT: Relay in Interlock group"));
relay_in_interlock = true; relay_in_interlock = true;
@ -293,7 +300,7 @@ void ShutterInit(void)
Settings.shuttercoeff[1][i] = Shutter[i].open_max/10 * (100 - Settings.shutter_set50percent[i] ) / 5000 ; Settings.shuttercoeff[1][i] = Shutter[i].open_max/10 * (100 - Settings.shutter_set50percent[i] ) / 5000 ;
Settings.shuttercoeff[0][i] = Shutter[i].open_max/100 - (Settings.shuttercoeff[1][i] * 10); Settings.shuttercoeff[0][i] = Shutter[i].open_max/100 - (Settings.shuttercoeff[1][i] * 10);
Settings.shuttercoeff[2][i] = (int32_t)(Settings.shuttercoeff[0][i]*10 + 5 * Settings.shuttercoeff[1][i]) / 5; Settings.shuttercoeff[2][i] = (int32_t)(Settings.shuttercoeff[0][i]*10 + 5 * Settings.shuttercoeff[1][i]) / 5;
//AddLog_P(LOG_LEVEL_DEBUG, PSTR("SHT: Shtr%d Shutter[i].open_max %d, 50perc:%d, 0:%d, 1:%d 2:%d"), i, Shutter[i].open_max, Settings.shutter_set50percent[i], Settings.shuttercoeff[0][i],Settings.shuttercoeff[1][i],Settings.shuttercoeff[2][i]); //AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Shtr%d Shutter[i].open_max %d, 50perc:%d, 0:%d, 1:%d 2:%d"), i, Shutter[i].open_max, Settings.shutter_set50percent[i], Settings.shuttercoeff[0][i],Settings.shuttercoeff[1][i],Settings.shuttercoeff[2][i]);
} }
ShutterGlobal.RelayShutterMask |= 3 << (Settings.shutter_startrelay[i] -1); ShutterGlobal.RelayShutterMask |= 3 << (Settings.shutter_startrelay[i] -1);
@ -313,8 +320,8 @@ void ShutterInit(void)
} }
Shutter[i].close_velocity_max = ShutterGlobal.open_velocity_max*Shutter[i].open_time / Shutter[i].close_time; Shutter[i].close_velocity_max = ShutterGlobal.open_velocity_max*Shutter[i].open_time / Shutter[i].close_time;
//AddLog_P(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_MORE, PSTR("SHT: Shtr%d Openvel %d, Closevel: %d"),i, ShutterGlobal.open_velocity_max, Shutter[i].close_velocity_max);
AddLog_P(LOG_LEVEL_DEBUG, PSTR("SHT: Shtr%d Init. Pos %d, Inverted %d, Locked %d, End stop time enabled %d, webButtons inverted %d"), AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Shtr%d Init. Pos %d, Inverted %d, Locked %d, End stop time enabled %d, webButtons inverted %d"),
i+1, Shutter[i].real_position, 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); (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);
@ -338,7 +345,7 @@ void ShutterReportPosition(bool always, uint32_t index)
n = index+1; n = index+1;
} }
for (i; i < n; i++) { for (i; i < n; i++) {
//AddLog_P(LOG_LEVEL_DEBUG, PSTR("SHT: Shtr%d Real Pos %d"), i+1,Shutter[i].real_position); //AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Shtr%d Real Pos %d"), i+1,Shutter[i].real_position);
uint32_t position = ShutterRealToPercentPosition(Shutter[i].real_position, i); uint32_t position = ShutterRealToPercentPosition(Shutter[i].real_position, i);
if (Shutter[i].direction != 0) { if (Shutter[i].direction != 0) {
TasmotaGlobal.rules_flag.shutter_moving = 1; TasmotaGlobal.rules_flag.shutter_moving = 1;
@ -352,7 +359,7 @@ void ShutterReportPosition(bool always, uint32_t index)
if (always || (TasmotaGlobal.rules_flag.shutter_moving)) { if (always || (TasmotaGlobal.rules_flag.shutter_moving)) {
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR(D_PRFX_SHUTTER)); // RulesProcess() now re-entry protected MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR(D_PRFX_SHUTTER)); // RulesProcess() now re-entry protected
} }
//AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: rules_flag.shutter_moving: %d, moved %d"), TasmotaGlobal.rules_flag.shutter_moving, TasmotaGlobal.rules_flag.shutter_moved); //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) {
@ -399,11 +406,12 @@ void ShutterDecellerateForStop(uint8_t i)
case SHT_COUNTER: case SHT_COUNTER:
int16_t missing_steps; int16_t missing_steps;
Shutter[i].accelerator = -(ShutterGlobal.open_velocity_max / (Shutter[i].motordelay>4 ? (Shutter[i].motordelay*11)/10 : 4) ); Shutter[i].accelerator = -(ShutterGlobal.open_velocity_max / (Shutter[i].motordelay>4 ? (Shutter[i].motordelay*11)/10 : 4) );
while (Shutter[i].pwm_velocity > -2*Shutter[i].accelerator ) { while (Shutter[i].pwm_velocity > -2*Shutter[i].accelerator && Shutter[i].pwm_velocity > 100) {
delay(50);
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Velocity %ld, Delta %d"), Shutter[i].pwm_velocity, Shutter[i].accelerator ); AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Velocity %ld, Delta %d"), Shutter[i].pwm_velocity, Shutter[i].accelerator );
//Shutter[i].pwm_velocity = tmax(Shutter[i].pwm_velocity-Shutter[i].accelerator , 0); //Shutter[i].pwm_velocity = tmax(Shutter[i].pwm_velocity-Shutter[i].accelerator , 0);
// Control will be done in RTC Ticker. // Control will be done in RTC Ticker.
delay(50);
} }
if (ShutterGlobal.position_mode == SHT_COUNTER){ if (ShutterGlobal.position_mode == SHT_COUNTER){
missing_steps = ((Shutter[i].target_position-Shutter[i].start_position)*Shutter[i].direction*ShutterGlobal.open_velocity_max/RESOLUTION/STEPS_PER_SECOND) - RtcSettings.pulse_counter[i]; missing_steps = ((Shutter[i].target_position-Shutter[i].start_position)*Shutter[i].direction*ShutterGlobal.open_velocity_max/RESOLUTION/STEPS_PER_SECOND) - RtcSettings.pulse_counter[i];
@ -415,7 +423,6 @@ void ShutterDecellerateForStop(uint8_t i)
analogWrite(Pin(GPIO_PWM1, i), 50); analogWrite(Pin(GPIO_PWM1, i), 50);
Shutter[i].pwm_velocity = 0; Shutter[i].pwm_velocity = 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) { 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) {
delay(1);
} }
analogWrite(Pin(GPIO_PWM1, i), 0); // removed with 8.3 because of reset caused by watchog analogWrite(Pin(GPIO_PWM1, i), 0); // removed with 8.3 because of reset caused by watchog
Shutter[i].real_position = ShutterCalculatePosition(i); Shutter[i].real_position = ShutterCalculatePosition(i);
@ -489,7 +496,7 @@ void ShutterUpdatePosition(void)
Shutter[i].time, toBeAcc, current_stop_way, Shutter[i].pwm_velocity, velocity_max, Shutter[i].accelerator, min_runtime_ms, Shutter[i].real_position, Shutter[i].time, toBeAcc, current_stop_way, Shutter[i].pwm_velocity, velocity_max, Shutter[i].accelerator, min_runtime_ms, Shutter[i].real_position,
next_possible_stop_position, Shutter[i].target_position, velocity_change_per_step_max, Shutter[i].direction); next_possible_stop_position, Shutter[i].target_position, velocity_change_per_step_max, Shutter[i].direction);
if ( Shutter[i].real_position * Shutter[i].direction >= Shutter[i].target_position * Shutter[i].direction || Shutter[i].pwm_velocity<velocity_change_per_step_max) { if ( Shutter[i].real_position * Shutter[i].direction + 2*Shutter[i].pwm_velocity >= Shutter[i].target_position * Shutter[i].direction ) {
if (Shutter[i].direction != 0) { if (Shutter[i].direction != 0) {
Shutter[i].lastdirection = Shutter[i].direction; Shutter[i].lastdirection = Shutter[i].direction;
} }
@ -563,9 +570,9 @@ void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos)
ShutterGlobal.skip_relay_change = 0; ShutterGlobal.skip_relay_change = 0;
TasmotaGlobal.rules_flag.shutter_moved = 0; TasmotaGlobal.rules_flag.shutter_moved = 0;
ShutterGlobal.start_reported = 0; ShutterGlobal.start_reported = 0;
//AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: real %d, start %d, counter %d,freq_max %d, dir %d, freq %d"),Shutter[i].real_position, Shutter[i].start_position ,RtcSettings.pulse_counter[i],ShutterGlobal.open_velocity_max , Shutter[i].direction ,ShutterGlobal.open_velocity_max ); //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: real %d, start %d, counter %d,freq_max %d, dir %d, freq %d"),Shutter[i].real_position, Shutter[i].start_position ,RtcSettings.pulse_counter[i],ShutterGlobal.open_velocity_max , Shutter[i].direction ,ShutterGlobal.open_velocity_max );
} }
//AddLog_P(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) int32_t ShutterCalculatePosition(uint32_t i)
@ -574,7 +581,7 @@ int32_t ShutterCalculatePosition(uint32_t i)
if (Shutter[i].direction != 0) { if (Shutter[i].direction != 0) {
switch (ShutterGlobal.position_mode) { switch (ShutterGlobal.position_mode) {
case SHT_COUNTER: case SHT_COUNTER:
return ((int32_t)RtcSettings.pulse_counter[i]*Shutter[i].direction*STEPS_PER_SECOND / ShutterGlobal.open_velocity_max * RESOLUTION)+Shutter[i].start_position; return ((int64_t)RtcSettings.pulse_counter[i]*Shutter[i].direction*STEPS_PER_SECOND * RESOLUTION / ShutterGlobal.open_velocity_max)+Shutter[i].start_position;
break; break;
case SHT_TIME: case SHT_TIME:
case SHT_TIME_UP_DOWN: case SHT_TIME_UP_DOWN:
@ -618,7 +625,7 @@ void ShutterRelayChanged(void)
if (Shutter[i].direction != 0 && powerstate_local) { if (Shutter[i].direction != 0 && powerstate_local) {
Shutter[i].target_position = Shutter[i].real_position; Shutter[i].target_position = Shutter[i].real_position;
powerstate_local = 0; powerstate_local = 0;
AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d, Switch OFF motor. Target %ld, Source %s, Powerstate %ld, RelayMask %d, ManualChange %d"), AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d, Switch OFF motor. Target %ld, Source %s, Powerstate %ld, RelayMask %d, ManualChange %d"),
i+1, Shutter[i].target_position, GetTextIndexed(stemp1, sizeof(stemp1), TasmotaGlobal.last_source, kCommandSource), powerstate_local,ShutterGlobal.RelayCurrentMask,manual_relays_changed); i+1, Shutter[i].target_position, GetTextIndexed(stemp1, sizeof(stemp1), TasmotaGlobal.last_source, kCommandSource), powerstate_local,ShutterGlobal.RelayCurrentMask,manual_relays_changed);
} }
break; break;
@ -641,7 +648,7 @@ void ShutterRelayChanged(void)
ShutterStartInit(i, -1, 0); ShutterStartInit(i, -1, 0);
break; break;
default: default:
//AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d Switch OFF motor."),i); //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d Switch OFF motor."),i);
Shutter[i].target_position = Shutter[i].real_position; Shutter[i].target_position = Shutter[i].real_position;
} }
break; break;
@ -654,7 +661,7 @@ void ShutterRelayChanged(void)
ShutterStartInit(i, -1, 0); ShutterStartInit(i, -1, 0);
break; break;
default: default:
//AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d Switch OFF motor."),i); //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d Switch OFF motor."),i);
Shutter[i].target_position = Shutter[i].real_position; Shutter[i].target_position = Shutter[i].real_position;
} }
break; break;
@ -761,7 +768,7 @@ void ShutterButtonHandler(void)
// check for simultaneous shutter button press // check for simultaneous shutter button press
uint32 min_shutterbutton_press_counter = -1; // -1 == max(uint32) uint32 min_shutterbutton_press_counter = -1; // -1 == max(uint32)
for (uint32_t i = 0; i < MAX_SHUTTER_KEYS; i++) { for (uint32_t i = 0; i < MAX_SHUTTER_KEYS; i++) {
AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: ShutterButton[i] %ld, ShutterIndex %d, ButtonPressCounter[i] %d, minShutterButtonPressCounter %d, i %d"), AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: ShutterButton[i] %ld, ShutterIndex %d, ButtonPressCounter[i] %d, minShutterButtonPressCounter %d, i %d"),
Settings.shutter_button[i], shutter_index, Button.press_counter[i] , min_shutterbutton_press_counter, i); Settings.shutter_button[i], shutter_index, Button.press_counter[i] , min_shutterbutton_press_counter, i);
if ((button_index != i) && (Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (i != button_index) && (Button.press_counter[i] < min_shutterbutton_press_counter)) { if ((button_index != i) && (Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (i != button_index) && (Button.press_counter[i] < min_shutterbutton_press_counter)) {
min_shutterbutton_press_counter = Button.press_counter[i]; min_shutterbutton_press_counter = Button.press_counter[i];
@ -835,7 +842,7 @@ void ShutterButtonHandler(void)
CmndShutterStop(); CmndShutterStop();
} else { } else {
XdrvMailbox.payload = position = (position-1)<<1; XdrvMailbox.payload = position = (position-1)<<1;
//AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d -> %d"), shutter_index+1, position); //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d -> %d"), shutter_index+1, position);
if (102 == position) { if (102 == position) {
XdrvMailbox.payload = XdrvMailbox.index; XdrvMailbox.payload = XdrvMailbox.index;
CmndShutterToggle(); CmndShutterToggle();
@ -883,7 +890,7 @@ void ShutterToggle(bool dir)
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) {
uint32_t index = XdrvMailbox.index-1; uint32_t index = XdrvMailbox.index-1;
if (dir) { if (dir) {
XdrvMailbox.payload = (Shutter[index].lastdirection > 0) ? 0 : 100; XdrvMailbox.payload = (Shutter[index].direction==0 ? ((Shutter[index].lastdirection > 0) ? 0 : 100) : (Shutter[index].direction > 0) ? 0 : 100);
} }
else { else {
XdrvMailbox.payload = (50 < ShutterRealToPercentPosition(Shutter[index].real_position, index)) ? 0 : 100; XdrvMailbox.payload = (50 < ShutterRealToPercentPosition(Shutter[index].real_position, index)) ? 0 : 100;
@ -994,6 +1001,7 @@ void CmndShutterStop(void)
} }
if (XdrvMailbox.command) if (XdrvMailbox.command)
ResponseCmndDone(); ResponseCmndDone();
ShutterUpdatePosition();
} else { } else {
if (XdrvMailbox.command) if (XdrvMailbox.command)
ResponseCmndIdxChar("Locked"); ResponseCmndIdxChar("Locked");
@ -1082,7 +1090,7 @@ void CmndShutterPosition(void)
// power on // power on
ExecuteCommandPowerShutter(Settings.shutter_startrelay[index], 1, SRC_SHUTTER); ExecuteCommandPowerShutter(Settings.shutter_startrelay[index], 1, SRC_SHUTTER);
} }
if (ShutterGlobal.position_mode != SHT_TIME_UP_DOWN) ExecuteCommandPowerShutter(Settings.shutter_startrelay[index]+2, 1, SRC_SHUTTER); //if (ShutterGlobal.position_mode != SHT_TIME_UP_DOWN) ExecuteCommandPowerShutter(Settings.shutter_startrelay[index]+2, 1, SRC_SHUTTER);
break; break;
case SHT_TIME: case SHT_TIME:
if (!ShutterGlobal.skip_relay_change) { if (!ShutterGlobal.skip_relay_change) {
@ -1551,3 +1559,61 @@ bool Xdrv27(uint8_t function)
} }
#endif //USE_SHUTTER #endif //USE_SHUTTER
#ifdef SHUTTER_UNITTEST
void CmndShutterUnitTest(void) {
int16_t input_percent[10] = {-5,0,10,26,35,55,80,99,100,105};
int16_t output_percent[10] = {0,0,10,26,35,55,80,99,100,100};
uint32_t result_percent[2][2][10] = {{{0,0,24000,62400,84000,132000,192000,237600,240000,240000},
{0,0,360000,936000,1260000,1980000,2880000,3564000,3600000,3600000}},
{{0,0,76296,100000,113333,174299,205795,237983,240000,240000},
{0,0,1144444,1500000,1700000,2614488,3086929,3569748,3600000,3600000}}};
uint32_t result = 0;
char svalue[50]; // Command and number parameter
Settings.shuttercoeff[0][0] = 0;
for (uint8_t i=0; i<2 ; i++){
snprintf_P(svalue, sizeof(svalue), PSTR(D_PRFX_SHUTTER D_CMND_SHUTTER_OPENTIME "%d %d"), 1, 12);
ExecuteCommand(svalue, SRC_SHUTTER);
ShutterInit();
for (uint8_t j=0; j<2 ; j++){
for (uint8_t k=0; k<10 ; k++){
result += (result_percent[i][j][k] == ShutterPercentToRealPosition(input_percent[k] , 0) ? 0 : 1);
AddLog(LOG_LEVEL_ERROR, PSTR("SHT: ShutterPercentToRealPosition error %d: %d <-> %d"),result, ShutterPercentToRealPosition(input_percent[k] , 0), result_percent[i][j][k]);
}
snprintf_P(svalue, sizeof(svalue), PSTR(D_PRFX_SHUTTER D_CMND_SHUTTER_OPENTIME "%d %d"), 1, 180);
ExecuteCommand(svalue, SRC_SHUTTER);
}
snprintf_P(svalue, sizeof(svalue), PSTR(D_PRFX_SHUTTER D_CMND_SHUTTER_CLIBRATION "%d %s"), 1, "15 83 105 185 210");
ExecuteCommand(svalue, SRC_SHUTTER);
}
if (!result){
AddLog(LOG_LEVEL_ERROR, PSTR("SHT: ShutterPercentToRealPosition: PASS"));
} else {
AddLog(LOG_LEVEL_ERROR, PSTR("SHT: ShutterPercentToRealPosition: FAIL"));
}
Settings.shuttercoeff[0][0] = 0;
for (uint8_t i=0; i<2 ; i++){
snprintf_P(svalue, sizeof(svalue), PSTR(D_PRFX_SHUTTER D_CMND_SHUTTER_OPENTIME "%d %d"), 1, 12);
ExecuteCommand(svalue, SRC_SHUTTER);
ShutterInit();
for (uint8_t j=0; j<2 ; j++){
for (uint8_t k=0; k<10 ; k++){
result += (output_percent[k] == ShutterRealToPercentPosition(result_percent[i][j][k] , 0) ? 0 : 1);
AddLog(LOG_LEVEL_ERROR, PSTR("SHT: ShutterRealToPercentPosition error %d: %d <-> %d"),result, ShutterRealToPercentPosition(result_percent[i][j][k] , 0), output_percent[k]);
}
snprintf_P(svalue, sizeof(svalue), PSTR(D_PRFX_SHUTTER D_CMND_SHUTTER_OPENTIME "%d %d"), 1, 180);
ExecuteCommand(svalue, SRC_SHUTTER);
}
snprintf_P(svalue, sizeof(svalue), PSTR(D_PRFX_SHUTTER D_CMND_SHUTTER_CLIBRATION "%d %s"), 1, "15 83 105 185 210");
ExecuteCommand(svalue, SRC_SHUTTER);
}
if (!result){
AddLog(LOG_LEVEL_ERROR, PSTR("SHT: ShutterRealToPercentPosition: PASS"));
} else {
AddLog(LOG_LEVEL_ERROR, PSTR("SHT: ShutterRealToPercentPosition: FAIL"));
}
}
#else
void CmndShutterUnitTest(void) {}
#endif