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.