Forum: Mikrocontroller und Digitale Elektronik PID-Code funktioniert nicht


von Tho. S. (tho_se)


Lesenswert?

Hallo zusammen,

ich habe einen Code geschrieben, welcher meine Temperatur Regeln soll. 
Dabei habe ich ein Thermoelement mit einem MAX31850 mit meinenm Arduino 
Mega2560 verbunden. Dafür benutze ich die entsprechende Library und die 
Messung funktioniert soweit.

Diese Messwerte will ich jetzt mithilfe der PID-Library in ein 
Ausgangssignal umwandeln. Leider reagiert der Controller nicht auf 
Temperaturschwankungen.

Ich habe noch kein Tuning Für den Controller gemacht, da der Fehler 
irgendwie im Code steckt.

Da ich keine Ahnung von Programmierung habe und selber den Fehler nicht 
finde, hoffe ich, dass mir hier jemand helfen kann.

Der Code:

//////////////////////////////////////////////////
//////Temperaturmessung
#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2

// Setup a oneWire instance to communicate with any OneWire devices (not 
just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

// arrays to hold device address
DeviceAddress insideThermometer;


//////////////////////////////////////////////////////////////////////// 
//////////
// Regelung

#include <PID_v1.h>

#define PIN_OUTPUT 4

//Define Variables we'll be connecting to
double Setpoint, Input, Output;

//Specify the links and initial tuning parameters
double Kp=2, Ki=5, Kd=1;
PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);




void setup()
{
  // start serial port
  Serial.begin(9600);
  Serial.println("Dallas Temperature IC Control Library Demo");



  Input = sensors.getTempCByIndex(0);
  Setpoint = 50;

  //turn the PID on
  myPID.SetMode(AUTOMATIC);
  // Start up the library
  sensors.begin();


}



void loop()
{
  // call sensors.requestTemperatures() to issue a global temperature
  // request to all devices on the bus
  Serial.print("Requesting temperatures...");
  sensors.requestTemperatures(); // Send the command to get temperatures
  Serial.println("DONE");

  Serial.print("Temperature for the device 1 (index 0) is: ");
  Serial.println(sensors.getTempCByIndex(0));

  Input = sensors.getTempCByIndex(0);
  myPID.Compute();
  analogWrite(PIN_OUTPUT, Output);


delay(500); // Wartezeit bis nächster Zyklus [ms]



}

von Bastian W. (jackfrost)


Lesenswert?

Kannst du die PWM messen ? Was heißt er reagiert nicht auf Schwankungen 
?

Gruß JackFrost

von Tho. S. (tho_se)


Lesenswert?

Hallo JackFrost,
Danke für die schnelle Antwort. Mit "nicht reagieren" meinte ich, dass 
auch in dem Fall, dass die Sollwert Temperatur gemessen wurde, der 
Arduino ein volles Signal ausgegeben hat.

Ich muss mich aber jetzt korrigieren. Der Code funktioniet jetzt. Ich 
habe den I- und den D-Anteil auf Null gesetzt.

von Bastian W. (jackfrost)


Lesenswert?

Damit hast du nun nur noch einen P-Regler. Deine Werte waren falsch. 
Wenn er der PID bei erreichen des Sollwertes noch 100 % ausgibt ist der 
I-Anteil deutlich zu stark. Du musst den Wert für den I-Anteil deutlich 
vergrößern.

Der I-Anteil ist kein echter I-Anteil, sondern ein Faktor. Bei 5 und 500 
ms Samplezeit und einer Regelabweichung von 30 K hast du nach 1 s schon 
100 % Stellgrad vom I Anteil. Wenn er 1 K drüber ist braucht der 
I-Anteil schon 25 s um den Stellgrad auf 0 zu senken.

Kannst du die PWM messen ?

Gruß JackFrost

: Bearbeitet durch User
von fop (Gast)


Lesenswert?

Wenn I-Anteil 0 geht's besser ? Klingt nach "windup". Im Integrator 
haben sich, durch was auch immer, mörderhohe Werte angesammelt, die den 
Regler in die Begrenzung treiben.

von Tho. S. (tho_se)


Lesenswert?

Die PWM kann ich leider nicht messen. Aber es stimtm, dass ich mir mal 
die größen Ordnung der Glieder in Abhängigkeit der Zeitschritte angucken 
sollte. Ich war nur zu sehr darauf fixiert, dass der Code an sich 
fehlerhaft ist.

Ja ein Anti-Wind up Verfahren wäre evtl auch sinnvoll. So weit ich das 
beurteilen kann, müsste ich dann von der Arduino Library abstand nehmen 
und den PID-Controller selber schreiben/ bei Google suchen.

von npn (Gast)


Lesenswert?

Bastian W. schrieb:
> ist der I-Anteil deutlich zu stark. Du musst den Wert
> für den I-Anteil deutlich vergrößern.

Wie soll man das verstehen?
Wenn man mit dem Auto kurz vor der Wand ist, muß man also Gas geben? 
:-)))

Das meintest du sicherlich anders...

von VorDieWandFahrer (Gast)


Lesenswert?

... das hätte dann wenigstens "durchschlagenden" Erfolg!

SCNR

von pegel (Gast)


Lesenswert?

Leider bin ich nicht schlau genug für die ganze Thematik, deshalb habe 
ich mir Online Hilfe gesucht.

http://www.rentanadviser.com/en/pid-fuzzy-logic/pid-fuzzy-logic.aspx

von Bastian W. (jackfrost)


Lesenswert?

npn schrieb:
> Bastian W. schrieb:
>> ist der I-Anteil deutlich zu stark. Du musst den Wert
>> für den I-Anteil deutlich vergrößern.
>
> Wie soll man das verstehen?
> Wenn man mit dem Auto kurz vor der Wand ist, muß man also Gas geben?
> :-)))
>
> Das meintest du sicherlich anders...

Normal stellt man beim I-Anteil die Nachstellzeit Ti ein. Innerhalb 
dieser Zeit wird der Ausgang um die Regelabweichung erhöht.

Nehmen wir an die Regelabweichung sei 3 K und Ti 10 s. Dann steigt der 
Ausgang um 3 % alle 10 Sekunden bis das Anti-Windup greift. Ist Ti aber 
100 s ist der I- Anteil schwächer weil er dann 100 s für die 3 % 
braucht.

Bei dem Arduino PID ist es aber ein Ki. Hier ist Ki = Samplezeit/Ti. 
Damit muss der TO das Ki deutlich verkleinern. Bei seiner Samplezeit von 
500 ms ist der I-Anteil in nur zwei Durchläufen in der Begrenzung wenn 
die Starttemperatur 20 'C. Der P-Anteil ist unwirksam nur das D kann 
noch bisserl bremsen.

Ein Ki von 0,025 könnte man mal testen und dann je nach Verlauf ändern.

Gruß JackFrost

von npn (Gast)


Lesenswert?

Bastian W. schrieb:
> Normal stellt man beim I-Anteil die Nachstellzeit Ti ein.

Das ist mir schon alles klar. Nur deine Formulierung war, sagen wir mal, 
etwas widersprüchlich :-)
Deswegen auch die Smileys...

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.