Hallo zusammen, ich möchte zwei E-Motoren (12V) die beide über PWM angesteuert werden und beide tachoscheiben besitzen irgendwie in ihrer Drehzahl synchronisieren, egal ob digital oder analog. Wer hat ideen wie dies möglichst genau zu bewerkstelligen ist ? P.S. Am liebsten via P.I.D.-regelung da sie schon an einem Prozessor hängen. Dank' vorab für alle Antworten. Gruss Sascha
Hallo! Anbei mal ein Software -PID Regler für einen SPS. Das ist zwar nicht kompatibel, aber du kannst zumindest erkenn wie sowas gemacht wird cu Afzelia (* PID controller / PID-Regler *)<BR> FUNCTION_BLOCK PID<BR> VAR_INPUT<BR> ACTUAL :REAL; (* actual value, process variable / Istwer t *)<BR> SET_POINT:REAL; (* desired value, <FONT COLOR=#0000FF>Set</FONT> point / Sollwert *)<BR> KP:REAL; (* proportionality <FONT COLOR=#0000FF>Const</FONT>. / Proportionalitätskoeff.&nbs p; *)<BR> TN:DWORD; (* reset time / Nachstellzeit <FONT COLOR=#0000FF>In</FONT> msec *)<BR> TV:DWORD; (* rate time, derivative time / Vorhaltzei t <FONT COLOR=#0000FF>In</FONT> msec *)<BR> Y_OFFSET:REAL; (* offset <FONT COLOR=#0000FF>For</FONT> manipulated variable / Stel lwert-Nullpunktsverschiebung *)<BR> Y_MIN:REAL; (* minimum value <FONT COLOR=#0000FF>For</FONT> manipulated variable / mini maler Stellwert *)<BR> Y_MAX:REAL; (* maximum value <FONT COLOR=#0000FF>For</FONT> manipulated variable / maxi maler Stellwert *)<BR> MANUAL:BOOL; (* <FONT COLOR=#0000FF>True</FONT>: manual / <FONT COLOR=#0000FF>True</FONT>: manueller Betrieb *)<BR> RESET:BOOL;<BR> END_VAR<BR> VAR_OUTPUT<BR> Y:REAL; (* manipulated variable, <FONT COLOR=#0000FF>Set</FONT> value / Stellgröße&nb sp;*)<BR> LIMITS_ACTIVE:BOOL:=<FONT COLOR=#0000FF>False</FONT>;<BR> OVERFLOW:BOOL:=<FONT COLOR=#0000FF>False</FONT>;<BR> END_VAR<BR> VAR<BR> CLOCK:TON;<BR> I: INTEGRAL;<BR> D: DERIVATIVE;<BR> TMDIFF: DWORD;<BR> <FONT COLOR=#0000FF>Error</FONT>: REAL;<BR> INIT: BOOL:=<FONT COLOR=#0000FF>True</FONT>;<BR> END_VAR<BR> <BR> <BR> <BR> <BR> <FONT COLOR=#0000FF>If</FONT> TN>0 <FONT COLOR=#0000FF>And</FONT> KP<> 0 <FONT COLOR=#0000FF>And</FONT> (<FONT COLOR=#0000FF>Not</FONT> OVERFLOW <FONT COLOR=#0000FF>Or</FONT> RESET <FONT COLOR=#0000FF>Or</FONT> MANUAL) <FONT COLOR=#0000FF>Then</FONT><BR> <FONT COLOR=#0000FF>Error</FONT> := SET_POINT-ACTUAL; (* Regeldifferenz *)<BR> <BR> <FONT COLOR=#0000FF>If</FONT> RESET <FONT COLOR=#0000FF>Or</FONT> MANUAL <FONT COLOR=#0000FF>Or</FONT> INIT <FONT COLOR=#0000FF>Then</FONT> (* Reset oder Handbetrieb *)<BR> I(RESET:=<FONT COLOR=#0000FF>True</FONT>);<BR> D(RESET:=<FONT COLOR=#0000FF>True</FONT>);<BR> OVERFLOW:=<FONT COLOR=#0000FF>False</FONT>;<BR> LIMITS_ACTIVE:=<FONT COLOR=#0000FF>False</FONT>;<BR> <FONT COLOR=#0000FF>If</FONT> RESET <FONT COLOR=#0000FF>Or</FONT> INIT <FONT COLOR=#0000FF>Then</FONT><BR> Y := Y_OFFSET;<BR> INIT:=<FONT COLOR=#0000FF>False</FONT>;<BR> END_IF;<BR> TMDIFF:=0;<BR> <FONT COLOR=#0000FF>Else</FONT><BR> CLOCK; (* Timer abfragen *)<BR> TMDIFF:=TIME_TO_DWORD(CLOCK.ET); (* Zeitdifferenz seit letztem Aufruf *)<BR> END_IF;<BR> <BR> <FONT COLOR=#0000FF>If</FONT> TMDIFF>0 <FONT COLOR=#0000FF>Then</FONT><BR> CLOCK(<FONT COLOR=#0000FF>In</FONT>:=<FONT COLOR=#0000FF>False</FONT>); (* Timer neu starten *)<BR> CLOCK(PT:=t#1h, <FONT COLOR=#0000FF>In</FONT>:=<FONT COLOR=#0000FF>True</FONT>);<BR> <BR> D(<FONT COLOR=#0000FF>In</FONT>:=<FONT COLOR=#0000FF>Error</FONT>, TM:=TMDIFF, RESET:=<FONT COLOR=#0000FF>False</FONT>); (* Differential abschätzen *)<BR> I(<FONT COLOR=#0000FF>In</FONT>:=<FONT COLOR=#0000FF>Error</FONT>, TM:=TMDIFF, RESET:=<FONT COLOR=#0000FF>False</FONT>); (* Integral abschätzen *)<BR> <BR> OVERFLOW := I.OVERFLOW;<BR> <FONT COLOR=#0000FF>If</FONT> <FONT COLOR=#0000FF>Not</FONT> OVERFLOW <FONT COLOR=#0000FF>Then</FONT><BR> Y:=Y_OFFSET+KP*(<FONT COLOR=#0000FF>Error</FONT>+I.OUT/TN+D.OUT*TV);<BR> <FONT COLOR=#0000FF>If</FONT> Y>1E30 <FONT COLOR=#0000FF>Or</FONT> Y<-1E30 <FONT COLOR=#0000FF>Then</FONT> (* Overflow steht bevor, darf aber eigentl ich nicht passieren *)<BR> OVERFLOW:=<FONT COLOR=#0000FF>True</FONT>;<BR> END_IF;<BR> <BR> LIMITS_ACTIVE:=<FONT COLOR=#0000FF>False</FONT>;<BR> <FONT COLOR=#0000FF>If</FONT> Y_MAX>Y_MIN <FONT COLOR=#0000FF>And</FONT> Y>Y_MAX <FONT COLOR=#0000FF>Then</FONT> (* Stellwert-Obergrenze überschritten *)<BR> Y:=Y_MAX;<BR> LIMITS_ACTIVE:=<FONT COLOR=#0000FF>True</FONT>;<BR> I(<FONT COLOR=#0000FF>In</FONT>:=-<FONT COLOR=#0000FF>Error</FONT>,TM:=TMDIFF,RESET:=<FONT COLOR=#0000FF>False</FONT>); (* Integral korrigieren *)<BR> END_IF;<BR> <BR> <FONT COLOR=#0000FF>If</FONT> Y_MAX>Y_MIN <FONT COLOR=#0000FF>And</FONT> Y<Y_MIN <FONT COLOR=#0000FF>Then</FONT> (* Stellwert-Untergrenze unterschritten *)<BR> Y:=Y_MIN;<BR> LIMITS_ACTIVE:=<FONT COLOR=#0000FF>True</FONT>;<BR> I(<FONT COLOR=#0000FF>In</FONT>:=-<FONT COLOR=#0000FF>Error</FONT>,TM:=TMDIFF,RESET:=<FONT COLOR=#0000FF>False</FONT>); (* Integral korrigieren *)<BR> END_IF;<BR> END_IF;<BR> <FONT COLOR=#0000FF>Else</FONT><BR> CLOCK(PT:=t#1h,IN:=<FONT COLOR=#0000FF>True</FONT>);<BR> END_IF;<BR> <BR> END_IF;<BR>
Sorry - Ich dachte das Forum kann HTML. Hier nochmal als reiner Text: (* PID controller / PID-Regler *) FUNCTION_BLOCK PID VAR_INPUT ACTUAL :REAL; (* actual value, process variable / Istwert *) SET_POINT:REAL; (* desired value, set point / Sollwert *) KP:REAL; (* proportionality const. / Proportionalitätskoeff. *) TN:DWORD; (* reset time / Nachstellzeit in msec *) TV:DWORD; (* rate time, derivative time / Vorhaltzeit in msec *) Y_OFFSET:REAL; (* offset for manipulated variable / Stellwert-Nullpunktsverschiebung *) Y_MIN:REAL; (* minimum value for manipulated variable / minimaler Stellwert *) Y_MAX:REAL; (* maximum value for manipulated variable / maximaler Stellwert *) MANUAL:BOOL; (* TRUE: manual / TRUE: manueller Betrieb *) RESET:BOOL; END_VAR VAR_OUTPUT Y:REAL; (* manipulated variable, set value / Stellgröße *) LIMITS_ACTIVE:BOOL:=FALSE; OVERFLOW:BOOL:=FALSE; END_VAR VAR CLOCK:TON; I: INTEGRAL; D: DERIVATIVE; TMDIFF: DWORD; ERROR: REAL; INIT: BOOL:=TRUE; END_VAR IF TN>0 AND KP<> 0 AND (NOT OVERFLOW OR RESET OR MANUAL) THEN ERROR := SET_POINT-ACTUAL; ( Regeldifferenz ) IF RESET OR MANUAL OR INIT THEN (* Reset oder Handbetrieb *) I(RESET:=TRUE); D(RESET:=TRUE); OVERFLOW:=FALSE; LIMITS_ACTIVE:=FALSE; IF RESET OR INIT THEN Y := Y_OFFSET; INIT:=FALSE; END_IF; TMDIFF:=0; ELSE CLOCK; ( Timer abfragen ) TMDIFF:=TIME_TO_DWORD(CLOCK.ET); (* Zeitdifferenz seit letztem Aufruf *) END_IF; IF TMDIFF>0 THEN CLOCK(IN:=FALSE); ( Timer neu starten ) CLOCK(PT:=t#1h, IN:=TRUE); D(IN:=ERROR, TM:=TMDIFF, RESET:=FALSE); (* Differential abschätzen *) I(IN:=ERROR, TM:=TMDIFF, RESET:=FALSE); (* Integral abschätzen *) OVERFLOW := I.OVERFLOW; IF NOT OVERFLOW THEN Y:=Y_OFFSET+KP*(ERROR+I.OUT/TN+D.OUT*TV); IF Y>1E30 OR Y<-1E30 THEN (* Overflow steht bevor, darf aber eigentlich nicht passieren *) OVERFLOW:=TRUE; END_IF; LIMITS_ACTIVE:=FALSE; IF Y_MAX>Y_MIN AND Y>Y_MAX THEN (* Stellwert-Obergrenze überschritten *) Y:=Y_MAX; LIMITS_ACTIVE:=TRUE; I(IN:=-ERROR,TM:=TMDIFF,RESET:=FALSE); (* Integral korrigieren *) END_IF; IF Y_MAX>Y_MIN AND Y<Y_MIN THEN (* Stellwert-Untergrenze unterschritten *) Y:=Y_MIN; LIMITS_ACTIVE:=TRUE; I(IN:=-ERROR,TM:=TMDIFF,RESET:=FALSE); (* Integral korrigieren *) END_IF; END_IF; ELSE CLOCK(PT:=t#1h,IN:=TRUE); END_IF; END_IF;
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.