www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Re: Algorithmus fuer PID (Heizungsregelung)


Autor: Sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

für meine Heizungsregelung habe ich bisher nur einen Zweipunktregler 
realisiert bekommen, sinngemäß:
if (ist_temp < soll_temp)
    heizen = 1;
else heizen = 0;

Nun schwingt diese Regelung extrem über.
Kann mir vielleicht jemand mit einem Quellcode aushelfen,
wie ich vielleicht mit einer PWM oder etwas ähnlichem so etwas besser 
regeln könnte.

Vielleicht in leicht verständlich, da ich ziemlich Anfäner bin.

Vielen Dank im voraus!
Sven

Autor: Thilo M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie hast du die Regelung aufgebaut?
Welche Temperatur wird ausgeregelt, Vorlauftemperatur oder 
Zimmertemperatur?
Was steuerst du an (Stellglied)? Einen Mischer?

Normalerweise ist diese Art der Regelung extrem träge und ein 
dreipunkt-Schrittregler mit Mischer (210s Stellzeit) ist prima dafür 
geeignet. Der I-Anteil wäre dann die Stellzeit des Mischers.

Autor: hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Für Reglerfragen:
http://www.roboternetz.de/wissen/index.php/Regelungstechnik

Für deinen Fall: Angaben fehlen!

gruß hans

Autor: Peter Diener (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Sven,

dein Code

if (ist_temp < soll_temp)
    heizen = 1;
else heizen = 0;

ist kein Zweipunktregler, bzw, wenn es einer sein soll, dann hat er 
keine Hysterese.

Mit Hysterese schaut das so aus:

if (ist_temp < (soll_temp - hysterese)) heizen = 1;
else if (ist_temp > (soll_temp + hysterese)) heizen = 0;

Für Heizungssteurungen ist ein PI Regler üblich, das benötigt aber eine 
analoge Strecke, d.h. kein Ein-Aus-Verhalten der Heizung. Die 
Heizleistung sollte prozentual einstellbar sein.

PI-Regler:

float heizen, ist_temp, soll_temp, Errorintegral, Kp, Ki;
#define negIntegralsaturation 100
#define posIntegralsaturation 100

Errorintegral += (ist_temp - soll_temp);
if (Errorintegral > posIntegralsaturation) Errorintegral = 
posIntegralsaturation;
if (Errorintegral < negIntegralsaturation) Errorintegral = 
negIntegralsaturation;
heizen = Kp * (ist_temp - soll_temp);
heizen += Ki * Errorintegral;
if (heizen > 1) heizen = 1;
if (heizen < 0) heizen = 0;

Am Anfang vom Programm müssen alle Variablen auf 0 initialisiert werden. 
Die meisten C-Compiler machen das, sollte man aber trotzdem prüfen.
heizen ist jetzt ein Ausgangswert im Gleitkommaformat von 0.0 (nicht 
heizen) bis 1.0 (volle Heizleistung). Kp und Ki sind die Regelparameter, 
einstellbar z.B. nach einer heuristischen Methode.

Mit diedem Regler ist sowohl eine Schwingneigung sowie ein Überschwingen 
vermeidbar.

Wichtig ist, dass die Routine immer gleich oft in gleichen 
Zeitabschnitten ausgeführt wird -> Timer verwenden.

Viele Grüße,

Peter

Autor: Michael H. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Statt peters float würde ich uint16_t, wenn nicht schon uint8_t 
verwenden. Float macht nur den ganzen RAM dicht.

Autor: Sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich habe nun versucht mit Hilfe von ISR einen PID-Regler zu realisieren, 
leider funktioniert es gar nicht, aber ich weiß nicht woran es liegt. 
Die Isttemperatur hole ich über den ADC und den Sollwert über das 
Keypad.

Hier einmal ein Stück Quellcode. Das zunächst habe ich global definiert.
float Ta = 0.03;                    // Abtastzeit in ms
float Tn = 100;                        // Nachstellzeit
float Tv = 1;                        //
float K = 3500;                        // Differenzieller Anteil
float e = 0;                        // Regelabweichung w-r
float esum = 0;                      // Summe der Regelabweichungen
float ealt = 0;                      // Regelabweichung zum Zeitpunkt z-1
long int stellgroesse = 0;              // Stellgröße


Ich bin mir halt auch nicht sicher ob ich die Interrupt Routinen richtig 
initialisiert habe. Wahrscheinlich nicht ;-)

TCCR1B = 0b00000010;   // Timer prescaler 2MHz
TIMSK  = 0x94;    // enable Interrupts
sei();   

// end main     

ISR (TIMER1A)
{
 cnt++;
 PORTA= heizung_aus;   // Aus
}


ISR (TIMER1_OWF)
{
 cnt1++;
 //PID-controller
 e = temp - ist_temp;   // Bilde Regeldifferenz
 esum = esum + e;        // Aktualisieren Summe der Regel
 stellgroesse = K*(e + (Ta/Tn)*esum + (Tv/Ta)*(e - ealt));
 ealt = e;   //Regelabweichung für nächste Anbtastung merken

 // Stellgröße begrenzen, 16-Bit PWM
 if (stellgroesse < 10)
    stellgroesse = 0x000A;
 if (stellgroesse > 65525)
        stellgroesse = 0xFFF5;

 OCR1A = stellgroesse;  //setzt compare-register für PWM
 PORTA= heizung_an;   // An
}


Vielleicht kann ja jemand daraus etwas erkennen. Die floats sollte ich 
dann wohl auch noch ändern.

Liebe Grüße,
Sven

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.