LOGO Logo Ausgänge flackern

mietian

Level-2
Beiträge
7
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,

ich habe ein Problem welches ich nicht gelöst bekomme und mir keine Ruhe lässt: 2 Ausgänge an meiner Logo schalten mal richtig durch, mal flackern diese. Und ja, ich habe hier schon gesucht und lese schon wieder lange mit und habe trotzdem nichts dazu gefunden.

Hier zuerst mal das Setup:
- Logo 24 CE mit FW 1.83.01 (6ED1052-1CC08-0BA1)
- Ersatz-Logo: 24CE FW 1.81.01 (6ED1052-1CC01-0BA8)
- an den Ausgängen Q1 und Q2 Halbleiterrelais Weidmüller TOS 24VDC/230VAC 0,1A
- Halbleiterrelais schalten einen Stellmotor Siemens SSA131.00 in die eine oder andere Richtung

Schaltplan und Logo-Programm siehe Anhänge.

Kurzbeschreibung der Software: Es ist eine Temperaturregelung über einen 3-Punkt-Schrittmotor. Analogwert einlesen und dann auffahren (heißer machen, Q1) oder zufahren (Q2), Q3 ist die Pumpe im Mischerkreis. Q4, 5 und 6 sind nicht benutzt. Die hatte ich nur mal wegen einfacherem Debugging drin.

In ca 30-40% der Fälle, wenn Q1 oder Q2 angesteuert werden flackern diese und schalten nicht ordentlich durch. Man sieht das an den LED's der Halbleiterrelais und am angesteuerten Gerät selbst. Mal mehrmals hintereinander, mal nur einmal und beim nächsten ansteuern ist wieder alles gut.
Das führt dann hinten dran wiederum zu mehr Problemen, weil der Antrieb Mist baut, manchmal gar nicht fährt, weil die "Taktung"/das Flackern zu schnell ist, und dann die Regelung versagt...

Jetzt ist für mich die große Frage nach dem Warum. Ich kann mir keinen Reim mehr drauf machen, als das am Ende die Last auf den Ausgängen zu gering ist, weil die Stromaufnahme der "Relaisspulen" (sind ja eigentlich Transistoren) zu gering oder grenzwertig ist, weil es mal geht mal nicht. Die Stromaufnahme der Relais beim schalten ist nur 3,6 mA. Aber in meiner kleinen Welt stört das einen Transistor nicht, wenn da zu wenig Strom drüber geht, nur wenn es zu viel ist. Darum ist das vermutlich auch nur eine dumme Idee. (Ich kenne es nur aus der Industrie oder von Brandmeldeanlagen, dass die nicht ordentlich schalten wenn der geschaltete Strom zu klein ist. Liegt aber eher daran, dass mit der Zeit die Kontakte da oxidieren wenn nur Milli- oder Mikroampere fließen über lange Zeit/viele Zyklen.)

Was ich schon gemacht habe:
- Stromaufnahme /Stromversorgung geprüft: Hutschienennetzteil mit 24V/0,6A ist verbaut. Es ist etwas klein, ja, aber ich habe die gesamte Stromaufnahme auf der 24VDC-Schiene gemessen und die war mit allem was geht (gleichzeitige Ansteuerung und Hintergrundbeleuchtung, alles an) nicht über 0,08A zu kriegen. Da liegt fast Faktor 10 dazwischen. Und die Spannung ist auch stabil. Ich konnte keinen Spannungseinbruch messen.
- Ersatz-Logo eingebaut: Ich habe eine ähnliche Logo noch rumliegen und habe die mal getauscht mit dem Ergebnis, dass es das gleiche ist. Mal flackern, mal nicht.

Die Software tut was sie soll. Das weiß ich aus Simulationen und aus Datenlogs. Oder ich bin der Meinung, dass es so ist, aber wer kann darf mich auch hier eines besseren belehren.

Inzwischen bin ich ratlos und für Ideen und Verbesserungsvorschläge zu haben.
Ich hoffe ich habe an alles gedacht.

Schonmal im Vorraus vielen Dank für Eure Unterstützung.

Grüße
Patrick

p.s.: Ich habe auch Videos davon, wollte die aber nicht direkt mit anhängen, kann aber gerne nachgeholt werden.
 

Anhänge

  • IMG_20251214_123401.jpg
    IMG_20251214_123401.jpg
    1.010,4 KB · Aufrufe: 42
  • IMG_20251214_123335.jpg
    IMG_20251214_123335.jpg
    1,1 MB · Aufrufe: 40
  • Schaltplan_FBH_OG_rev1.zip
    Schaltplan_FBH_OG_rev1.zip
    154,6 KB · Aufrufe: 10
Klemm mal den Motor ab und bau dir mal ein Testprogramm. Irgendwas in der Art x Sekunden an und y Sekunden aus.
Dann kannst du mal schauen, ob's an der Hardware oder doch an der Software liegt.
 
Danke erstmal für die schnellen Antworten.

Erstmal zum Oberchefe, weil ich das einfacher ist. Ja, Fehlerfall ist nicht ordentlich abgefangen, muss ich zugeben. Aber das flackern ist nicht hin und her zwischen Q1 und Q2 sondern nur der jeweils angesteuerte Ausgang flackert, also geht an und aus. Und ich habe zwischen den Richtungen etwas Toleranz drin. Auffahren hört auf bei 36°C und zufahren fängt erst bei 38°C an. Den Rest macht die Physik, weil das Ssystem aus Wasser, Rohr und Masse des Temperaturfühlers doch leicht träger ist als die Logo.

Dann zu Blockmove: Test ohne Motor kann ich morgen mal machen. Motor abklemmen und Sensor anwärmen ist machbar. Wobei ich nicht an eine Rückwirkung des Motors glaube, weil der auf der 24VAC Schiene hängt und an DC nichts macht. Es sind auch zwei getrennte Netzteile. Aber ich teste.
Und ich verstehe nicht so ganz was für eine Testsoftware, aber ich nehme mal an, das bezog sich auf die steigende Temperaturen zu simulieren und den Motor auch in die andere Richtung fahren zu lassen.

Danke schonmal und ich werde morgen berichten.

Grüße
Patrick
 
Laut Deinem E-Plan (Handskizze) hast Du keine Schutzbeschaltung an den Relais K2 / K3. Das würde ich auf jeden Fall ändern.
Eventuell die Motorleitung als geschirmte Leitung ausführen auf jeden Fall aber die Temp.fühlerleitung auf die LOGO (I1/ AI3 ).
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Und ich verstehe nicht so ganz was für eine Testsoftware
Du baust dir ein Programm mit einem Timer der den Motor für 5s in die eine Richtung fährt. Und dann wieder 5s wartet.

Also einfach das Programm aufs nötige runterbrechen. Und schauen was Real passiert.

Eigentlich gibt man dem Regler ja eine Mindest verstellzeit mit und die Zeit für den Verstellweg. Könnte mir dein Programm leider nicht anschauen.
 
So, gestern hat er mir leider nicht mehr gereicht zu schreiben.

Die Ursache für das Flackern ist gefunden. Es lag doch an der Software, genauer gesagt sogar an den Analogwerten. Mir ist durch Zufall aufgefallen, dass das Flackern immer nur im Grenzbereich passiert in dem der Regler nicht mehr regeln soll. also zum Beispiel beim wärmer machen (auffahren) genau an der Schwelle von 35°C zu 36°C. Der rohe Analogwert hat geschwankt, gerade um den Wert herum und das hat dann dazu geführt, dass der Ausgang mit an und ausgegangen ist. Außerdem hatte ich noch eine "Handverstellung" des Antriebs über die Cursortasten der Logo drin unnd da war die Ansteuerung immer flackerfrei.

Ich habe das ganze jetzt dadurch im Griff, dass ich das Ergebnis der Analogwertauswertung jeweils in einem RS-Flip-Flop speichere und so ein konstantes Signal habe zur Ansteuerung.

Somit ist das eigentliche Problem gelöst. Wenn es jemanden interessiert ist die neue Schaltung mit anbei.

Jetzt muss ich noch den eigentlichen Regler in den Griff bekommen, weil der jetzt doch spürbar schneller geworden ist und es jetzt wieder über die Maßen schwingt. Meine Bemühungen dahingehend sind aber wohl eher Stoff für einen neuen Thread, weil es um die Eigenheiten der Analogwertbausteine geht und nichts mehr mit dem eigenltichen Titel zu tun hat.

Danke für die Diskussion und Hinweise, die dann letztlich doch die richtige Richtung gezeigt haben.

Grüße
Patrick
 

Anhänge

Je nach Verwendung kann auch ein Flip-Flop zyklisch hin und her flattern!
Was du brauchst, ist eine Hysterese.
Ein bei Temperatur x.
Aus bei Temperatur x+y.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Danke, aber Hysterese ist drin. Problem ist die Trägheit. Ich muss den ganzen Regler stark einbremsen... weil sonst die Stellgröße schon zu sehr beeinflusst wurde.

Und ich denke, dass ich die Flip-Flops ordentlich genutzt habe. Aber Ihr könnt gerne noch Gegenvorschläge machen.

Grüße
Patrick

edit: mein aktuelles Problem ist, dass ich versuche zu erkennen ob sich die Regelgröße gerade noch ändert oder nicht und davon abhängig dann nochmal einen Impuls an die Stellgröße zu geben oder eben nicht. Aber das funktioniert noch nicht so wie gewünscht.... Der Baustein Analogwertüberwachung ist nicht ganz so trivial anzuwenden. Aber das ist, wie schon gesagt, in meinen Augen ein anderes Thema
 
Moin,
ich hatte ein ähnliches Problem. Hast Du mal einen Analogfilter probiert? Damit lassen sich solche Schwankungen sehr gut glätten... nur eine Idee zu dem Thema
 
Es lag doch an der Software, genauer gesagt sogar an den Analogwerten. Mir ist durch Zufall aufgefallen, dass das Flackern immer nur im Grenzbereich passiert in dem der Regler nicht mehr regeln soll.
Das habe ich mir Gedacht ;) und andere denke ich auch! Ich kenne mich mit der Logo zu wenig aus was die Möglichkeiten der Regelung angeht. Aber eigentlich lässt man ja einfach die Stellzeit vom PID mit einem Tod Band Laufen. Dann gibt es irgendwann eine Mindestlaufzeit die auf den Ausgang gelegt wird. Gleichzeitig kann man dann die Zeiten der Ausgänge mit Summieren und hat dann eine Schätzung der ist Position vom Ventil.

Ich würde aber aktuell immer einen weiten Weg um die Logo machen, weil es günstig China SPSen gibt die sich "klassisch" programmieren lassen.

Ziehe meinen Hut vor einigen aus dem Forum was die aus der Logo Zaubern.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich würde aber aktuell immer einen weiten Weg um die Logo machen, weil es günstig China SPSen gibt die sich "klassisch" programmieren lassen.
Es ist nicht relevant welche Steuerung du im Einsatz hast – eine Hysterese ist bei Schaltpunkten um einer Grenzwert immer erforderlich.
 
Es ist nicht relevant welche Steuerung du im Einsatz hast – eine Hysterese ist bei Schaltpunkten um einer Grenzwert immer erforderlich.
Ja, mir ging es nur darum das die Möglichkeiten mit anderen Steuerungen in der Regelungstechnik besser sind als mit der Logo. Beziehungsweise einfacher zu implementieren.
Der Baustein Analogwertüberwachung ist nicht ganz so trivial anzuwenden
Und wenn Logo Funktionen und Programme größe werden, finde ich die Struktur sehr Gewöhnungsbedürftig 😄.

In diesem Fall versucht man sich ja glaube ich um den Eingang zu kümmern. Aber IMHO muss man einfach die Stellgröße und Ausgänge beobachten und erst weitergeben wenn Zeit X zur Soll verstellzeit erreicht ist.

Ich kenne das Programm vom Kollegen aber nicht.

Hier mal ein KI Beispiel, selber habe ich das noch nicht implementiert.

Code:
FUNCTION_BLOCK FB_Schrittregler_Final
VAR_INPUT
    rSetPoint      : REAL;    (* Sollwert (z.B. Temperatur) *)
    rActualValue   : REAL;    (* Istwert vom Sensor *)
    bManual        : BOOL;    (* Handbetrieb-Modus *)
    rManualOut     : REAL;    (* Manueller Stellgrad 0-100% *)
    tCycleTime     : TIME := T#100ms; (* Aufrufintervall (WICHTIG!) *)
END_VAR

VAR_OUTPUT
    qUp            : BOOL;    (* Relais AUF *)
    qDown          : BOOL;    (* Relais ZU *)
    rEstimatedPos  : REAL;    (* Geschätzte Position 0..100% *)
END_VAR

VAR
    (* PID-Parameter - ggf. anpassen *)
    rKp            : REAL := 2.5;
    rTn            : REAL := 60.0;  (* Nachstellzeit in s *)
    rI_Part        : REAL;
    
    (* Ventil-Parameter *)
    rTotalRuntime  : REAL := 120.0; (* 120s Laufzeit *)
    rHysteresis    : REAL := 1.5;   (* Totzone in % *)
    rOverRun       : REAL := 12.0;  (* 10% Sicherheit für Referenzierung *)
    
    (* Interne Hilfsvariablen *)
    rError         : REAL;
    rPID_Out       : REAL;
    rCycleSec      : REAL;
END_VAR

(* ------------------------------------------------------------------------- *)
(* 1. ZEITBASIS BERECHNEN *)
rCycleSec := TIME_TO_REAL(tCycleTime) / 1000.0;

(* 2. PID-REGELALGORITHMUS (PI-Struktur) *)
rError := rSetPoint - rActualValue;

IF bManual THEN
    rPID_Out := LIMIT(0.0, rManualOut, 100.0);
    rI_Part  := rPID_Out; (* Tracking für stoßfreies Umschalten *)
ELSE
    (* I-Anteil mit Anti-Windup *)
    rI_Part := LIMIT(0.0, rI_Part + (rKp / rTn * rError * rCycleSec), 100.0);
    (* P-Anteil + I-Anteil *)
    rPID_Out := LIMIT(0.0, (rKp * rError) + rI_Part, 100.0);
END_IF;

(* 3. REFERENZIERUNG & DREI-PUNKT-LOGIK *)
IF rPID_Out >= 100.0 THEN
    (* Volle Öffnung angefordert -> Referenzierung am oberen Anschlag *)
    qDown := FALSE;
    IF rEstimatedPos < (100.0 + (rOverRun / rTotalRuntime * 100.0)) THEN
        qUp := TRUE;
    ELSE
        qUp := FALSE;
        rEstimatedPos := 100.0; (* Kalibriert *)
    END_IF;

ELSIF rPID_Out <= 0.0 THEN
    (* Volle Schließung angefordert -> Referenzierung am unteren Anschlag *)
    qUp := FALSE;
    IF rEstimatedPos > (0.0 - (rOverRun / rTotalRuntime * 100.0)) THEN
        qDown := TRUE;
    ELSE
        qDown := FALSE;
        rEstimatedPos := 0.0; (* Kalibriert *)
    END_IF;

ELSE
    (* Normalbetrieb: Vergleich PID-Soll zu Schätz-Ist *)
    qUp   := (rPID_Out > (rEstimatedPos + rHysteresis));
    qDown := (rPID_Out < (rEstimatedPos - rHysteresis));
    
    (* Schätzer im Regelbereich begrenzen *)
    rEstimatedPos := LIMIT(0.0, rEstimatedPos, 100.0);
END_IF;

(* 4. POSITIONSSCHÄTZER (INTEGRATOR) *)
IF qUp AND NOT qDown THEN
    rEstimatedPos := rEstimatedPos + (rCycleSec / rTotalRuntime * 100.0);
ELSIF qDown AND NOT qUp THEN
    rEstimatedPos := rEstimatedPos - (rCycleSec / rTotalRuntime * 100.0);
END_IF;
 
Hier mal ein KI Beispiel, selber habe ich das noch nicht implementiert..
KI ist zwar hilfreich, aber bislang habe ich die Erfahrung gemacht, dass die Bausteine sehr selten auf Anhieb funktionieren. Es war eigentlich immer Nacharbeit notwendig.
Es wäre also interessant, wenn du den Baustein mal testest.
Was mir beim Anschauen aufgefallen ist, ist dass die Regelung ohne vorherige Referenzfahrt startet.
Der Positionsschätzer hängt somit erstmal in der Luft oder hab ich da was auf die Schnelle übersehen?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Der Positionsschätzer hängt somit erstmal in der Luft oder hab ich da was auf die Schnelle übersehen?
Ich glaube da liegst du richtig! Hab es auf deine "Empfehlung" mal mit Grok gemacht. Gemini hat eine Variante wo vorher auf Referenz getestet wurde... und den Code mal mit Claude.ai überarbeitet :D. Aktuell fehlt mir leider die Zeit zum testen es wird Etwas OT hier im Logo Bereich ;).


Code:
FUNCTION_BLOCK FB_Schrittregler_Final
VAR_INPUT
    rSetPoint      : REAL;    (* Sollwert (z.B. Temperatur) *)
    rActualValue   : REAL;    (* Istwert vom Sensor *)
    bManual        : BOOL;    (* Handbetrieb-Modus *)
    rManualOut     : REAL;    (* Manueller Stellgrad 0-100% *)
    bEnable        : BOOL := TRUE;  (* Regler freigeben *)
    bForceRef      : BOOL;    (* Zwangsreferenzierung starten *)
    tCycleTime     : TIME := T#100ms; (* Aufrufintervall *)
END_VAR

VAR_OUTPUT
    qUp            : BOOL;    (* Relais AUF *)
    qDown          : BOOL;    (* Relais ZU *)
    rEstimatedPos  : REAL;    (* Geschätzte Position 0..100% *)
    bIsReferenced  : BOOL;    (* TRUE = System ist referenziert *)
    eState         : INT;     (* Status: 0=Init, 1=RefDown, 2=RefUp, 3=Normal, 4=Error *)
END_VAR

VAR
    (* PID-Parameter - ggf. anpassen *)
    rKp            : REAL := 2.5;
    rTn            : REAL := 60.0;  (* Nachstellzeit in s *)
    rTd            : REAL := 0.0;   (* Vorhaltzeit (optional) *)
    rI_Part        : REAL;
    rD_Part        : REAL;
    rLastError     : REAL;
    
    (* Ventil-Parameter *)
    rTotalRuntime  : REAL := 120.0; (* Laufzeit 0-100% *)
    rHysteresis    : REAL := 1.5;   (* Totzone in % *)
    rOverRun       : REAL := 12.0;  (* Überlauf für sichere Referenzierung (10%) *)
    rRefTimeout    : REAL := 150.0; (* Timeout für Referenzierung in s *)
    
    (* Interne Zustandsvariablen *)
    rError         : REAL;
    rPID_Out       : REAL;
    rCycleSec      : REAL;
    rRefTimer      : REAL;  (* Timer für Referenzierung *)
    bFirstCycle    : BOOL := TRUE;
    eLastState     : INT;
    
    (* Sicherheit & Diagnose *)
    rMinValidPos   : REAL := -15.0;  (* Erlaubter Bereich für Schätzer *)
    rMaxValidPos   : REAL := 115.0;
    bOutputLocked  : BOOL;  (* Ausgangssperre bei Fehler *)
END_VAR

(* ========================================================================= *)
(* HAUPTPROGRAMM *)
(* ========================================================================= *)

(* 1. ZEITBASIS & INITIALISIERUNG *)
rCycleSec := TIME_TO_REAL(tCycleTime) / 1000.0;

IF bFirstCycle THEN
    eState := 0;  (* Start im Init-Zustand *)
    bIsReferenced := FALSE;
    rEstimatedPos := 50.0;  (* Mittelstellung annehmen *)
    rI_Part := 50.0;
    bOutputLocked := FALSE;
    bFirstCycle := FALSE;
END_IF;

(* 2. ZWANGSREFERENZIERUNG *)
IF bForceRef AND (eState = 3) THEN
    eState := 0;
    bIsReferenced := FALSE;
    rRefTimer := 0.0;
END_IF;

(* 3. ZUSTANDSMASCHINE *)
CASE eState OF
    
    (* --------------------------------------------------------------- *)
    0: (* INIT - Startzustand, Referenzierung vorbereiten *)
    (* --------------------------------------------------------------- *)
        qUp := FALSE;
        qDown := FALSE;
        rRefTimer := 0.0;
        
        IF bEnable THEN
            eState := 1;  (* Starte mit Schließen (unterer Anschlag) *)
        END_IF;
    
    (* --------------------------------------------------------------- *)
    1: (* REFERENZIERUNG UNTEN - Fahre zum unteren Anschlag *)
    (* --------------------------------------------------------------- *)
        qUp := FALSE;
        qDown := TRUE;
        rRefTimer := rRefTimer + rCycleSec;
        
        (* Warte auf vollständiges Schließen + Überlauf *)
        IF rRefTimer >= (rTotalRuntime + rOverRun) THEN
            rEstimatedPos := 0.0;  (* Position kalibriert *)
            eState := 2;  (* Weiter zu oberer Referenzierung *)
            rRefTimer := 0.0;
        ELSIF rRefTimer > rRefTimeout THEN
            eState := 4;  (* Timeout-Fehler *)
            bOutputLocked := TRUE;
        END_IF;
    
    (* --------------------------------------------------------------- *)
    2: (* REFERENZIERUNG OBEN - Fahre zum oberen Anschlag *)
    (* --------------------------------------------------------------- *)
        qUp := TRUE;
        qDown := FALSE;
        rRefTimer := rRefTimer + rCycleSec;
        
        (* Fahre Position mit um Überprüfung zu ermöglichen *)
        rEstimatedPos := (rRefTimer / rTotalRuntime) * 100.0;
        
        IF rRefTimer >= (rTotalRuntime + rOverRun) THEN
            rEstimatedPos := 100.0;  (* Position kalibriert *)
            bIsReferenced := TRUE;
            eState := 3;  (* Normalbetrieb *)
            rRefTimer := 0.0;
            (* Starte mit mittlerer Position für sanften Übergang *)
            rI_Part := 50.0;
        ELSIF rRefTimer > rRefTimeout THEN
            eState := 4;  (* Timeout-Fehler *)
            bOutputLocked := TRUE;
        END_IF;
    
    (* --------------------------------------------------------------- *)
    3: (* NORMALBETRIEB - PID-Regelung *)
    (* --------------------------------------------------------------- *)
        IF NOT bEnable THEN
            qUp := FALSE;
            qDown := FALSE;
        ELSIF bManual THEN
            (* Handbetrieb mit Tracking *)
            rPID_Out := LIMIT(0.0, rManualOut, 100.0);
            rI_Part := rPID_Out;
            ManualControl();
        ELSE
            (* Automatikbetrieb *)
            PID_Control();
            ThreePointLogic();
            PositionEstimator();
        END_IF;
        
        (* Plausibilitätsprüfung *)
        IF (rEstimatedPos < rMinValidPos) OR (rEstimatedPos > rMaxValidPos) THEN
            eState := 4;  (* Fehler: Position außerhalb Grenzen *)
            bOutputLocked := TRUE;
        END_IF;
    
    (* --------------------------------------------------------------- *)
    4: (* FEHLER - Ausgänge gesperrt *)
    (* --------------------------------------------------------------- *)
        qUp := FALSE;
        qDown := FALSE;
        
        (* Reset nur durch Zwangsreferenzierung *)
        IF bForceRef THEN
            eState := 0;
            bIsReferenced := FALSE;
            bOutputLocked := FALSE;
            rRefTimer := 0.0;
        END_IF;
        
END_CASE;

(* 4. AUSGANGS-SICHERHEITSÜBERWACHUNG *)
IF bOutputLocked THEN
    qUp := FALSE;
    qDown := FALSE;
END_IF;

(* Verhindere gleichzeitiges Schalten *)
IF qUp AND qDown THEN
    qUp := FALSE;
    qDown := FALSE;
    eState := 4;
    bOutputLocked := TRUE;
END_IF;

(* ========================================================================= *)
(* INTERNE METHODEN *)
(* ========================================================================= *)

(* ----------------------------------------------------------------- *)
(* PID-REGLER *)
(* ----------------------------------------------------------------- *)
PID_Control:
    rError := rSetPoint - rActualValue;
    
    (* I-Anteil mit Anti-Windup *)
    IF (rI_Part <= 100.0 OR rError < 0.0) AND (rI_Part >= 0.0 OR rError > 0.0) THEN
        rI_Part := rI_Part + (rKp / rTn * rError * rCycleSec);
    END_IF;
    rI_Part := LIMIT(0.0, rI_Part, 100.0);
    
    (* D-Anteil (optional) *)
    IF rTd > 0.0 THEN
        rD_Part := rKp * rTd * (rError - rLastError) / rCycleSec;
        rD_Part := LIMIT(-20.0, rD_Part, 20.0);  (* Begrenzung *)
    ELSE
        rD_Part := 0.0;
    END_IF;
    rLastError := rError;
    
    (* PID-Ausgangssignal *)
    rPID_Out := (rKp * rError) + rI_Part + rD_Part;
    rPID_Out := LIMIT(0.0, rPID_Out, 100.0);

(* ----------------------------------------------------------------- *)
(* DREI-PUNKT-LOGIK MIT DYNAMISCHER REFERENZIERUNG *)
(* ----------------------------------------------------------------- *)
ThreePointLogic:
    (* Oberer Anschlag mit Referenzierung *)
    IF rPID_Out >= 99.5 THEN
        qDown := FALSE;
        IF rEstimatedPos < (100.0 + (rOverRun / rTotalRuntime * 100.0)) THEN
            qUp := TRUE;
        ELSE
            qUp := FALSE;
            rEstimatedPos := 100.0;
            bIsReferenced := TRUE;
        END_IF;
    
    (* Unterer Anschlag mit Referenzierung *)
    ELSIF rPID_Out <= 0.5 THEN
        qUp := FALSE;
        IF rEstimatedPos > (0.0 - (rOverRun / rTotalRuntime * 100.0)) THEN
            qDown := TRUE;
        ELSE
            qDown := FALSE;
            rEstimatedPos := 0.0;
            bIsReferenced := TRUE;
        END_IF;
    
    (* Normalbetrieb mit Hysterese *)
    ELSE
        qUp := (rPID_Out > (rEstimatedPos + rHysteresis));
        qDown := (rPID_Out < (rEstimatedPos - rHysteresis));
    END_IF;

(* ----------------------------------------------------------------- *)
(* POSITIONSSCHÄTZER *)
(* ----------------------------------------------------------------- *)
PositionEstimator:
    IF qUp AND NOT qDown THEN
        rEstimatedPos := rEstimatedPos + (rCycleSec / rTotalRuntime * 100.0);
    ELSIF qDown AND NOT qUp THEN
        rEstimatedPos := rEstimatedPos - (rCycleSec / rTotalRuntime * 100.0);
    END_IF;
    
    (* Sanfte Begrenzung im Normalbetrieb *)
    rEstimatedPos := LIMIT(0.0, rEstimatedPos, 100.0);

(* ----------------------------------------------------------------- *)
(* HANDBETRIEB *)
(* ----------------------------------------------------------------- *)
ManualControl:
    qUp := (rPID_Out > (rEstimatedPos + rHysteresis));
    qDown := (rPID_Out < (rEstimatedPos - rHysteresis));
    PositionEstimator();

END_FUNCTION_BLOCK
 
Ich glaube da liegst du richtig! Hab es auf deine "Empfehlung" mal mit Grok gemacht. Gemini hat eine Variante wo vorher auf Referenz getestet wurde... und den Code mal mit Claude.ai überarbeitet :D. Aktuell fehlt mir leider die Zeit zum testen es wird Etwas OT hier im Logo Bereich ;).
Es ist wieder ein schönes Beispiel dafür dass die KI einem viel Arbeit abnehmen kann weil sie halt ein sauberes und auch verständliches Grundgerüst erstellt. Allerdings brauchst du trotzdem Wissen um zu verstehen was die KI macht. Also noch lange kein Tool für Einsteiger sondern eher ein Hilfsmittel für Experten.
 
So, zurück zum Thema.

Ich habe meine Gründe es mit einer Logo zu machen. Und ich habe es ohne den PI-Regler der Logo gemacht, weil der ja eine kontinuierliches Signal rausgibt, was ich für den 3-Punkt Regler nicht brauchen kann. Vor allem nicht bei einer Totzeit von grob 30 Sekunden...
Moin,
ich hatte ein ähnliches Problem. Hast Du mal einen Analogfilter probiert? Damit lassen sich solche Schwankungen sehr gut glätten... nur eine Idee zu dem Thema

Ja, den Analogfilter hatte ich auch schon getestet, der hat das Problem aber auch nicht lösen können. Den Grund sehe ich darin, dass die Zykluszeit im Vergleich zum umschalten des Eingangs udn des A/D-Wandlers halt doch noch zu klein ist und die max 256 Zyklen zu wenig waren. Aber das hatte ich auch nur in einem schnellen Test mal angeschaut.

Ich werde mir ggf den PI-Regler nochmal genauer anschauen, aber das ist ja wie shcon gesagt ein anderes Thema.

Grüße
Patrick
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Entweder habe ich es überlesen oder es wurde noch nicht geklärt:
Was misst der PT1000 (Raumtemp. oder Vorlauftemp. der Heizung ) und wie hast Du den PT1000 in die LOGO verschaltet ?
Kurzbeschreibung der Software: Es ist eine Temperaturregelung über einen 3-Punkt-Schrittmotor. Analogwert einlesen und dann auffahren (heißer machen, Q1) oder zufahren (Q2), Q3 ist die Pumpe im Mischerkreis.
Die Mischer- Motorventile, die ich kenne, fahren nicht nur AUF/ ZU.
Die fahren alle möglichen Stellungen zwischen AUF bzw. ZU an - je nachdem, wie groß die Differenztemp. zwischen Vor- und Rücklauf ist.
Diese Mischer- Ventile (die ich kenne ! ) sind eigentlich ein Bypass
--> Differenztemp. Vor- und Rücklauf ist klein --> Mischer= AUF --> der Heizungswärmetauscher wird quasi stumm geschalten
--> Differenztemp. Vor- und Rücklauf ist groß --> Mischer= ZU --> die Heizung wird angefordert

Dreipunktregler
 
Die Mischer- Motorventile, die ich kenne, fahren nicht nur AUF/ ZU.
Die fahren alle möglichen Stellungen zwischen AUF bzw. ZU an - je nachdem, wie groß die Differenztemp. zwischen Vor- und Rücklauf ist.
Diese Mischer- Ventile (die ich kenne ! ) sind eigentlich ein Bypass
--> Differenztemp. Vor- und Rücklauf ist klein --> Mischer= AUF --> der Heizungswärmetauscher wird quasi stumm geschalten
--> Differenztemp. Vor- und Rücklauf ist groß --> Mischer= ZU --> die Heizung wird angefordert
Was das Motorventil in Stellung 100% und in Stellung 0% macht, ist nicht einheitlich.
Da gibt's Beides. Sowohl Kessel -> Heizkreis Vorlauf Auf als auch Kessel -> Heizkreis Vorlauf Zu.
Die Heizungsbauer sind da manchmal sehr kreativ. 🤪
 
Zurück
Oben