mirror of https://github.com/arendst/Tasmota.git
Merge pull request #7103 from stefanbode/patch-2
Added frequency change support
This commit is contained in:
commit
e396cbec1f
|
@ -37,10 +37,13 @@
|
|||
#define D_CMND_SHUTTER_INVERT "Invert"
|
||||
#define D_CMND_SHUTTER_CLIBRATION "Calibration"
|
||||
#define D_CMND_SHUTTER_MOTORDELAY "MotorDelay"
|
||||
#define D_CMND_SHUTTER_FREQUENCY "Frequency"
|
||||
|
||||
#define D_SHUTTER "SHUTTER"
|
||||
|
||||
const uint16_t MOTOR_STOP_TIME = 500; // in mS
|
||||
const uint16_t MOTOR_STOP_TIME = 500; // in mS
|
||||
|
||||
|
||||
|
||||
uint8_t calibrate_pos[6] = {0,30,50,70,90,100};
|
||||
uint16_t messwerte[5] = {30,50,70,90,100};
|
||||
|
@ -51,12 +54,13 @@ const char kShutterCommands[] PROGMEM = D_PRFX_SHUTTER "|"
|
|||
D_CMND_SHUTTER_OPEN "|" D_CMND_SHUTTER_CLOSE "|" D_CMND_SHUTTER_STOP "|" D_CMND_SHUTTER_POSITION "|"
|
||||
D_CMND_SHUTTER_OPENTIME "|" D_CMND_SHUTTER_CLOSETIME "|" D_CMND_SHUTTER_RELAY "|"
|
||||
D_CMND_SHUTTER_SETHALFWAY "|" D_CMND_SHUTTER_SETCLOSE "|" D_CMND_SHUTTER_INVERT "|" D_CMND_SHUTTER_CLIBRATION "|"
|
||||
D_CMND_SHUTTER_MOTORDELAY;
|
||||
D_CMND_SHUTTER_MOTORDELAY "|" D_CMND_SHUTTER_FREQUENCY;
|
||||
|
||||
void (* const ShutterCommand[])(void) PROGMEM = {
|
||||
&CmndShutterOpen, &CmndShutterClose, &CmndShutterStop, &CmndShutterPosition,
|
||||
&CmndShutterOpenTime, &CmndShutterCloseTime, &CmndShutterRelay,
|
||||
&CmndShutterSetHalfway, &CmndShutterSetClose, &CmndShutterInvert, &CmndShutterCalibration , &CmndShutterMotorDelay};
|
||||
&CmndShutterSetHalfway, &CmndShutterSetClose, &CmndShutterInvert, &CmndShutterCalibration , &CmndShutterMotorDelay,
|
||||
&CmndShutterFrequency};
|
||||
|
||||
const char JSON_SHUTTER_POS[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Position\":%d,\"direction\":%d}";
|
||||
|
||||
|
@ -68,23 +72,24 @@ struct SHUTTER {
|
|||
power_t mask = 0; // bit mask with 11 at the position of relays that belong to at least ONE shutter
|
||||
power_t old_power = 0; // preserve old bitmask for power to extract the relay that changes.
|
||||
power_t switched_relay = 0; // bitmatrix that contain the relays that was lastly changed.
|
||||
uint32_t time[MAX_SHUTTERS];
|
||||
uint32_t time[MAX_SHUTTERS]; // operating time of the shutter in 0.05sec
|
||||
int32_t open_max[MAX_SHUTTERS]; // max value on maximum open calculated
|
||||
int32_t target_position[MAX_SHUTTERS]; // position to go to
|
||||
int32_t start_position[MAX_SHUTTERS];
|
||||
int32_t start_position[MAX_SHUTTERS]; // position before a movement is started. init at start
|
||||
int32_t real_position[MAX_SHUTTERS]; // value between 0 and Shutter.open_max
|
||||
uint16_t open_time[MAX_SHUTTERS]; // duration to open the shutter
|
||||
uint16_t close_time[MAX_SHUTTERS]; // duration to close the shutter
|
||||
uint16_t open_time[MAX_SHUTTERS]; // duration to open the shutter. 112 = 11.2sec
|
||||
uint16_t close_time[MAX_SHUTTERS]; // duration to close the shutter. 112 = 11.2sec
|
||||
uint16_t close_velocity[MAX_SHUTTERS]; // in relation to open velocity. higher value = faster
|
||||
int8_t direction[MAX_SHUTTERS]; // 1 == UP , 0 == stop; -1 == down
|
||||
uint8_t mode = 0; // operation mode definition. see enum type above SHT_OFF_OPEN__OFF_CLOSE, SHT_OFF_ON__OPEN_CLOSE, SHT_PULSE_OPEN__PULSE_CLOSE
|
||||
uint8_t motordelay[MAX_SHUTTERS]; // initial motorstarttime in 0.05sec.
|
||||
uint16_t pwm_frequency;
|
||||
uint8_t motordelay[MAX_SHUTTERS]; // initial motorstarttime in 0.05sec.
|
||||
uint16_t pwm_frequency; // frequency of PWN for stepper motors
|
||||
uint16_t max_pwm_frequency = 1000;
|
||||
} Shutter;
|
||||
|
||||
void ShutterRtc50mS(void)
|
||||
{
|
||||
for (uint32_t i = 0; i < MAX_SHUTTERS; i++) {
|
||||
for (uint32_t i = 0; i < shutters_present; i++) {
|
||||
Shutter.time[i]++;
|
||||
}
|
||||
}
|
||||
|
@ -189,6 +194,11 @@ void ShutterInit(void)
|
|||
}
|
||||
} else {
|
||||
Shutter.mode = SHT_OFF_ON__OPEN_CLOSE;
|
||||
if (pin[GPIO_PWM1 ]+i < 99) {
|
||||
Shutter.pwm_frequency = 0;
|
||||
analogWriteFreq(Shutter.pwm_frequency);
|
||||
analogWrite(pin[GPIO_PWM1]+i, 50);
|
||||
}
|
||||
}
|
||||
|
||||
TickerShutter.attach_ms(50, ShutterRtc50mS );
|
||||
|
@ -243,21 +253,21 @@ void ShutterUpdatePosition(void)
|
|||
if (Shutter.direction[i] != 0) {
|
||||
//char stemp1[20];
|
||||
|
||||
if (pin[GPIO_PWM1]+i < 99 && Shutter.pwm_frequency != 1000) {
|
||||
Shutter.pwm_frequency += 100;
|
||||
Shutter.pwm_frequency = (Shutter.pwm_frequency > 1000 ? 1000 : Shutter.pwm_frequency);
|
||||
// frequency start at 0. Stepper will start moving with first change of the Speed
|
||||
// Counter should be initiated to 0 to count movement.
|
||||
// 0..1000 in step 100 = 10 steps with 0.05 sec = 0.5sec total ramp time from start to
|
||||
// full speed.
|
||||
if (pin[GPIO_PWM1]+i < 99 && Shutter.pwm_frequency != Shutter.max_pwm_frequency) {
|
||||
Shutter.pwm_frequency += Shutter.max_pwm_frequency/20;
|
||||
Shutter.pwm_frequency = (Shutter.pwm_frequency > Shutter.max_pwm_frequency ? Shutter.max_pwm_frequency : Shutter.pwm_frequency);
|
||||
analogWriteFreq(Shutter.pwm_frequency);
|
||||
analogWrite(pin[GPIO_PWM1]+i, 50);
|
||||
}
|
||||
|
||||
Shutter.real_position[i] = Shutter.start_position[i] + ( (Shutter.time[i] - Shutter.motordelay[i]) * (Shutter.direction[i] > 0 ? 100 : -Shutter.close_velocity[i]));
|
||||
// avoid real position leaving the boundaries.
|
||||
if (Shutter.real_position[i] < 0 || Shutter.real_position[i] > Shutter.open_max[i]) {
|
||||
dtostrfd((float)Shutter.time[i] / 20, 1, stemp2);
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: ShutterTEMP %d: Real Pos. %d, Stoppos: %ld, direction %d, rtcshutter: %s [s]"), i, Shutter.real_position[i], Settings.shutter_position[i], Shutter.direction[i], stemp2);
|
||||
Shutter.real_position[i] = Shutter.real_position[i] < 0 ? 0 : (Shutter.real_position[i] > Shutter.open_max[i] ? Shutter.open_max[i] : Shutter.real_position[i]) ;
|
||||
|
||||
Shutter.real_position[i] = Shutter.real_position[i] < 0 ? 0 : (Shutter.real_position[i] > Shutter.open_max[i] ? Shutter.open_max[i] : Shutter.real_position[i]) ;
|
||||
}
|
||||
|
||||
if (Shutter.real_position[i] * Shutter.direction[i] >= Shutter.target_position[i] * Shutter.direction[i] ) {
|
||||
// calculate relay number responsible for current movement.
|
||||
|
@ -275,17 +285,26 @@ void ShutterUpdatePosition(void)
|
|||
break;
|
||||
case SHT_OFF_ON__OPEN_CLOSE:
|
||||
// This is a failsafe configuration. Relay1 ON/OFF Relay2 -1/1 direction
|
||||
if (pin[GPIO_PWM1 ]+i < 99) {
|
||||
// Only allow PWM microstepping if PWM and COUNTER are defined.
|
||||
// see wiki to connect PWM and COUNTER
|
||||
if (pin[GPIO_PWM1 ]+i < 99 && pin[GPIO_CNTR1 ]+i < 99 ) {
|
||||
int16_t missing_steps = ((Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) - RtcSettings.pulse_counter[i];
|
||||
Shutter.pwm_frequency = 0;
|
||||
//slow down for acurate position
|
||||
analogWriteFreq(500);
|
||||
analogWrite(pin[GPIO_PWM1]+i, 50);
|
||||
//prepare for stop PWM
|
||||
Shutter.motordelay[i] = -2 + Shutter.motordelay[i] + missing_steps/(Shutter.max_pwm_frequency/20);
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Missing steps %d, adjust motordelay %d, counter %d, temp realpos %d"), missing_steps, Shutter.motordelay[i],RtcSettings.pulse_counter[i] ,Shutter.real_position[i]);
|
||||
Settings.shutter_motordelay[i]=Shutter.motordelay[i];
|
||||
analogWriteFreq(0);
|
||||
while (RtcSettings.pulse_counter[i] < (Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]/2) {
|
||||
while (RtcSettings.pulse_counter[i] < (uint32_t)(Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) {
|
||||
delay(1);
|
||||
}
|
||||
analogWrite(pin[GPIO_PWM1]+i, 0);
|
||||
Shutter.real_position[i] = RtcSettings.pulse_counter[i]*Shutter.direction[i]*2+Shutter.start_position[i];
|
||||
Shutter.real_position[i] = ((int32_t)RtcSettings.pulse_counter[i]*Shutter.direction[i]*2000 / Shutter.max_pwm_frequency)+Shutter.start_position[i];
|
||||
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT:Realpos %d, pulsecount %d, startpos %d, int32 %d"), Shutter.real_position[i],RtcSettings.pulse_counter[i], Shutter.start_position[i], ((int32_t)RtcSettings.pulse_counter[i]*Shutter.direction[i]*2000 / Shutter.max_pwm_frequency));
|
||||
|
||||
}
|
||||
if ((1 << (Settings.shutter_startrelay[i]-1)) & power) {
|
||||
ExecuteCommandPower(Settings.shutter_startrelay[i], 0, SRC_SHUTTER);
|
||||
|
@ -303,7 +322,7 @@ void ShutterUpdatePosition(void)
|
|||
Settings.shutter_position[i] = ShutterRealToPercentPosition(Shutter.real_position[i], i);
|
||||
|
||||
dtostrfd((float)Shutter.time[i] / 20, 1, stemp2);
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Real Pos. %d, Stoppos: %ld, relay: %d, direction %d, pulsetimer: %d, rtcshutter: %s [s]"), i, Shutter.real_position[i], Settings.shutter_position[i], cur_relay -1, Shutter.direction[i], Settings.pulse_timer[cur_relay -1], stemp2);
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Real Pos. %d, Stoppos: %ld, relay: %d, direction %d, pulsetimer: %d, motordelay %d, rtcshutter: %s [s]"), i, Shutter.real_position[i], Settings.shutter_position[i], cur_relay -1, Shutter.direction[i], Settings.pulse_timer[cur_relay -1], Shutter.motordelay[i],stemp2);
|
||||
Shutter.start_position[i] = Shutter.real_position[i];
|
||||
|
||||
// sending MQTT result to broker
|
||||
|
@ -342,7 +361,10 @@ void ShutterStartInit(uint8_t index, uint8_t direction, int32_t target_pos)
|
|||
Shutter.pwm_frequency = 0;
|
||||
analogWriteFreq(Shutter.pwm_frequency);
|
||||
analogWrite(pin[GPIO_PWM1]+index, 0);
|
||||
RtcSettings.pulse_counter[index] = 0;
|
||||
// can be operated without counter, but then not that acurate.
|
||||
if (pin[GPIO_CNTR1]+index < 99) {
|
||||
RtcSettings.pulse_counter[index] = 0;
|
||||
}
|
||||
}
|
||||
//AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start shutter: %d from %d to %d in directin %d"), index, Shutter.start_position[index], Shutter.target_position[index], Shutter.direction[index]);
|
||||
}
|
||||
|
@ -360,10 +382,10 @@ void ShutterReportPosition(void)
|
|||
if (Shutter.direction[i] != 0) {
|
||||
char stemp1[20];
|
||||
char stemp2[10];
|
||||
dtostrfd((float)Shutter.time[i] / 20, 1, stemp2);
|
||||
dtostrfd((float)Shutter.time[i] / 20, 2, stemp2);
|
||||
shutter_moving = 1;
|
||||
//Settings.shutter_position[i] = Settings.shuttercoeff[2][i] * 5 > Shutter.real_position[i] ? Shutter.real_position[i] / Settings.shuttercoeff[2][i] : (Shutter.real_position[i]-Settings.shuttercoeff[0,i]) / Settings.shuttercoeff[1][i];
|
||||
AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d: Real Pos: %d, Target %d, source: %s, start-pos: %d %%, direction: %d, rtcshutter: %s [s]"), i,Shutter.real_position[i], Shutter.target_position[i], GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource), Settings.shutter_position[i], Shutter.direction[i], stemp2 );
|
||||
AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d: Real Pos: %d, Target %d, source: %s, start-pos: %d %%, direction: %d, motordelay %d, rtcshutter: %s [s]"), i,Shutter.real_position[i], Shutter.target_position[i], GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource), Settings.shutter_position[i], Shutter.direction[i], Shutter.motordelay[i], stemp2 );
|
||||
}
|
||||
}
|
||||
if (rules_flag.shutter_moving > shutter_moving) {
|
||||
|
@ -424,12 +446,6 @@ void ShutterRelayChanged(void)
|
|||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Shutter specific functions
|
||||
// TODO: move to shutter driver and make them accessible in a generic way
|
||||
|
||||
// device: 1..<numberOfShutters>
|
||||
// position: 0-100
|
||||
void ShutterSetPosition(uint8_t device, uint8_t position)
|
||||
{
|
||||
char svalue[32]; // Command and number parameter
|
||||
|
@ -463,7 +479,7 @@ void CmndShutterStop(void)
|
|||
if (Shutter.direction[index] != 0) {
|
||||
|
||||
AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Stop moving shutter %d: direction: %d"), XdrvMailbox.index, Shutter.direction[index]);
|
||||
|
||||
// set stop position 10 steps ahead (0.5sec to allow normal stop)
|
||||
int32_t temp_realpos = Shutter.start_position[index] + ( (Shutter.time[index]+10) * (Shutter.direction[index] > 0 ? 100 : -Shutter.close_velocity[index]));
|
||||
XdrvMailbox.payload = ShutterRealToPercentPosition(temp_realpos, index);
|
||||
//XdrvMailbox.payload = Settings.shuttercoeff[2][index] * 5 > temp_realpos ? temp_realpos / Settings.shuttercoeff[2][index] : (temp_realpos-Settings.shuttercoeff[0,index]) / Settings.shuttercoeff[1][index];
|
||||
|
@ -609,6 +625,16 @@ void CmndShutterSetHalfway(void)
|
|||
}
|
||||
}
|
||||
|
||||
void CmndShutterFrequency(void)
|
||||
{
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 10000)) {
|
||||
Shutter.max_pwm_frequency = XdrvMailbox.payload;
|
||||
ResponseCmndNumber(XdrvMailbox.payload); // ????
|
||||
} else {
|
||||
ResponseCmndNumber(Shutter.max_pwm_frequency);
|
||||
}
|
||||
}
|
||||
|
||||
void CmndShutterSetClose(void)
|
||||
{
|
||||
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) {
|
||||
|
|
Loading…
Reference in New Issue