30.04.2013
Überarbeitet 2.2018 Es sind noch einige Link Fehler drin
Ursache ATMEL wurde von Microchip aufgekauft
Hinweis:
ATMEL wurde von Microchip aufgekauft und die haben die ursprünglichen Links gelöscht und verändert
Also, selbst neu suchen
PID-Regler mit µController
Aufgabe:
Ein Objekt ohne thermische Schwingung auf genau eine Temperatur zu bringen. Abweichng < 1%
Relatetd Parameter:
Wärmekapazität von xx,x J/K, woraus bei x W eine Anstiegsgeschwindigkeit von 0,xx K/s der Temperatur unter vernachlässigung der Wärmeabgabe an die Umgebung resultiert.
Links Fehlerursache ATMEL wurde von Microchip aufgekauft und die haben die Links gelöscht und verändert
Interessantes aus dem Netz:
geht nicht mehr: http://www.atmel.com/ und dann nach" AVR221" suchen
Die
Dimensionierung nach Rezept ist eine praktische Methode ohne viel
Rechnerei und Hilfsmittel, eine Methode also für den Praktiker. Die
bekanntesten Einstellregeln sind von Ziegler/Nichols und von
Chien/Hrones/Reswick. Darüber hinaus gibt es noch eine Vielzahl anderer
Einstelltabellen, auf die hier aber verzichtet wird, das würde den
Rahmen dieses Artikels sprengen.
An der Vielzahl kann man schon
ersehen, dass es kein universell gültiges Rezept gibt und mit diesen
Tabellen nicht unbedingt das Optimum erreicht wird, eine
Nachoptimierung kann nötig sein.
Bei Ziegler/Nichols unterscheidet man noch zwischen der Schwingungsmethode und der Einstellung nach der Sprungantwort.
Einstellung nach der Schwingungsmethode:
Bei
der Schwingungsmethode nach Ziegler/Nichols werden die Reglerparameter
so verstellt, dass die Stabilitätsgrenze erreicht wird und der
Regelkreis zu schwingen beginnt, d.h. die Regelgröße periodische
Schwingungen ausführt. Aus der so gefundenen Einstellung können die
Reglerparameter ermittelt werden. Dieses Verfahren ist nur auf
Regelstrecken anwendbar, bei denen ein Schwingen keinen Schaden
anrichtet und die überhaupt instabil gemacht werden können. Die
Vorgehensweise ist folgende:
Einstellung des Reglers als reinen P-Regler: Ki = 0 und Kd = 0
Die
Reglerverstärkung Kp wird solange vergrößert, bis sich der geschlossene
Regelkreis an der Stabilitätsgrenze befindet und Dauerschwingungen
ausführt.
Der dabei eingestellte Wert Kp wird als Kpkritbezeichnet.
Die Periodendauer der sich einstellenden Dauerschwingung Tkritwird gemessen.
Anhand der folgenden Tabelle werden dann die Reglerparameter bestimmt.
Der
Vorteil dieses Verfahrens liegt darin, dass die Untersuchung während
des Betriebes und ohne Öffnen des Regelkreises durchgeführt werden
kann. Der Nachteil an dem Verfahren ist, dass es nur auf Strecken
angewendet werden kann, die auch zum Schwingen gebracht werden können.
Einstellung nach der Sprungantwort: Diese
Methode der Parameterbestimmung beruht auf der Aufnahme der
Sprungantwort der Regelstrecke. Es eignet sich auch für Strecken, die
nicht zum Schwingen gebracht werden können. Der Regelkreis muss
allerdings geöffnet werden. Vorgehensweise: Es wird die Sprungantwort
aufgenommen und durch Einzeichnen der Wendetangente die Verzugszeit Tu
und die Ausgleichszeit Tg ermittelt.
Mit den so festgestellten Werten werden die Parameter für den einzusetzenden Regler gemäß nachstehenden Tabellen ermittelt.
18.02.2018 Manuelle KP ermittlung:
Das habe ich in einer China PDF gefunden und funktioniert erstaunlich gut.
1.) gewünschte Regelstrecke real aufbauen. Bsp Heizelemt und Thermosensor mit den thermischen Massen.
2.) Die PID Software: die Zeitscheiben-Aufrufe im Timerinterrupt, etwas schneller
als die Trägheit des Systems, stellen.
z.B. für Thermosysteme >~1 Sekunde.
für Motoren muss da s schon sehr viel flotter ( < 1mS ) gegen0
3.) KI und KD=0; Damit nur der Proportionalanteil arbeitet. Also die reine Fehlerdifferenz ( Soll -Ist = Fehler )
( Dabei wird der Ausgabewert seltsamerweise nicht
größer als 255 ( Mit KI != 0 aber auch bis 32767 )Liegt an der Software
4.) . KP Schrittweise von auf 1, >1, 5~~10--20, erhörhen.
5.) mit einem Datenlogger, oder sonst wie!, den Regelausgang über
die Regelzeit (die ja ermittelt werden soll) beobachten/Anzeigen.
.... beobacheten wie sich das System einschwingt.
Noch empirischer: Dafür etwas handbarer:
KP Wert so ermittlen dass das Sysstem gerade zu Oszillieren (bsp..
Heizen/Kühl Phasen ) beginnt, also die Oszillation gerade beginnt
überzureagieren
Davon nehmen wir ~60.80%
Das ist schon KP !! z.b. Bsp: --> KP= 3.1
Dann diesen gefunden KP Wert eintragen.
Jetzt wird KI und KD ermittelt: 6.) Diese Zeit messen
7.) Daraus --> F = 1/( Perioden pro Sekunde ) = Herz
Bps. bei einem "trägen Thermo System" 4.5 Regelperioden pro 2,5Minuten = 0.03 Hz
Merke: Omega (dieses sitzende Hinternzeichen) = 2* PI * F
Ich habe es mal so gemacht , mit erstaunlich guten Ergebnissen ( KP haben wir schon.. )
KP=3.1 KI hat sich bei trägen System als sehr niedrig herausgestellt.
Ich habe KI=0.02 genommen. KD = 13.1 !! ( Das hatte ich nicht erwartet, bei einem trägen Heizsystem )
Ich bin immer noch ewas unsicher, weil KD bei trägen System keinen Sinn macht.
Das Ergebniss war jedoch gut brauchbar
Hier darf noch etwas getunt werden.
evtl. KI noch kleiner.. (
Merke K* (Intern *127 Integerwert).
Kx < 0.01 macht keinen Sinn, da 0.01 *127 = 1,27 --> und das rundet ab.
wobei u(t ) die Stellgröße, e(t) die Regeldifferenz, KR die Reglerverstärkung, TN die Nachstellzeit und TV die Vorhaltzeit ist. (siehe 1 seite vom pdf über mir)
So, das wollen wir in einer zeitdiskreten Form haben. Da nen Rechner nur diskrete Werte rechnen kann... Also wird aus:
Integral(e(t) * dt) => Summe(e(k) ) * delta t // Fläche unter einer Kurve und e'(t) => (e(k) - e(k-1) ) / delta t // Steilheit einer Kurve...
wenn man das in die ürsprüngliche Gleichung setzt und bisschen hin und her rechnet (die unendliche Summe z.B. muss man eleminieren) kommt man auf:
Diese obige Formel haut man in eine Programmierzeile. Danach speichert man noch u(k-1), e(k-1), e(k-2) für die nächste Rechnung...
Achja: Kr = Kp ; Tn = Kr/Ki ; Tv = Kd/Kr
Tn = -26 und Tv = 0.16 sind gute richtwerte...
Viel Spaß damit...wer nachlesen will kann sich das obige pdf durchlesen :)
ZWEITER TEIL:
Das Problem bei der Differenzengleichung für den zeitdiskreten PID-Regler ist ja die Summe. Man müsste also die Summe immer wieder neu berechnen bzw. wird auch mit der Zeit ziemlich groß. Um diese Problem zu umgehen macht man folgendes:
Man betrachtet die Gleichung für einen Zeitpunnkt früher, also y(k-1). Der D-Anteil wird also zu: (e(k-1) - e(k-2))/Ta Die Summe beim I-Anteil wird jetzt von i=0 bis k-1 gezählt. Der P-Anteil wird einfach zu y(k-1)...
Nun kommt der Trick: Man subtrahiert diese Gleichung von der Gl. für y(k). Also: y(k) - y(k-1) Was passiert bei der Summe? Folgendes: Die Summe bei y(k) sieht explizit so aus: e0 + e1+ e2 + ...+e(k) Die Summe bei y(k-1) hat ein Glied weniger: e0 + e1+ ...+e(k-1) subrahiert man beide bleibt von den zwei großen Summen nur noch das Glied e(k) übrig! Und ist damit für den Rechner geeignet...
Du mußt die folgenden drei Größen berechnen und diese mit geeigneten Verstärkungen als Korrekturgröße verwenden.
1) für P-Anteil: (Istwert-Sollwert)
2) für D-Anteil: ((Änderung des istwertes seit letzter Berechnung)/zeitdifferenz)
3) für I-Anteil: (Istwert-Sollwert)*Zeitdifferenz
Allerding sollte bei der gewünschten Genauigkeit mit PWM (Pulsbreiten-Modulation) deie Heizungsregelung steuern.
Die Wirkung der einzelnen Parameter ist wie folgt:
Der P-Anteil macht die Regelung schnell (mit nur dieser Verstärkung
solltest Du anfangen bis der Regelvorgang anfängt zu schwingen).
Der D-Anteil (Geschwindigkeitsrückführung) wird zur Dämpfung von Überschwingen verwendet. er macht die Regelung langsamer.
Der I-Anteil macht deine Regelung genau (eigentlich unendlich genau da die Heizleistung so lange verändert wird bis Soll=Ist)
Das Optimun hast Du falls der Istwert einer Sprunghafte Änderung des Sollwertes mit ca 10 % Überschwingen folgt.
das heisst also fuer meinen Programm-Algorithmus:
* messe ist-Wert * speichere Ist-Wert (fuer naechste Differenzbildung) * berechne P * berechne D * berechne I
Jetzt definierst Du 3 Verstärkungen also beispielsweise KP, KD, KI. Deine Ausgangsgröße also dein PWM Ausgang berechnest Du wie folgt: Ausgang = KP*P + KD*D + KI*I Wichtig ist noch daß du am Start mit dem Wert I=0 anfängst damit der Heizvorgang langsam anfängt. Nehmen wir an Du willst 100 Grad haben und hast die Verstärkungen KP=5 bits/Grad KD=1 bit/(grad/sec) KI=2 (bit*sec) /grad und nehmen wir weiter an Du hast 20 Grad als Istwert und 19 Grad beim letzten loop und dein loop dauer 0,1 sec so ergibt sich KP*P=(20-100)*5=-400 KD*D=(20-19)/0,1=+10 KI*I=(20-100)*0,1*2=-16+(Summe aller bisherigen KI*Is)
Ausgang=-(-400+10-16=-406)gilt nur beim ersten loop. Beim zweiten loop haben wir bei gleichen Temperaturen -400+10-16-16=-422 Hinweis: Das Minus vor der Klammer hatte ich vergessen Nach mehreren loops wird KP*P immer kleiner weil Soll und Istwert sich annähern. KD*D geht gegen Null weil sich die Temperatur nicht mehr
ändert und Integral(KI*I) wird praktisch gleich dem Ausgang.
/*! \brief Flags for status information
*/
struct GLOBAL_FLAGS {
//! True when PID control loop should run one time
uint8_t pidTimer:1;
uint8_t dummy:7;
} gFlags = {0, 0};
//! Parameters for regulator
struct PID_DATA pidData;
/*! \brief Sampling Time Interval
*
* Specify the desired PID sample time (255 cylces to overflow), the time interval value is calculated as follows:
* TIME_INTERVAL = ( desired interval [sec] interval
* With a 8-bit counter ) * ( frequency [Hz] ) / 256
*/
//! \xrefitem todo "Todo" "Todo list"
/*! \brief Read reference value.
*
* This function must return the reference value.
* May be constant or varying
*/
int16_t Get_Reference(void)
{
return gf_SOLL_Temperatur * FLOATTOINT_KOMMA_FAKTOR; // = 44.44 GRAD
}
/*! \brief Read system process value
*
* This function must return the measured data
*/
int16_t Get_Measurement(void)
{
return (int16_t)(gf_IST_Temperatur * FLOATTOINT_KOMMA_FAKTOR);
}
/*! \brief Set control input to system
*
* Set the output from the controller as input
* to system.
*/
void Set_Input(int16_t inputValue)
{
if( inputValue > 0 ) // KANN JA NUR HEIZEN
{
OCR1A = (inputValue / 32767.0) * 1023.0; //0..1*PWM
}
else
{
OCR1A=0; // KANN NICHT KÜHLEN
};
};
//hier die while(1)
while(1) //ENDLESS
{
// Run PID calculations once every PID timer timeout
if( gFlags.pidTimer )
{
gFlags.pidTimer = FALSE;
ret = (p_term + i_term + d_term) / SCALING_FACTOR;
if(ret > MAX_INT){
ret = MAX_INT;
}
else if(ret < -MAX_INT){
ret = -MAX_INT;
}
return((int16_t)ret);
}
/*! \brief Resets the integrator.
*
* Calling this function will reset the integrator in the PID regulator.
*/
void pid_Reset_Integrator(pidData_t *pid_st)
{
pid_st->sumError = 0;
}
/*This file has been prepared for Doxygen automatic documentation generation.*/
/*! \file *********************************************************************
*
* \brief Header file for pid.c.
*
* - File: pid.h
* - Compiler: IAR EWAAVR 4.11A
* - Supported devices: All AVR devices can be used.
* - AppNote: AVR221 - Discrete PID controller
*
*
\author
Atmel Corporation: http://www.atmel.com \n
*
Support email: avr@atmel.com
*
* $Name$
* $Revision: 456 $
* $RCSfile$
* $Date: 2006-02-16 12:46:13 +0100 (to, 16 feb 2006) $
*****************************************************************************/
#ifndef PID_H
#define PID_H
#include "stdint.h"
/// PID.h
// -ZUGEFÜGT C.E.----------------------------------------
/*
NAch Ziegler Nichosl Methode
T = Periodendauer gemessen. etwa drei Durchläufe für eine Automatisierung
A = Amplitude
/*! \brief PID Status
*
* Setpoints and data used by the PID control algorithm
*/
typedef struct PID_DATA{
//! Last process value, used to find derivative of process value.
int16_t lastProcessValue;
//! Summation of errors, used for integrate calculations
int32_t sumError;
//! The Proportional tuning constant, multiplied with SCALING_FACTOR
int16_t P_Factor;
//! The Integral tuning constant, multiplied with SCALING_FACTOR
int16_t I_Factor;
//! The Derivative tuning constant, multiplied with SCALING_FACTOR
int16_t D_Factor;
//! Maximum allowed error, avoid overflow
int16_t maxError;
//! Maximum allowed sumerror, avoid overflow
int32_t maxSumError;
} pidData_t;
/*! \brief Maximum values
*
* Needed to avoid sign/overflow problems
*/
// Maximum value of variables
#define MAX_INT INT16_MAX
#define MAX_LONG INT32_MAX
#define MAX_I_TERM (MAX_LONG / 2)