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


von Sven (Gast)


Lesenswert?

Hallo zusammen,

für meine Heizungsregelung habe ich bisher nur einen Zweipunktregler 
realisiert bekommen, sinngemäß:
1
if (ist_temp < soll_temp)
2
    heizen = 1;
3
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

von Thilo M. (Gast)


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.

von hans (Gast)


Lesenswert?

Für Reglerfragen:
http://www.roboternetz.de/wissen/index.php/Regelungstechnik

Für deinen Fall: Angaben fehlen!

gruß hans

von Peter Diener (Gast)


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

von Michael H. (Gast)


Lesenswert?

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

von Sven (Gast)


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.
1
float Ta = 0.03;                    // Abtastzeit in ms
2
float Tn = 100;                        // Nachstellzeit
3
float Tv = 1;                        //
4
float K = 3500;                        // Differenzieller Anteil
5
float e = 0;                        // Regelabweichung w-r
6
float esum = 0;                      // Summe der Regelabweichungen
7
float ealt = 0;                      // Regelabweichung zum Zeitpunkt z-1
8
long int stellgroesse = 0;              // Stellgröße

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

1
TCCR1B = 0b00000010;   // Timer prescaler 2MHz
2
TIMSK  = 0x94;    // enable Interrupts
3
sei();   
4
5
// end main     
6
7
ISR (TIMER1A)
8
{
9
 cnt++;
10
 PORTA= heizung_aus;   // Aus
11
}
12
13
14
ISR (TIMER1_OWF)
15
{
16
 cnt1++;
17
 //PID-controller
18
 e = temp - ist_temp;   // Bilde Regeldifferenz
19
 esum = esum + e;        // Aktualisieren Summe der Regel
20
 stellgroesse = K*(e + (Ta/Tn)*esum + (Tv/Ta)*(e - ealt));
21
 ealt = e;   //Regelabweichung für nächste Anbtastung merken
22
23
 // Stellgröße begrenzen, 16-Bit PWM
24
 if (stellgroesse < 10)
25
    stellgroesse = 0x000A;
26
 if (stellgroesse > 65525)
27
        stellgroesse = 0xFFF5;
28
29
 OCR1A = stellgroesse;  //setzt compare-register für PWM
30
 PORTA= heizung_an;   // An
31
}

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

Liebe Grüße,
Sven

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.