Einstieg in die Regelungstechnik mit Python

Fachbuch von Hans-Werner Philippsen

Kapitel 9

Es folgen Programme des Beispielkapitels.


web901

CODESYS-Programm PI-Regler

Listing 9.1 und Listing 9.2: CODESYS Hauptprogramm und Funktionsbaustein Beispiel 9.1.2

PROGRAM PLC_PRG 
VAR 
  INIT:BYTE:=0; 
  Regler:PI_REGLER;     (*Instanz des Funktions-   
      blocks PI_REGLER*) 
  A_IN AT %IW1:INT;     (*Analog-Kanal 2*) 
  A_OUT AT %QW1:WORD;    (*Analog-Kanal 2 Ausgang*) 
  Drehzahl:REAL;       (*in U/min*) 
  Fuehrungsgroesse: REAL := 0;  (*in U/min*) 
  Stellgroesse: REAL := 0;  (*in Volt*) 
  Kp:REAL := 0; 
  Tn:REAL := 0; 
  T0:REAL := 0.05; 
  d0:REAL := 0; 
  d1:REAL := 0; 
END_VAR 
 
(**Initialisierung  Regler und Zähler (falls gesteckt)******) 
CASE INIT OF 
0:      (*Initialisierung Zähler (falls gesteckt)*) 
  INIT:=1; 
  RETURN; 
1: 
 
(*********Initialisierung des Reglers********************) 
(*Die folgenden Variablen werden über Winfact gesetzt *) 
 
  Kp:= (INT_TO_REAL(%IW256))*0.001; 
  Tn:= (INT_TO_REAL(%IW257))*0.001; 
  Fuehrungsgroesse:=(INT_TO_REAL(%IW259))*0.1; 
 
  IF Kp = 0 THEN  (* ist WinFACT nicht in Betrieb! *) 
    Kp:=6;   217 
    Tn:=0.9; 
    Fuehrungsgroesse := 1; 
  END_IF 
  (*Diskretisierung des Reglers*) 
  d0 :=    Kp *T0 /(2*Tn) + Kp; 
  d1 :=    Kp *T0 /(2*Tn) - Kp; 
 
   INIT:=2; 
RETURN; 
 
2:  (* CASE 2: Ausführung wenn INIT = 2*) 
 
(********  Einlesen Daten Analogeingang***************) 
 
  Drehzahl:=INT_TO_REAL(A_IN)*0.00030518509; 
   
(******************Aufruf Funktionsblock PI-REGLER ********) 
 
Regler(xk:=Drehzahl, wk:=Fuehrungsgroesse, rd0:=d0, rd1:=d1); 
Stellgroesse:=Regler.yk; 
 
%QW257:=REAL_TO_INT(Drehzahl* 1000);          
  (*Speichere Regelgröße in %QW257 für Boris*) 
%QW258:=REAL_TO_INT(Stellgroesse*1000);         
  (*Speichere Stellgröße in %QW258 für Boris*) 
 
(**********analoge Ausgabe*************************) 
 
A_OUT:=REAL_TO_INT(  Stellgroesse * 3276.7); 
(*Umrechnung Real in Zahlenformat für die analoge Ausgabe*) 
 
(* Zur Sicherheit keine negative Spannungsausgabe *) 
  IF A_OUT > 32767 THEN             
    A_OUT:= 0;    (* 0V = Motor stopp *) 
  END_IF 
END_CASE 
FUNCTION_BLOCK PI_REGLER 
VAR_INPUT 
  wk: REAL := 0; 
  xk: REAL := 0; 
  rd0:REAL := 0; 
  rd1:REAL := 0; 
END_VAR 
VAR_OUTPUT 
  yk: REAL; 
END_VAR 
VAR 
  Min_Stell: REAL := 0.0;   (*kleinster Wert von y k  *) 
  Max_Stell: REAL := 10.0;  (*größter Wert von y k  *)   218 
  ek: REAL := 0.0;      (*Regelfehler *) 
  ek1: REAL := 0.0;     (*Regelfehler k-1*) 
  yk1: REAL:=0.0;      (*Stellgröße k-1*) 
END_VAR 
 
ek := wk - xk; 
yk := yk1 + rd0*ek +rd1*ek1; 
 
(*Stellgrößenbegrenzung ohne AWR*) 
  IF yk < Min_Stell THEN 
    yk := Min_Stell; 
  ELSIF yk > Max_Stell THEN 
    yk := Max_Stell; 
  END_IF 
yk1:=yk; 
ek1:=ek; 
 
%QW260:=REAL_TO_INT(xk*100); 
%QW261:=REAL_TO_INT(yk*100); 

web903

DC-Motor Beispiel 9.1.4

Listing 9.3: Der DC-Motor wird inklusive Regelung im Zustandsraum dargestellt und simuliert.

# -*- coding: utf-8 -*-
"""

DC-Motor mit P-PI-Lageregler im Zustandsraum und G(s)
Kaskade gemäß Faulhaber MC5005
Created on 12.4. 2019, mod. 20.8.24
@author: philippsen
"""

import numpy as np
import control as ct
import matplotlib.pyplot as plt

Tc = 1e-3       #  Ersatzzeitkonstante Stromregelkreis
zpiJ = 47.119e-6 #	 Meine Berechnung 2pi7,5e-6
KL = 1          #  Integrierbeiwert Lagestrecke
cPsi= 0.0318    #   Datenblatt Faulhaber
Ks = cPsi/zpiJ  #  Verstärkung Teilstrecke

a= 16
KR= 1/(a*Ks*Tc) #  Verstärkung Drehzahlregler gemäß SymOpt
Tnv = a*a*Tc    #  Nachstellzeit Drehzahlregler
Tnv = 2*a*Tc    #  Nachstellzeit Drehzahlregler modifiziert
Kreib=1e-5
 
a1 = KR*Ks; a2 = a1*Tnv; a3 = Tnv; a4 = a3*Tc

null = np.roots([a4*a2, 0, (a3*a1 - a2*a2 ), 0, -a1*a1]);
wi = np.max(null)
Kkrit = (1/KL)*(a3*a2*wi**4 - a2*a1*wi**2 -a4*a1*wi**4 +a2*a1*wi**2)/( (a2**2)*(wi**2) + a1**2 )
Kv= Kkrit/40        #   Verstärkung Lageregler
   
Ar  = np.array([[0, KL, 0, 0],
                [0, -Kreib/zpiJ, cPsi/zpiJ, 0],
                [-KR*Kv/Tc, -KR/Tc, -1/Tc, 1/Tc],
                [-KR*Kv/Tnv, -KR/Tnv, 0, 0]])
br  = np.array([[ 0. ],[ 0], [KR*Kv/Tc],[KR*Kv/Tnv]])
cr  = np.array([1, 0, 0, 0])
C  = np.array([[1, 0, 0, 0],
                [0, 1, 0, 0],
                [0, 0, 1, 0],
                [0, 0, 0, 1]])
D  = np.array([[ 0. ],[ 0], [0],[0]])
DCkreis = ct.ss(Ar, br, cr, 0)

t, y, x =ct.step_response(DCkreis,return_x=True)
plt.subplot(3,1,1)
plt.plot(t,x[0,:])
plt.title('Lageregelkreis DC-Motor'); plt.ylabel('Lage')
plt.xlabel('t [s]')
plt.grid(True)
plt.subplot(3,1,2)
plt.plot(t,x[1,:],'g')
plt.xlabel('t [s]'); plt.ylabel('n(t)')
plt.grid(True)
plt.subplot(3,1,3)
plt.plot(t,x[2,:],'r')
plt.xlabel('t [s]'); plt.ylabel('Strom')
plt.grid(True)

plt.figure() # neue Plot-Funktion
DCkreis = ct.ss(Ar, br, C, D)
ct.step_response(DCkreis).plot(
    title='Sprungantwort Lageregelkreis')

Theme von Anders Norén