www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik PID-Regler


Autor: sascha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: afzelia (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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



(*&nbsp;PID&nbsp;controller&nbsp;/&nbsp;PID-Regler&nbsp;*)<BR>
FUNCTION_BLOCK&nbsp;PID<BR>
VAR_INPUT<BR>
  ACTUAL&nbsp;:REAL; 
(*&nbsp;actual&nbsp;value,&nbsp;process&nbsp;variable&nbsp;/&nbsp;Istwer 
t&nbsp;*)<BR>
  SET_POINT:REAL;    (*&nbsp;desired&nbsp;value,&nbsp;<FONT 
COLOR=#0000FF>Set</FONT>&nbsp;point&nbsp;/&nbsp;Sollwert&nbsp;*)<BR>
  KP:REAL;      (*&nbsp;proportionality&nbsp;<FONT 
COLOR=#0000FF>Const</FONT>.&nbsp;/&nbsp;Proportionalit&auml;tskoeff.&nbs 
p;&nbsp;*)<BR>
  TN:DWORD; 
(*&nbsp;reset&nbsp;time&nbsp;/&nbsp;Nachstellzeit&nbsp;<FONT 
COLOR=#0000FF>In</FONT>&nbsp;msec&nbsp;*)<BR>
  TV:DWORD; 
(*&nbsp;rate&nbsp;time,&nbsp;derivative&nbsp;time&nbsp;/&nbsp;Vorhaltzei 
t&nbsp;<FONT  COLOR=#0000FF>In</FONT>&nbsp;msec&nbsp;*)<BR>
  Y_OFFSET:REAL;    (*&nbsp;offset&nbsp;<FONT 
COLOR=#0000FF>For</FONT>&nbsp;manipulated&nbsp;variable&nbsp;/&nbsp;Stel 
lwert-Nullpunktsverschiebung&nbsp;*)<BR>
  Y_MIN:REAL;      (*&nbsp;minimum&nbsp;value&nbsp;<FONT 
COLOR=#0000FF>For</FONT>&nbsp;manipulated&nbsp;variable&nbsp;/&nbsp;mini 
maler&nbsp;Stellwert&nbsp;*)<BR>
  Y_MAX:REAL;      (*&nbsp;maximum&nbsp;value&nbsp;<FONT 
COLOR=#0000FF>For</FONT>&nbsp;manipulated&nbsp;variable&nbsp;/&nbsp;maxi 
maler&nbsp;Stellwert&nbsp;*)<BR>
  MANUAL:BOOL;    (*&nbsp;<FONT 
COLOR=#0000FF>True</FONT>:&nbsp;manual&nbsp;/&nbsp;<FONT 
COLOR=#0000FF>True</FONT>:&nbsp;manueller&nbsp;Betrieb&nbsp;*)<BR>
  RESET:BOOL;<BR>
END_VAR<BR>
VAR_OUTPUT<BR>
  Y:REAL;        (*&nbsp;manipulated&nbsp;variable,&nbsp;<FONT 
COLOR=#0000FF>Set</FONT>&nbsp;value&nbsp;/&nbsp;Stellgr&ouml;&szlig;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:&nbsp;INTEGRAL;<BR>
  D:&nbsp;DERIVATIVE;<BR>
  TMDIFF:&nbsp;DWORD;<BR>
  <FONT COLOR=#0000FF>Error</FONT>:&nbsp;REAL;<BR>
  INIT:&nbsp;BOOL:=<FONT COLOR=#0000FF>True</FONT>;<BR>
END_VAR<BR>
<BR>
<BR>
<BR>
<BR>
<FONT COLOR=#0000FF>If</FONT>&nbsp;TN&gt;0&nbsp;<FONT 
COLOR=#0000FF>And</FONT>&nbsp;KP&lt;&gt;&nbsp;0&nbsp;<FONT 
COLOR=#0000FF>And</FONT>&nbsp;(<FONT 
COLOR=#0000FF>Not</FONT>&nbsp;OVERFLOW&nbsp;<FONT 
COLOR=#0000FF>Or</FONT>&nbsp;RESET&nbsp;<FONT 
COLOR=#0000FF>Or</FONT>&nbsp;MANUAL)&nbsp;<FONT 
COLOR=#0000FF>Then</FONT><BR>
  <FONT COLOR=#0000FF>Error</FONT>&nbsp;:=&nbsp;SET_POINT-ACTUAL; 
(*&nbsp;Regeldifferenz&nbsp;*)<BR>
<BR>
  <FONT COLOR=#0000FF>If</FONT>&nbsp;RESET&nbsp;<FONT 
COLOR=#0000FF>Or</FONT>&nbsp;MANUAL&nbsp;<FONT 
COLOR=#0000FF>Or</FONT>&nbsp;INIT&nbsp;<FONT COLOR=#0000FF>Then</FONT> 
(*&nbsp;Reset&nbsp;oder&nbsp;Handbetrieb&nbsp;*)<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>&nbsp;RESET&nbsp;<FONT 
COLOR=#0000FF>Or</FONT>&nbsp;INIT&nbsp;<FONT 
COLOR=#0000FF>Then</FONT><BR>
      Y&nbsp;:=&nbsp;Y_OFFSET;<BR>
      INIT:=<FONT COLOR=#0000FF>False</FONT>;<BR>
    END_IF;<BR>
    TMDIFF:=0;<BR>
  <FONT COLOR=#0000FF>Else</FONT><BR>
    CLOCK; 
(*&nbsp;Timer&nbsp;abfragen&nbsp;*)<BR>
    TMDIFF:=TIME_TO_DWORD(CLOCK.ET); 
(*&nbsp;Zeitdifferenz&nbsp;seit&nbsp;letztem&nbsp;Aufruf&nbsp;*)<BR>
  END_IF;<BR>
<BR>
  <FONT COLOR=#0000FF>If</FONT>&nbsp;TMDIFF&gt;0&nbsp;<FONT 
COLOR=#0000FF>Then</FONT><BR>
    CLOCK(<FONT COLOR=#0000FF>In</FONT>:=<FONT 
COLOR=#0000FF>False</FONT>); 
(*&nbsp;Timer&nbsp;neu&nbsp;starten&nbsp;*)<BR>
    CLOCK(PT:=t#1h,&nbsp;<FONT COLOR=#0000FF>In</FONT>:=<FONT 
COLOR=#0000FF>True</FONT>);<BR>
<BR>
    D(<FONT COLOR=#0000FF>In</FONT>:=<FONT 
COLOR=#0000FF>Error</FONT>,&nbsp;TM:=TMDIFF,&nbsp;RESET:=<FONT 
COLOR=#0000FF>False</FONT>); 
(*&nbsp;Differential&nbsp;absch&auml;tzen&nbsp;*)<BR>
    I(<FONT COLOR=#0000FF>In</FONT>:=<FONT 
COLOR=#0000FF>Error</FONT>,&nbsp;TM:=TMDIFF,&nbsp;RESET:=<FONT 
COLOR=#0000FF>False</FONT>); 
(*&nbsp;Integral&nbsp;absch&auml;tzen&nbsp;*)<BR>
<BR>
    OVERFLOW&nbsp;:=&nbsp;I.OVERFLOW;<BR>
    <FONT COLOR=#0000FF>If</FONT>&nbsp;<FONT 
COLOR=#0000FF>Not</FONT>&nbsp;OVERFLOW&nbsp;<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>&nbsp;Y&gt;1E30&nbsp;<FONT 
COLOR=#0000FF>Or</FONT>&nbsp;Y&lt;-1E30&nbsp;<FONT 
COLOR=#0000FF>Then</FONT> 
(*&nbsp;Overflow&nbsp;steht&nbsp;bevor,&nbsp;darf&nbsp;aber&nbsp;eigentl 
ich&nbsp;nicht&nbsp;passieren&nbsp;*)<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>&nbsp;Y_MAX&gt;Y_MIN&nbsp;<FONT 
COLOR=#0000FF>And</FONT>&nbsp;Y&gt;Y_MAX&nbsp;&nbsp;<FONT 
COLOR=#0000FF>Then</FONT> 
(*&nbsp;Stellwert-Obergrenze&nbsp;&uuml;berschritten&nbsp;*)<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>); 
(*&nbsp;Integral&nbsp;korrigieren&nbsp;*)<BR>
      END_IF;<BR>
<BR>
      <FONT COLOR=#0000FF>If</FONT>&nbsp;Y_MAX&gt;Y_MIN&nbsp;<FONT 
COLOR=#0000FF>And</FONT>&nbsp;Y&lt;Y_MIN&nbsp;<FONT 
COLOR=#0000FF>Then</FONT> 
(*&nbsp;Stellwert-Untergrenze&nbsp;unterschritten&nbsp;*)<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>); 
(*&nbsp;Integral&nbsp;korrigieren&nbsp;*)<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>

Autor: afzelia (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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;

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.