Fixes on Stepper + Servo

- fix restart bug on servo
- refactor smooth-ramp for stepper and servo. Now in RTC and much more stable
- increased internal resolution to better work with ramps
- testing, testing, testing....
This commit is contained in:
stefanbode 2020-09-08 19:34:10 +02:00 committed by GitHub
parent 1c657e86e7
commit 72afb15601
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 113 additions and 95 deletions

View File

@ -30,14 +30,22 @@
#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
const uint8_t steps_per_second = 20; // FUNC_EVERY_50_MSECOND const uint16_t RESOLUTION = 1000;
const uint8_t STEPS_PER_SECOND = 20; // FUNC_EVERY_50_MSECOND
const uint16_t pwm_max = 500; const uint16_t pwm_max = 500;
const uint16_t pwm_min = 90; const uint16_t pwm_min = 90;
uint8_t calibrate_pos[6] = {0,30,50,70,90,100}; uint8_t calibrate_pos[6] = {0,30,50,70,90,100};
uint16_t messwerte[5] = {30,50,70,90,100}; uint16_t messwerte[5] = {30,50,70,90,100};
uint16_t last_execute_step; uint16_t last_execute_step;
int32_t stop_position_delta = 20;
int32_t max_velocity = 0;
int32_t max_velocity_change_per_step = 0;
int32_t min_runtime_ms = 0;
int32_t minstopway = 0;
int32_t next_possible_stop = 0;
int32_t toBeAcc = 0;
const uint8_t MAX_MODES = 7; const uint8_t MAX_MODES = 7;
enum ShutterPositionMode {SHT_UNDEF, SHT_TIME, SHT_TIME_UP_DOWN, SHT_TIME_GARAGE, SHT_COUNTER, SHT_PWM_VALUE, SHT_PWM_TIME,}; enum ShutterPositionMode {SHT_UNDEF, SHT_TIME, SHT_TIME_UP_DOWN, SHT_TIME_GARAGE, SHT_COUNTER, SHT_PWM_VALUE, SHT_PWM_TIME,};
@ -98,8 +106,8 @@ struct SHUTTER {
void ShutterLogPos(uint32_t i) void ShutterLogPos(uint32_t i)
{ {
char stemp2[10]; char stemp2[10];
dtostrfd((float)Shutter.time[i] / steps_per_second, 2, stemp2); dtostrfd((float)Shutter.time[i] / STEPS_PER_SECOND, 2, stemp2);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter%d Real %d, Start %d, Stop %d, Dir %d, Delay %d, Rtc %s [s], Freq %d, PWM %d"), AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d Real %d, Start %d, Stop %d, Dir %d, Delay %d, Rtc %s [s], Freq %d, PWM %d"),
i+1, Shutter.real_position[i], Shutter.start_position[i], Shutter.target_position[i], Shutter.direction[i], Shutter.motordelay[i], stemp2, Shutter.pwm_velocity[i], Shutter.pwm_value[i]); i+1, Shutter.real_position[i], Shutter.start_position[i], Shutter.target_position[i], Shutter.direction[i], Shutter.motordelay[i], stemp2, Shutter.pwm_velocity[i], Shutter.pwm_value[i]);
} }
@ -111,30 +119,35 @@ void ExecuteCommandPowerShutter(uint32_t device, uint32_t state, uint32_t source
void ShutterUpdateVelocity(uint8_t i) void ShutterUpdateVelocity(uint8_t i)
{ {
Shutter.pwm_velocity[i] += Shutter.accelerator[i]; Shutter.pwm_velocity[i] += Shutter.accelerator[i];
Shutter.pwm_velocity[i] = tmax(1,tmin(Shutter.direction[i]==1 ? Shutter.max_pwm_velocity : Shutter.max_close_pwm_velocity[i],Shutter.pwm_velocity[i])); Shutter.pwm_velocity[i] = tmax(0,tmin(Shutter.direction[i]==1 ? Shutter.max_pwm_velocity : Shutter.max_close_pwm_velocity[i],Shutter.pwm_velocity[i]));
} }
void ShutterRtc50mS(void) void ShutterRtc50mS(void)
{ {
for (uint8_t i = 0; i < shutters_present; i++) { for (uint8_t i = 0; i < shutters_present; i++) {
Shutter.time[i]++; if (Shutter.direction[i]) {
switch (Shutter.PositionMode) { // update position data before increasing counter
case SHT_PWM_VALUE: Shutter.real_position[i] = ShutterCalculatePosition(i);
if (Shutter.accelerator[i]) ShutterUpdateVelocity(i); Shutter.time[i]++;
Shutter.real_position[i] += Shutter.direction[i] > 0 ? Shutter.pwm_velocity[i] : (Shutter.direction[i] < 0 ? -Shutter.pwm_velocity[i] : 0); ShutterCalculateAccelerator(i);
Shutter.pwm_value[i] = SHT_DIV_ROUND((Shutter.pwm_max[i]-Shutter.pwm_min[i]) * Shutter.real_position[i] , Shutter.open_max[i])+Shutter.pwm_min[i]; switch (Shutter.PositionMode) {
analogWrite(Pin(GPIO_PWM1, i), Shutter.pwm_value[i]); case SHT_PWM_VALUE:
break;
case SHT_COUNTER:
if (Shutter.accelerator[i]) {
//AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: accelerator i=%d -> %d"),i, Shutter.accelerator[i]);
ShutterUpdateVelocity(i); ShutterUpdateVelocity(i);
analogWriteFreq(Shutter.pwm_velocity[i]); Shutter.real_position[i] += Shutter.direction[i] > 0 ? Shutter.pwm_velocity[i] : (Shutter.direction[i] < 0 ? -Shutter.pwm_velocity[i] : 0);
analogWrite(Pin(GPIO_PWM1, i), 50); Shutter.pwm_value[i] = SHT_DIV_ROUND((Shutter.pwm_max[i]-Shutter.pwm_min[i]) * Shutter.real_position[i] , Shutter.open_max[i])+Shutter.pwm_min[i];
} analogWrite(Pin(GPIO_PWM1, i), Shutter.pwm_value[i]);
break; break;
}
case SHT_COUNTER:
if (Shutter.accelerator[i]) {
//AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: accelerator i=%d -> %d"),i, Shutter.accelerator[i]);
ShutterUpdateVelocity(i);
analogWriteFreq(Shutter.pwm_velocity[i]);
analogWrite(Pin(GPIO_PWM1, i), 50);
}
break;
}
} // if (Shutter.direction[i])
} }
} }
@ -266,14 +279,14 @@ void ShutterInit(void)
Shutter.open_time[i] = (Settings.shutter_opentime[i] > 0) ? Settings.shutter_opentime[i] : 100; Shutter.open_time[i] = (Settings.shutter_opentime[i] > 0) ? Settings.shutter_opentime[i] : 100;
Shutter.close_time[i] = (Settings.shutter_closetime[i] > 0) ? Settings.shutter_closetime[i] : 100; Shutter.close_time[i] = (Settings.shutter_closetime[i] > 0) ? Settings.shutter_closetime[i] : 100;
//temporary hard coded.
Shutter.pwm_min[i] = pwm_min; Shutter.pwm_min[i] = pwm_min;
Shutter.pwm_max[i] = pwm_max; Shutter.pwm_max[i] = pwm_max;
// Update Calculation 20 because time interval is 0.05 sec // Update Calculation 20 because time interval is 0.05 sec ans time is in 0.1sec
Shutter.open_max[i] = 200 * Shutter.open_time[i]; Shutter.open_max[i] = STEPS_PER_SECOND * RESOLUTION * Shutter.open_time[i] / 10;
Shutter.close_velocity[i] = Shutter.open_max[i] / Shutter.close_time[i] / 2 ; Shutter.close_velocity[i] = Shutter.open_max[i] / Shutter.close_time[i] / 2 ;
// calculate a ramp slope at the first 5 percent to compensate that shutters move with down part later than the upper part // calculate a ramp slope at the first 5 percent to compensate that shutters move with down part later than the upper part
if (Settings.shutter_set50percent[i] != 50) { if (Settings.shutter_set50percent[i] != 50) {
Settings.shuttercoeff[1][i] = Shutter.open_max[i] * (100 - Settings.shutter_set50percent[i] ) / 5000; Settings.shuttercoeff[1][i] = Shutter.open_max[i] * (100 - Settings.shutter_set50percent[i] ) / 5000;
@ -283,19 +296,19 @@ void ShutterInit(void)
Shutter.mask |= 3 << (Settings.shutter_startrelay[i] -1); Shutter.mask |= 3 << (Settings.shutter_startrelay[i] -1);
Shutter.real_position[i] = ShutterPercentToRealPosition(Settings.shutter_position[i], i); Shutter.real_position[i] = ShutterPercentToRealPosition(Settings.shutter_position[i], i);
//Shutter.real_position[i] = Settings.shutter_position[i] <= 5 ? Settings.shuttercoeff[2][i] * Settings.shutter_position[i] : Settings.shuttercoeff[1][i] * Settings.shutter_position[i] + Settings.shuttercoeff[0,i];
Shutter.start_position[i] = Shutter.target_position[i] = Shutter.real_position[i]; Shutter.start_position[i] = Shutter.target_position[i] = Shutter.real_position[i];
Shutter.motordelay[i] = Settings.shutter_motordelay[i]; Shutter.motordelay[i] = Settings.shutter_motordelay[i];
Shutter.lastdirection[i] = (50 < Settings.shutter_position[i]) ? 1 : -1; Shutter.lastdirection[i] = (50 < Settings.shutter_position[i]) ? 1 : -1;
switch (Shutter.PositionMode) { switch (Shutter.PositionMode) {
case SHT_COUNTER:
case SHT_PWM_VALUE: case SHT_PWM_VALUE:
Shutter.max_close_pwm_velocity[i] = Shutter.max_pwm_velocity*Shutter.open_time[i] / Shutter.close_time[i]; Shutter.max_pwm_velocity = RESOLUTION;
break; break;
} }
Shutter.max_close_pwm_velocity[i] = Shutter.max_pwm_velocity*Shutter.open_time[i] / Shutter.close_time[i];
//AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shutter %d Closevel: %d"),i, Shutter.max_close_pwm_velocity[i]); //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shutter %d Openvel %d, Closevel: %d"),i, Shutter.max_pwm_velocity, Shutter.max_close_pwm_velocity[i]);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT%d: Init. Pos: %d,inverted %d, locked %d, end stop time enabled %d, webButtons inverted %d"), AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT%d: Init. Pos: %d,inverted %d, locked %d, end stop time enabled %d, webButtons inverted %d"),
i+1, Shutter.real_position[i], i+1, Shutter.real_position[i],
(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);
@ -349,40 +362,35 @@ void ShutterLimitRealAndTargetPositions(uint32_t i) {
void ShutterCalculateAccelerator(uint8_t i) void ShutterCalculateAccelerator(uint8_t i)
{ {
switch (Shutter.PositionMode) { if (Shutter.direction[i] != 0) {
case SHT_COUNTER: switch (Shutter.PositionMode) {
case SHT_PWM_VALUE: case SHT_COUNTER:
int32_t max_velocity = Shutter.direction[i] == 1 ? Shutter.max_pwm_velocity : Shutter.max_close_pwm_velocity[i]; case SHT_PWM_VALUE:
int32_t max_velocity_change_per_step = Shutter.max_pwm_velocity / (Shutter.motordelay[i]>0 ? Shutter.motordelay[i] : 1); // calculate max velocity allowed in this direction
int32_t min_runtime_ms = Shutter.pwm_velocity[i] * 1000 / steps_per_second / max_velocity_change_per_step; max_velocity = Shutter.direction[i] == 1 ? Shutter.max_pwm_velocity : Shutter.max_close_pwm_velocity[i];
//int32_t velocity = Shutter.direction[i] == 1 ? 100 : Shutter.close_velocity[i]; // calculate max change of velocyty based on the defined motordelay in steps
int32_t minstopway = (min_runtime_ms * (Shutter.pwm_velocity[i]+max_velocity_change_per_step)/100 - Shutter.pwm_velocity[i]) * Shutter.direction[i] ; max_velocity_change_per_step = max_velocity / (Shutter.motordelay[i]>0 ? Shutter.motordelay[i] : 1);
int32_t toBeAcc = 0; // minimumtime required from current velocity to stop
int32_t next_possible_stop = Shutter.real_position[i] + minstopway ; min_runtime_ms = Shutter.pwm_velocity[i] * 1000 / STEPS_PER_SECOND / max_velocity_change_per_step;
stop_position_delta = Shutter.direction[i] * (next_possible_stop - Shutter.target_position[i]); // decellartion way from current velocity
if (Shutter.PositionMode == SHT_COUNTER) { minstopway = (min_runtime_ms * (Shutter.pwm_velocity[i]+max_velocity_change_per_step)/100 - Shutter.pwm_velocity[i])*RESOLUTION/Shutter.max_pwm_velocity * Shutter.direction[i] ;
// ToDo need to check the influence of frequency and speed on the secure area to stop right in time. next_possible_stop = Shutter.real_position[i] + minstopway ;
// seems currently only work with motordelay but not ok without motordelay. toBeAcc = 0;
stop_position_delta =+ 200 * Shutter.pwm_velocity[i]/max_velocity; // ensure that accelerator kicks in IN TIME and that STOP procedure kicks in at least ONE step before reach end position.
} else { //Shutter.accelerator[i] = tmin(tmax(max_velocity_change_per_step*(100-(Shutter.direction[i]*(Shutter.target_position[i]-next_possible_stop) ))/2000 , max_velocity_change_per_step*9/200), max_velocity_change_per_step*11/200);
stop_position_delta =+ Shutter.pwm_velocity[i]-max_velocity_change_per_step; //int32_t act_freq_change = max_velocity_change_per_step/20;
}
//Shutter.accelerator[i] = tmin(tmax(max_velocity_change_per_step*(100-(Shutter.direction[i]*(Shutter.target_position[i]-next_possible_stop) ))/2000 , max_velocity_change_per_step*9/200), max_velocity_change_per_step*11/200); // ensure that the accelerotor kicks in at least one step BEFORE it is to late and a hard stop required.
//int32_t act_freq_change = max_velocity_change_per_step/20; if (Shutter.accelerator[i] < 0 || (next_possible_stop * Shutter.direction[i]) +RESOLUTION*Shutter.pwm_velocity[i]/Shutter.max_pwm_velocity>= Shutter.target_position[i] * Shutter.direction[i] ) {
// 10 times the deviation is the value of this simple p-regulator
if (Shutter.accelerator[i] < 0 || next_possible_stop * Shutter.direction[i] > (Shutter.target_position[i]- (stop_position_delta * Shutter.direction[i])) * Shutter.direction[i] ) { toBeAcc = 100+(Shutter.direction[i]*(next_possible_stop-Shutter.target_position[i])*max_velocity/Shutter.pwm_velocity[i]*10/RESOLUTION);
toBeAcc = 100+(Shutter.direction[i]*max_velocity*(next_possible_stop-Shutter.target_position[i])/Shutter.pwm_velocity[i]); Shutter.accelerator[i] = - tmin(tmax( max_velocity_change_per_step*toBeAcc/100 , (max_velocity_change_per_step*9/10)), (max_velocity_change_per_step*11/10));
Shutter.accelerator[i] = - tmin(tmax((toBeAcc > 100 ? max_velocity_change_per_step*toBeAcc/100 : max_velocity_change_per_step*toBeAcc/100) , (max_velocity_change_per_step*9/10)-1), (max_velocity_change_per_step*11/10)+1); //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Ramp down: acc: %d"), Shutter.accelerator[i]);
//AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Ramp down: acc: %d"), Shutter.accelerator[i]); } else if ( Shutter.accelerator[i] > 0 && Shutter.pwm_velocity[i] == max_velocity) {
} else if ( Shutter.accelerator[i] > 0 && Shutter.pwm_velocity[i] == max_velocity) { Shutter.accelerator[i] = 0;
Shutter.accelerator[i] = 0; }
} break;
}
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: time: %d, toBeAcc %d, minstopway %d,cur_vel %d, max_vel %d, act_vel_change %d, min_runtime_ms %d, act.pos %d, next_stop %d, target: %d, stop_position_delta %d, max_vel_change_per_step %d"),Shutter.time[i],toBeAcc,minstopway,
Shutter.pwm_velocity[i],max_velocity, Shutter.accelerator[i],min_runtime_ms,Shutter.real_position[i], next_possible_stop,Shutter.target_position[i],stop_position_delta,max_velocity_change_per_step);
break;
} }
} }
@ -392,15 +400,15 @@ void ShutterDecellerateForStop(uint8_t i)
case SHT_PWM_VALUE: case SHT_PWM_VALUE:
case SHT_COUNTER: case SHT_COUNTER:
int16_t missing_steps; int16_t missing_steps;
Shutter.accelerator[i] = -(Shutter.max_pwm_velocity / (Shutter.motordelay[i]>0 ? Shutter.motordelay[i] : 1)); Shutter.accelerator[i] = -(Shutter.max_pwm_velocity / (Shutter.motordelay[i]>0 ? Shutter.motordelay[i] : 1) *11/10);
while (Shutter.pwm_velocity[i] > -Shutter.accelerator[i] && Shutter.accelerator[i] != 0) { while (Shutter.pwm_velocity[i] > -2*Shutter.accelerator[i] ) {
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: velocity: %ld, delta: %d"), Shutter.pwm_velocity[i], Shutter.accelerator[i] ); AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: velocity: %ld, delta: %d"), Shutter.pwm_velocity[i], Shutter.accelerator[i] );
//Shutter.pwm_velocity[i] = tmax(Shutter.pwm_velocity[i]-Shutter.accelerator[i] , 0); //Shutter.pwm_velocity[i] = tmax(Shutter.pwm_velocity[i]-Shutter.accelerator[i] , 0);
// Control will be done in RTC Ticker. // Control will be done in RTC Ticker.
delay(50); delay(50);
} }
if (Shutter.PositionMode == SHT_COUNTER){ if (Shutter.PositionMode == SHT_COUNTER){
missing_steps = ((Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_velocity/2000) - RtcSettings.pulse_counter[i]; missing_steps = ((Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_velocity/RESOLUTION/STEPS_PER_SECOND) - RtcSettings.pulse_counter[i];
//prepare for stop PWM //prepare for stop PWM
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Remain steps %d, counter %d, freq %d"), missing_steps, RtcSettings.pulse_counter[i] ,Shutter.pwm_velocity[i]); AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Remain steps %d, counter %d, freq %d"), missing_steps, RtcSettings.pulse_counter[i] ,Shutter.pwm_velocity[i]);
Shutter.accelerator[i] = 0; Shutter.accelerator[i] = 0;
@ -409,7 +417,7 @@ void ShutterDecellerateForStop(uint8_t i)
analogWrite(Pin(GPIO_PWM1, i), 50); analogWrite(Pin(GPIO_PWM1, i), 50);
Shutter.pwm_velocity[i] = 0; Shutter.pwm_velocity[i] = 0;
analogWriteFreq(Shutter.pwm_velocity[i]); analogWriteFreq(Shutter.pwm_velocity[i]);
while (RtcSettings.pulse_counter[i] < (uint32_t)(Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_velocity/2000) { while (RtcSettings.pulse_counter[i] < (uint32_t)(Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_velocity/RESOLUTION/STEPS_PER_SECOND) {
delay(1); 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
@ -418,6 +426,7 @@ void ShutterDecellerateForStop(uint8_t i)
} }
Shutter.direction[i] = 0; Shutter.direction[i] = 0;
Shutter.pwm_velocity[i] = 0;
break; break;
} }
} }
@ -452,6 +461,14 @@ void ShutterPowerOff(uint8_t i) {
} }
break; break;
} }
// Store current PWM value to ensure proper position after reboot.
switch (Shutter.PositionMode) {
case SHT_PWM_VALUE:
char scmnd[20];
snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_PWM " %d" ),Shutter.pwm_value[i]);
ExecuteCommand(scmnd, SRC_BUTTON);
break;
}
} }
void ShutterUpdatePosition(void) void ShutterUpdatePosition(void)
@ -460,33 +477,33 @@ void ShutterUpdatePosition(void)
char scommand[CMDSZ]; char scommand[CMDSZ];
char stopic[TOPSZ]; char stopic[TOPSZ];
stop_position_delta = 20;
for (uint32_t i = 0; i < shutters_present; i++) { for (uint32_t i = 0; i < shutters_present; i++) {
if (Shutter.direction[i] != 0) { if (Shutter.direction[i] != 0) {
// Calculate position with counter. Much more accurate and no need for motordelay workaround // Calculate position with counter. Much more accurate and no need for motordelay workaround
// adding some steps to stop early // adding some steps to stop early
Shutter.real_position[i] = ShutterCalculatePosition(i); //Shutter.real_position[i] = ShutterCalculatePosition(i);
if (!Shutter.start_reported) { if (!Shutter.start_reported) {
ShutterReportPosition(true, i); ShutterReportPosition(true, i);
XdrvRulesProcess(); XdrvRulesProcess();
Shutter.start_reported = 1; Shutter.start_reported = 1;
} }
ShutterCalculateAccelerator(i); //ShutterCalculateAccelerator(i);
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: time: %d, toBeAcc %d, minstopway %d,cur_vel %d, max_vel %d, act_vel_change %d, min_runtime_ms %d, act.pos %d, next_stop %d, target: %d, max_vel_change_per_step %d"),Shutter.time[i],toBeAcc,minstopway,
Shutter.pwm_velocity[i],max_velocity, Shutter.accelerator[i],min_runtime_ms,Shutter.real_position[i], next_possible_stop,Shutter.target_position[i],max_velocity_change_per_step);
if ( Shutter.real_position[i] * Shutter.direction[i] + stop_position_delta >= Shutter.target_position[i] * Shutter.direction[i] ) {
if ( Shutter.real_position[i] * Shutter.direction[i] >= Shutter.target_position[i] * Shutter.direction[i] || Shutter.pwm_velocity[i]<max_velocity_change_per_step) {
if (Shutter.direction[i] != 0) { if (Shutter.direction[i] != 0) {
Shutter.lastdirection[i] = Shutter.direction[i]; Shutter.lastdirection[i] = Shutter.direction[i];
} }
ShutterPowerOff(i); ShutterPowerOff(i);
ShutterLimitRealAndTargetPositions(i); ShutterLimitRealAndTargetPositions(i);
Settings.shutter_position[i] = ShutterRealToPercentPosition(Shutter.real_position[i], i); Settings.shutter_position[i] = ShutterRealToPercentPosition(Shutter.real_position[i], i);
Shutter.start_position[i] = Shutter.real_position[i];
ShutterLogPos(i); ShutterLogPos(i);
Shutter.start_position[i] = Shutter.real_position[i];
// sending MQTT result to broker // sending MQTT result to broker
snprintf_P(scommand, sizeof(scommand),PSTR(D_SHUTTER "%d"), i+1); snprintf_P(scommand, sizeof(scommand),PSTR(D_SHUTTER "%d"), i+1);
GetTopic_P(stopic, STAT, mqtt_topic, scommand); GetTopic_P(stopic, STAT, mqtt_topic, scommand);
@ -524,9 +541,6 @@ void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos)
RtcSettings.pulse_counter[i] = 0; RtcSettings.pulse_counter[i] = 0;
break; break;
#endif #endif
case SHT_PWM_VALUE:
Shutter.max_pwm_velocity = 100;
break;
} }
Shutter.accelerator[i] = Shutter.max_pwm_velocity / (Shutter.motordelay[i]>0 ? Shutter.motordelay[i] : 1); Shutter.accelerator[i] = Shutter.max_pwm_velocity / (Shutter.motordelay[i]>0 ? Shutter.motordelay[i] : 1);
Shutter.target_position[i] = target_pos; Shutter.target_position[i] = target_pos;
@ -545,22 +559,26 @@ void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos)
int32_t ShutterCalculatePosition(uint32_t i) int32_t ShutterCalculatePosition(uint32_t i)
{ {
switch (Shutter.PositionMode) { if (Shutter.direction[i] != 0) {
case SHT_COUNTER: switch (Shutter.PositionMode) {
return ((int32_t)RtcSettings.pulse_counter[i]*Shutter.direction[i]*2000 / Shutter.max_pwm_velocity)+Shutter.start_position[i]; case SHT_COUNTER:
return ((int32_t)RtcSettings.pulse_counter[i]*Shutter.direction[i]*STEPS_PER_SECOND*RESOLUTION / Shutter.max_pwm_velocity)+Shutter.start_position[i];
break;
case SHT_TIME:
case SHT_TIME_UP_DOWN:
case SHT_TIME_GARAGE:
return Shutter.start_position[i] + ( (Shutter.time[i] - Shutter.motordelay[i]) * (Shutter.direction[i] > 0 ? RESOLUTION : -Shutter.close_velocity[i]));
break;
case SHT_PWM_TIME:
break;
case SHT_PWM_VALUE:
return Shutter.real_position[i];
break; break;
case SHT_TIME: default:
case SHT_TIME_UP_DOWN: break;
case SHT_TIME_GARAGE: }
return Shutter.start_position[i] + ( (Shutter.time[i] - Shutter.motordelay[i]) * (Shutter.direction[i] > 0 ? 100 : -Shutter.close_velocity[i])); } else {
break;
case SHT_PWM_TIME:
break;
case SHT_PWM_VALUE:
return Shutter.real_position[i]; return Shutter.real_position[i];
break;
default:
break;
} }
} }
@ -591,7 +609,7 @@ void ShutterRelayChanged(void)
break; break;
default: default:
last_source = SRC_SHUTTER; // avoid switch off in the next loop last_source = SRC_SHUTTER; // avoid switch off in the next loop
if (Shutter.direction[i] != 0 )ShutterPowerOff(i); if (Shutter.direction[i] != 0 ) ShutterPowerOff(i);
} }
switch (Shutter.PositionMode) { switch (Shutter.PositionMode) {
// enum ShutterPositionMode {SHT_TIME, SHT_TIME_UP_DOWN, SHT_TIME_GARAGE, SHT_COUNTER, SHT_PWM_VALUE, SHT_PWM_TIME,}; // enum ShutterPositionMode {SHT_TIME, SHT_TIME_UP_DOWN, SHT_TIME_GARAGE, SHT_COUNTER, SHT_PWM_VALUE, SHT_PWM_TIME,};
@ -1022,8 +1040,8 @@ void CmndShutterPosition(void)
} }
if ( (target_pos_percent >= 0) && (target_pos_percent <= 100) && abs(Shutter.target_position[index] - Shutter.real_position[index] ) / Shutter.close_velocity[index] > 2) { if ( (target_pos_percent >= 0) && (target_pos_percent <= 100) && abs(Shutter.target_position[index] - Shutter.real_position[index] ) / Shutter.close_velocity[index] > 2) {
if (Settings.shutter_options[index] & 4) { if (Settings.shutter_options[index] & 4) {
if (0 == target_pos_percent) Shutter.target_position[index] -= 1 * 2000; if (0 == target_pos_percent) Shutter.target_position[index] -= 1 * RESOLUTION * STEPS_PER_SECOND;
if (100 == target_pos_percent) Shutter.target_position[index] += 1 * 2000; if (100 == target_pos_percent) Shutter.target_position[index] += 1 * RESOLUTION * STEPS_PER_SECOND;
} }
int8_t new_shutterdirection = Shutter.real_position[index] < Shutter.target_position[index] ? 1 : -1; int8_t new_shutterdirection = Shutter.real_position[index] < Shutter.target_position[index] ? 1 : -1;
if (Shutter.direction[index] == -new_shutterdirection) { if (Shutter.direction[index] == -new_shutterdirection) {
@ -1128,11 +1146,11 @@ void CmndShutterMotorDelay(void)
{ {
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) {
if (XdrvMailbox.data_len > 0) { if (XdrvMailbox.data_len > 0) {
Settings.shutter_motordelay[XdrvMailbox.index -1] = (uint16_t)(steps_per_second * CharToFloat(XdrvMailbox.data)); Settings.shutter_motordelay[XdrvMailbox.index -1] = (uint16_t)(STEPS_PER_SECOND * CharToFloat(XdrvMailbox.data));
ShutterInit(); ShutterInit();
} }
char time_chr[10]; char time_chr[10];
dtostrfd((float)(Settings.shutter_motordelay[XdrvMailbox.index -1]) / steps_per_second, 2, time_chr); dtostrfd((float)(Settings.shutter_motordelay[XdrvMailbox.index -1]) / STEPS_PER_SECOND, 2, time_chr);
ResponseCmndIdxChar(time_chr); ResponseCmndIdxChar(time_chr);
} }
} }