PWM für PID-Ausgang - Twincat3

MZo

Level-1
Beiträge
20
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Zusammen,

Projekt an der Hochschule: PID-Regler für Temperaturregelung.

Ich habe einen PID-Regler realisiert der die Temperatur in einem Modul regeln soll (Entwicklungsumgebung Twincat3).
Dazu habe ich den Funktionsblock FB_BasicPID verwendet die Soll- und Isttemperatur und die PID Werte werden hier übergeben und intern berechnet,
sodass ich am Ausgang des Reglers einen Wert habe, der sich ständig ändert.
Das heizen soll über ein Halbleiterrelai (SSR) funktionieren.

Mein Problem:
Ich weis, dasss ich dazu eine PWM verwenden muss, damit ich die gewünschte Temperatur mit möglichst wenig Überschwingung erreiche.
Doch ich weis nicht wie ich diese PWM realisieren soll.
Ich darf keine weitere lizensabhängiges FB verwenden, sondern sollte/muss die PWM Steuerung "zu Fuß" programmieren.

Bin recht neu hier und arbeite mich seit 1-2 Monaten erst ein in Twincat3.

Kann mir da evtl jemand weiterhelfen?

Vielen Dank schonmal im Voraus :)
 
Hallo MZo,

wenn das Ausgangssignal ein normiertes Signal im Bereich 0 ... 1 ist, kannst du beispielsweise den PWM Baustein von OSCAT benutzen. Den kannst du mit n bisschen Gehirnschmalz aber auch selber schreiben.

Du musst nur beachten, was der Tyro / das Halbleiterrelais für Nenndaten hat (minimales Puls-Pausenverhältnis, maximale 100% Zeit... schau da mal ins Datenblatt).

Viele Grüße
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo MZo,

das ist recht einfach. Ich kann Dir einen fertiogen FB zusenden, den ich unter twinCat 2 in AWL gemacht habe.
Der Eingang in dieses Bausteines bekommt 0 - 100 %, und einen Wert ( Zeitbasis ) der bestimmt wie schnell das
PWM Signal ist.
Er sieht wie folgt aus:

FUNCTION_BLOCK Allg_FB_PWM
VAR_INPUT
IN_Freigabe : BOOL;
IN_Sollwert : REAL;
IN_Zeitbasis : INT := 1000;
END_VAR
VAR_OUTPUT
OUT_PWM_Signal : BOOL;
END_VAR
VAR
Sollwert_INT : INT;
Taktlaenge : INT;
Zeitbasis_Time : TIME;
Zeitbasis_Timer : TON;
Taktlaenge_Time : TIME;
Takt_Timer : TOF;
Takt_Trigger : BOOL;
END_VAR
VAR
END_VAR

(* Dieser Baustein erzeugt ein PWM Signal bei einem Eingang von
0-100% des Einganges. Der Baustein ist Zykluszeitabhängig, deshalb muss die
Zeitbasis angegeben werden. *)

(* Wandlung Sollwert *)
LD IN_Sollwert
REAL_TO_DINT
DINT_TO_INT
ST Sollwert_INT

LD Sollwert_INT
GT 1.0
AND IN_Freigabe
JMPC Go
LD 0
ST Sollwert_INT
LD FALSE
ST OUT_PWM_Signal
RET
(* Prozentuale Taktlänge berechnen *)
Go:LD IN_Zeitbasis (* 1ne Sekunde *)
DIV 100 (* 10 ms *)
MUL Sollwert_INT
ST Taktlaenge

(* Zeitbasis, also Länge des Taktes pro Zeitbasis in Zeit umrechnen *)
LD IN_Zeitbasis
INT_TO_TIME
ST Zeitbasis_Time

(* Timer für Zeitbasis *)
LD IN_Freigabe
ANDN Takt_Trigger
ST Zeitbasis_Timer.IN
CAL Zeitbasis_Timer(PT :=Zeitbasis_Time)
LD Zeitbasis_Timer.Q
ST Takt_Trigger

(* Länge des Taktes pro Zeitbasis in Time umrechnen *)
LD Taktlaenge
INT_TO_TIME
ST Taktlaenge_Time

(* Takt ausgeben *)
LD IN_Freigabe
AND Takt_Trigger
ST Takt_Timer.IN
CAL Takt_Timer(PT :=Taktlaenge_Time)
LD Takt_Timer.Q
ST OUT_PWM_Signal

Also bei einer Zeitbasis von 1000 und einer Zykluszeit von 1 ms ergibt sich
für jeden Takt des PWM Signals eine Länge von 1 sek. (1000 ms )
Bei einem Sollwert von 10.0 ergibt sich 900ms aus und 100 ms ein.

Das ganze habe ich bei Bedarf auch für sehr schnelle Zykluszeiten gemacht,
um Beispielsweise Gleichstrommotoren in der Drehzahl zu regeln.


Gruß Jörg
 
Abhängig von der Zykluszeit des Reglers und der Taskzeit der Steuerung wär zum Beispiel für den PWM-Teil ein freilaufender Zähler denkbar, der in jedem Zyklus inkrementiert wird (Byte). Der zählt jetzt bis zu einem von Dir definierten Wert hoch und wird auf Null zurückgesetzt.
Der Ausgang wird über einen <= Vergleich des PID-Ausgangswerts mit dem Zahlerwert geschaltet. Dafür muss der PID-Ausgangswert auf Deinen gewählten Zählbereich normiert werden.

Beispiel:
Zähler 0...100
PID-Ausgang 0...100%

Wenn PID-Ausgang > 0 und Zähler >= PID-Ausgang dann Heizausgang ein.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Soo, Hallo nochmal,

Tut mir leid für die späte Rückmeldung, war ziemlich angeschlagen und lag im Krankenhaus..

Danke auf jeden Fall für eure Hilfe :)

das ist recht einfach. Ich kann Dir einen fertiogen FB zusenden, den ich unter twinCat 2 in AWL gemacht habe.

Dein Code wäre ziemlich interessant eigentlich sowas ähnliches habe ich auch versucht nur ich blicke nicht so genau durch, da ich nur in ST programmiere und nicht AWL, schade..

@wollvieh danke für dein Codebeispiel
 
Hallo wollvieh,

ich habe in meinem Programm die PI Werte bestimmt und zwischen 0-255 skaliert. Sprich ich mach bei Reglerausgang>255 Heizen und Reglerausgang zwischen 0-255 PWM.
Dein Code habe ich zum Testen in einem Funktionsblock verwendet. Die rPwmFrequenz ist bei mir 255 und rDutyCycle der skallierter Reglerausgang.

Habe ich die Werte soweit richtig bestimmt?, muss ich noch andere Variablen definieren? und wie genau muss ich diesen Funktionsblock in main() dann aufrufen?

Sry wenn ich mich gerade dumm anstelle, aber ich mach sowas zum ersten mal ^^

Danke schon mal für deine Hilfe :)
 
rPwmFrequenz von 255 würde 255Hz bedeuten, das heißt 4ms PWM Grundzeit, so schnell ist deine SPS sicher nicht. Sinnvolle Werte sind hier 0,1 (10s) bis 10,0 (100ms) PWM Grundzeit. Und Deine 0 bis 255 für 0..100% PWM Duty Cycle musst Du dann mittels Dreisatz nach 0..1.0 rDutyCycle umrechnen und dem FB Eingang rDutyCycle zuweisen.

https://5volt-junkie.net/was-ist-pwm-ein-kleines-tutorial/
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Okay verstehe, danke für deine Antwort :)

und was genau ist "rtmp" ? Muss da bei der Berechnung die Zahl 1000.0 bleiben oder ist die Zahl gleich der Taskzyklus?

Mein Beispiel: Das hier rufe ich bei mir im Main auf

Code:
IF Output < 255 AND Output > 0 THEN
temp:= (Output * 100) / 255;
fb_PWM(rDutyCycle:= temp, rPwmFrequency:= 0.1, xPwmOut=> );
IF fb_PWM.xPwmOut THEN
Heizen := TRUE;
END_IF
END_IF

Mein fb_PWM Baustein habe ich von dir übernommen, doch ich kann hier nicht pulsen (siehe Bild) auf dem Pulstimer.Q kommt nie eine True zustande bei mir..
 

Anhänge

  • 1.JPG
    1.JPG
    32,5 KB · Aufrufe: 33
Zuletzt bearbeitet:
Hallo

Auszug aus Deinem Code : temp:= (Output * 100) / 255;
Das ist nicht richtig. Bei Output 255 ergibt das 255*100 /255 = 100.

richtig wäre :
temp:= ( 1.0 / 255 ) * Output --> ( 1.0/255 ) * 255 = 1.0
rDutyCycle MUSS zwichen 0.0 und 1.0 betragen !
:cool:
P.S.: die rTemp 1000 sind 1000ms, da die Timer Millisekunden als Auflösung verwenden
 
Zuletzt bearbeitet:
Hallo,

ich muss für eine Arbeit in der Uni genau das gleiche wie du machen. Also mit der BasicPID Funktion in TwinCAT3 einen digitalen Ausgang über eine "selbstprogrammierten" PWM regeln.

Meine Frage:

Wie kann ich meine Ausgabewert der BasicPID Funktion auf einen Wert zwischen 0 und 1 normieren wenn dieser vom Typ LREAL ist und damit theoretisch Werte bis 1,8·10[SUP]308 [/SUP] annehmen könnte?

würde mich freuen wenn Ihr mir helfen könntet!
 
Zuviel Werbung?
-> Hier kostenlos registrieren
... eine "selbstprogrammierten" PWM ...

Wie kann ich meine Ausgabewert der BasicPID Funktion auf einen Wert zwischen 0 und 1 normieren wenn dieser vom Typ LREAL ist und damit theoretisch Werte bis 1,8·10[SUP]308 [/SUP] annehmen könnte?
Den kompletten mit LREAL darstellbaren Bereich wirst Du sicherlich nicht nutzen.
Welcher Bereich wird denn vom PID genutzt und begrenzt Du diesen Bereich (vorsichtshalber) noch zusätzlich?
Dann könntest Du Dich daran orientieren.
Man kann und sollte sich auch an dem gewünschten Ergebnis orientieren und vielleicht in Prozent (oder Promille oder ...) des vom Stellglied abgedeckten Bereichs "denken".
Fütterst Du Deine selbstprogrammierte PWM wirklich mit einem REAL- oder LREAL-Wert 0.0 .. 1.0?
 
Zurück
Oben