- LiTime Speicher und Akkus         
Ergebnis 1 bis 9 von 9

Thema: Heizungsregelung mit PID

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    25.05.2008
    Ort
    Korntal-Münchingen
    Alter
    42
    Beiträge
    15

    Heizungsregelung mit PID

    Anzeige

    Praxistest und DIY Projekte
    Hallo zusammen,

    bei meinem Projekt (Auswertung einer Breitbandlambdasonde) brauche ich eine Heizungsregelung und irgendwie komme ich nicht weiter.

    Also, ich habe den Sensor mit einer integrierten Heizung. Diese Sonde hängt an einem Auswertechip. Über diesen Chip wird die Temperatur der Heizung indirekt gemessen... Der Chip hat einen Kalibrierungsmodus, in dem er sagt was die "Zielspannung" (Ur reference) ist, also die Referenz. Diese Zielspannung liegt bei 1 Volt. Nach der Kalibierung wird der Chip ist den normalen Modus geschaltet und in der Applikation die aktuelle Spannung (und damit auch die Temperatur des Sensors bzw. dessen Heizung) gemessen. Dabei ist es so, dass die niedrigere Spannung einen heißeren Sensor bedeutet und somit die Heizung gedrosselt werden soll, bis man die Referenz erreicht, also den 1V. Die Heizung wird über PWM geregelt.

    Mein PID-Code sieht so aus:

    Code:
    uint16_t calc_pid (uint16_t referenceValue, uint16_t measuredValue)
    {
        // calculation error:
        int16_t error = (int16_t) referenceValue - (int16_t) measuredValue;
        int16_t position = (int16_t) measuredValue;
        
        // calculate p-term;
        float pTerm = pidController.pGain * error;
        
        //Calculate the integral state
        pidController.iState += error;
        
        // check limits of iState
        if (pidController.iState > pidController.iMax) pidController.iState = pidController.iMax;
        if (pidController.iState < pidController.iMin) pidController.iState = pidController.iMin;
        
        //Calculate the integral term.
        float iTerm = pidController.iGain * pidController.iState;
        
        //Calculate the derivative term.
        float dTerm = pidController.dGain * (pidController.dState - position);
        pidController.dState = position;
        
        //Calculate regulation (PI).
        int16_t RegulationOutput = pTerm + iTerm + dTerm;
        
        // check limits of pwm here....
        
        if (RegulationOutput > pidController.pwmMax) RegulationOutput = pidController.pwmMax;
        if (RegulationOutput < pidController.pwmMin) RegulationOutput = pidController.pwmMin;
            
        return  (uint16_t) RegulationOutput;
    }
    Die Parameter für den PID-Controller sehen so aus:

    Code:
        // init PID controller...
        pidController.pGain = 120;
        pidController.iGain = 0.8;
        pidController.dGain = 10;
        
        pidController.iMin = -250;
        pidController.iMax = 250;
        pidController.pwmMin = 0;
        pidController.pwmMax = 240;
    Dadurch, dass "niedrigere Spannung heißeren Sensor" bedeutet, rufe ich referenceValue und measuredValue andersrum auf, also referenceValue ist die aktuell gemessene Spannung und measuredValue ist die Referenz aus dem Kalibrierungsmodus. Beide Werrte sind Werte vom ADC, ohne Wandlung in Volt.

    Mein Problem: die Funktion liefert immer 240 zurück, also Vollgas für die Heizung und die gemessene Spannung hängt immer bei 0,42V...

    Hat jemand eine Idee? Ich blicke es nicht...

    Danke Euch!

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    07.04.2015
    Beiträge
    865
    1. PID-Reglern einfach den kompletten Regelparametersatz vor die Füße zu schmeißen und auf ein gutes Ergebnis zu hoffen, funzt in der Regel nicht. Setz mal iGain und dGain zuerst auf 0 und erhöhe pGain langsam, bis Ist möglichst nahe am Soll landet und nicht überschwingt.
    2. Der Tausch von Ist und Soll bei der Übergabe tauscht zwar das Vorzeichen von "error", für "position" wird dann allerdings der Sollwert weiter verwendet. Zumindest der dTerm wird damit zum Quatsch.
    3. Auch ohne Verständnis der ganzen Mathematik eines PID sollte man zumindest mal grob abschätzen, was der Code treibt.
    Mit
    pGain=120,
    referenceValue=x
    measuredValue = x+/-2
    hängt Deine PWM bereits bei einem error=+/-2 voll am jeweiligen Anschlag pwmMin/pwmMax.

    Also: Zuerst einmal den Debugger/Simulator mit Testwerten bemühen und daran testen, ob die Funktion auch das zurückgibt, was Du erwartest/ selber errechnet hast. Ansonsten siehst Du den Wald vor lauter Bäumen nicht.


    Nachtrag: Diese Richtungsdreherei passt man üblicherweise durch Wechsel der Vorzeichen in den Regelparametern an.
    In der Realität ist, wenn Ist<Soll, der Fehler negativ (z.B. ich liege um -10° am Soll vorbei). Wenn die Stellgröße jetzt aufgedreht werden müsste, ginge das nur über negative Regelparameter (z.B. iGain=-0.8 ).
    Es ist jetzt nicht so, dass es den Quellcode stört, wenn sämtliche Berechnungen und Parameterangaben, wie oben angewendet, im Vorzeichen getauscht werden. Zur Klarheit der Sache trägt diese Optimierung allerdings nicht bei.
    Geändert von Holomino (08.09.2022 um 13:03 Uhr)

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    25.05.2008
    Ort
    Korntal-Münchingen
    Alter
    42
    Beiträge
    15
    Danke Dir für die Antwort erstmal.

    Zitat Zitat von Holomino Beitrag anzeigen
    1. PID-Reglern einfach den kompletten Regelparametersatz vor die Füße zu schmeißen und auf ein gutes Ergebnis zu hoffen, funzt in der Regel nicht. Setz mal iGain und dGain zuerst auf 0 und erhöhe pGain langsam, bis Ist möglichst nahe am Soll landet und nicht überschwingt.
    2. Der Tausch von Ist und Soll bei der Übergabe tauscht zwar das Vorzeichen von "error", für "position" wird dann allerdings der Sollwert weiter verwendet. Zumindest der dTerm wird damit zum Quatsch.
    3. Auch ohne Verständnis der ganzen Mathematik eines PID sollte man zumindest mal grob abschätzen, was der Code treibt.
    Den Code habe ich so aus einem anderen Lambdaprojekt übernommen und bin davon ausgegangen, dass es so tut... eine sehr kühne Annahme, wie man jetzt merkt.

    Ich werde das fettmarkierte heute Abend mal umsetzen und schauen, was er da treibt. Es ist das erste Projekt mit einem PID-Regler...

    Zitat Zitat von Holomino Beitrag anzeigen
    Mit
    pGain=120,
    referenceValue=x
    measuredValue = x+/-2
    hängt Deine PWM bereits bei einem error=+/-2 voll am jeweiligen Anschlag pwmMin/pwmMax.

    Also: Zuerst einmal den Debugger/Simulator mit Testwerten bemühen und daran testen, ob die Funktion auch das zurückgibt, was Du erwartest/ selber errechnet hast. Ansonsten siehst Du den Wald vor lauter Bäumen nicht.
    Ja, das habe ich gemacht. Ich habe die Berechnung so in ein VS-Projekt übernommen und sie mit Zahlen (also den IST-Werten) gefüttert, das Ergebnis war genau wie bei Dir (mit +-2), dass er direkt an den Anschlag geht.

    Zitat Zitat von Holomino Beitrag anzeigen
    Nachtrag: Diese Richtungsdreherei passt man üblicherweise durch Wechsel der Vorzeichen in den Regelparametern an.
    In der Realität ist, wenn Ist<Soll, der Fehler negativ (z.B. ich liege um -10° am Soll vorbei). Wenn die Stellgröße jetzt aufgedreht werden müsste, ginge das nur über negative Regelparameter (z.B. iGain=-0.8 ).
    Es ist jetzt nicht so, dass es den Quellcode stört, wenn sämtliche Berechnungen und Parameterangaben, wie oben angewendet, im Vorzeichen getauscht werden. Zur Klarheit der Sache trägt diese Optimierung allerdings nicht bei.
    Ich könnte dann doch im Code die Stellen, wo pidController.pGain, pidController.iGain und pidController.dGain verwendet werden, einfach mit einem Vorzeichen versehen, also beim Berechnen und nicht die Faktoren an sich. Oder alternativ einen Parameter verwenden, der Aussagt, dass invertiert gerechnet werden soll, dann sieht man direkt.

    Werde ich auf jeden Fall heute Abend mal ausprobieren, danke nochmal.
    Geändert von Hemi (08.09.2022 um 16:03 Uhr)

  4. #4
    Erfahrener Benutzer Roboter Genie Avatar von White_Fox
    Registriert seit
    04.10.2011
    Beiträge
    1.473
    Es gibt auch ein Verfahren, um die Regelparameter aus der Sprungantwort zu berechnen.

    Du läßt die Heizung einfach z.B. 5% heizen, logst dabei den Temperaturverlauf, und kannst dann aus einer Tabelle daraus die Regelparameter bestimmen.

  5. #5
    Neuer Benutzer Öfters hier
    Registriert seit
    25.05.2008
    Ort
    Korntal-Münchingen
    Alter
    42
    Beiträge
    15
    Mahlzeit zusammen,

    ich habe etwas die Berechnung angepasst, sieht jetzt aus:

    Code:
    uint16_t calc_pid (uint16_t referenceValue, uint16_t measuredValue, bool inverted)
    {
        float pTerm = 0, iTerm = 0, dTerm = 0;
        // calculation error:
        int16_t error = (int16_t) referenceValue - (int16_t) measuredValue;
        int16_t position = (int16_t) measuredValue;
        
        // calculate p-term;
        if (inverted)
        {
            pTerm = -pidController.pGain * error;
        } else {
            pTerm = pidController.pGain * error;
        }
        
        
        //Calculate the integral state
        pidController.iState += error;
        
        // check limits of iState
        if (pidController.iState > pidController.iMax) pidController.iState = pidController.iMax;
        if (pidController.iState < pidController.iMin) pidController.iState = pidController.iMin;
        
        //Calculate the integral term.
        if (inverted)
        {
            iTerm = -pidController.iGain * pidController.iState;
        } else {
            iTerm = pidController.iGain * pidController.iState;
        }
        
        //Calculate the derivative term.
        if (inverted)
        {
            dTerm = -pidController.dGain * (pidController.dState - position);
        } else {
            dTerm = pidController.dGain * (pidController.dState - position);
        }
        pidController.dState = position;
        
        //Calculate regulation (PI).
        int16_t RegulationOutput = pTerm + iTerm + dTerm;
        
        // check limits of pwm here....
        
        if (RegulationOutput > pidController.pwmMax) 
        {
            RegulationOutput = pidController.pwmMax;
        }
        
        if (RegulationOutput < pidController.pwmMin)
        {
             RegulationOutput = pidController.pwmMin;
        }
            
        return  (uint16_t) RegulationOutput;
    }
    Damit rechnet er schon mal genau so wie ich es von ihm erwarte... hatte noch einen anderen kleinen Bug...
    Memo an mich: VS verhält sich bei manchen Sachen (Datentypkonvertierung) anders als Microchip Studio...


    Habe jetzt pidController.iGain und pidController.dGain auf 0 gesetzt und spiele nur mit dem pidController.pGain rum.

    So sieht es mit pidController.pGain = 3.1 aus. Die Heizung wird alle 100ms überprüft (referenz vs. aktuell) und nachgeregelt.
    (sorry muss das Bild extern hosten, die Forumsoftware macht es mini und da sieht man nichts):

    Bild hier  

    gelbe Linie: der Referenzwert. Der liegt bei kostant 208.
    grüne Linie: der aktuelle Wert. Der schwankt zwischen 226 und 237.
    rote Linie: PWM-Wert (Ausgabe des PID-Reglers, andere Auflöung) pendelt zwischen 68 und 86.

    Ich würde sagen, ich kann mit dem pidController.pGain noch ein Stückchen höher gehen oder?

    EDIT:
    So sieht die Linie mit pidController.pGain = 7.1 und pidController.iGain = 0.18 aus:

    Bild hier  

    gelbe Linie: der Referenzwert. Der liegt bei kostant 208.
    grüne Linie: der aktuelle Wert. Der schwankt zwischen 209 und 216.
    rote Linie: PWM-Wert (Ausgabe des PID-Reglers, andere Auflöung) pendelt zwischen 59 und 102.
    Geändert von Hemi (08.09.2022 um 22:08 Uhr)

  6. #6
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    07.04.2015
    Beiträge
    865
    Eigentlich schon nicht schlecht, kann aber sein, dass die Parameter im wahren Leben (wenn die Lambdasonde im heißen Abgasstrom hängt) noch einmal angepasst werden müssen (weniger p, mehr i).
    Etwas mehr i würde der Sache wahrscheinlich eh nicht schaden, idealerweise schwingt der Ist-Wert dann einmal kurz über den Sollwert, ohne in Dauerschwingung überzugehen. Dann würde Ist auch um den Soll herum geregelt, nicht nur darunter.

  7. #7
    Neuer Benutzer Öfters hier
    Registriert seit
    25.05.2008
    Ort
    Korntal-Münchingen
    Alter
    42
    Beiträge
    15
    Ich habe ein kleines Video gemacht, wo man den Regelverlauf sieht.
    PID Werte sind im Video: P = 5, I = 0.8 und D = 3.2 (ist ein spontaner Wert).



    Die PID-Regelung fängt bei 0:50 an zu arbeiten, da sieht man einen gelben Pick. Im unteren Fenster (Titel: Grafik) sieht man die Linien:
    -> PID (gelb) ist PWM-Wert
    -> Ur_raw (grün) ist aktueller Wert
    -> Ur_ref_raw (rot) ist die Referenz

    Man sieht, dass die grüne Linie überwiegend auf der roten liegt. Ich habe den Sensor kräftig angepustet und gesehen, dass die grüne Linie nur kurz und leicht über der roten lag. PWM ging direkt hoch.

  8. #8
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    07.04.2015
    Beiträge
    865
    Schick.
    Jetzt könnte man noch des Lerneffektes wegen versuchen, die Parameter nach Ziegler/Nichols mathematisch aus der Sprungantwort zu ermitteln und mit den Eigenen (Werte und Ergebnisse) vergleichen.
    Geändert von Holomino (12.09.2022 um 10:28 Uhr)

  9. #9
    Neuer Benutzer Öfters hier
    Registriert seit
    25.05.2008
    Ort
    Korntal-Münchingen
    Alter
    42
    Beiträge
    15
    Okay, das ist dann für Fortgeschrittene

Ähnliche Themen

  1. Mega 32 Heizungsregelung
    Von motch im Forum C - Programmierung (GCC u.a.)
    Antworten: 4
    Letzter Beitrag: 04.12.2005, 17:23

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

LiFePO4 Speicher Test