PID FTW!


Silvia fühlt sich mittlererweile ganz wohl bei mir. Manchmal ist sie eine Zicke, aber die Qualität meines Cappuccinos scheint immer weniger mit der Anzahl der schwarzen Katzen im Stadtteil zu korrelieren. Wenn der Cappuccino nicht schmeckt, hab ich einen Fehler gemacht — so einfach ist das. Und auch Spinnen finden Silvia toll:

Das heisst aber nicht, dass es in Sachen Cappuccino nicht noch technische Weiterentwicklungen geben würde. Bis vor drei Wochen lief der PID-Controller, der die normale Temperaturregelung der Silvia ersetzt hat, nur als einfacher P-Controller, sprich: Da fehlte noch das komplette Feintuning. Der Hintergrund: Ich war mit dem Bare Bones Coffee Controller nicht wirklich zufrieden, der Code war nicht schön. Daher stand also eine Neuimplementation an. Gesagt, getan: Im ChaosCoffeeControl-Repository gibt es nun einen development-Branch, in dem der neue Code liegt. Einzig das Senden des DTR-Signals, um den µC neu zu starten und so über den Bootloader zu programmieren, ist noch etwas häßlich. Aber irgendwas ist ja immer.

Der PID-Algorithmus

Der PID-Algorithmus war dann auch recht schnell implementiert. Der Kern sieht so aus:

float curTemp=getTemperatureFloat();
float error = _pid_data.setpoint - curTemp;
_p_term = _pid_data.p_gain * error;
// iState keeps changing over time; it's overall 
// "performance" over time, or accumulated error
_iState += error;
// Use a static windup guard to keep the balance 
// of the istate.
if (_iState > WINDUP_GUARD) 
  _iState = WINDUP_GUARD;
else if (_iState < -WINDUP_GUARD) 
  _iState = -WINDUP_GUARD;
_i_term = _pid_data.i_gain * _iState;
// the dTerm, the difference between the temperature 
// now and our last reading, indicated the "speed," 
// how quickly the temp is changing. 
_d_term = (_pid_data.d_gain * (curTemp - _last_temp));
// now that we've use lastTemp, put the current temp 
// in our pocket until for the next round
_last_temp = curTemp;
// the magic feedback bit
_pid_value = _p_term + _i_term - _d_term;

Als ich dann von dem einfachen P-Regler auf den PID-Algorithmus umstellen wollte, funktionierte zunächst alles prima. Nach etwas Parameter-Raten war die Kombination P=60, I=0.48 und D=1800 recht brauchbar. Um die zu ermitteln habe ich den Regler zunächst als reinen P-Regler betrieben und P langsam erhöht. Bei P=100 schwingt das System, und zwar mit einer Periode von 250 Sekunden. Die Einstellregeln von Ziegler-Nichols ergeben dann die Parameter oben. Ich hab hierfür folgendes R-Skript benutzt:

K_P_krit<-100
T_krit<-250

print(paste("Estimation of PID controller ",
      "parameters for K_pkrit=",
      K_P_krit, " and T_krit=", T_krit));

K_P<-0.6*K_P_krit
T_N<-0.5*T_krit
T_V<-0.12*T_krit
K_I<-K_P/T_N
K_D<-K_P*T_V

print(paste("K_P: ", K_P));
print(paste("K_I: ", K_I));
print(paste("K_D: ", K_D));

Danach zeigt der Regler ein sehr stabiles Temperaturverhalten:

Klasse, denke ich mir, mahle Kaffee und will mir einen Cappuccino machen. Leider ist nach der Betätigung der Pumpe auf einmal der Mikrocontroller tot. WTF?

EMV — nicht witzig

Ich bin dann erst einmal für zwei Tage zurück zur Senseo-Kaffeemaschine. Es stellte sich heraus, dass die Pumpe massive Einstrahlungen in die Schaltung liefert. Da ein Atmel-Mikrocontroller Überspannungen an der Resetleitung als Aufforderung zur Hochvolt-Programmierung versteht, hat er sich quasi beim Anschalten der Pumpe selbst gelöscht.

Also die Platine mit diversen Dioden und Kondensatoren ausgestattet. Der Schaltplan sieht nun so aus (großes PDF):

Danach lief die Maschine zumindest meistens. Irgendwo kommen immer noch Störungen rein, aber der Mikrocontroller resettet sich nur und startet dann wieder. Das ist unbefriedigend, wenn man Geräte an den USB-Port anschließen will:

Das Loch habe ich mit einer Lochstanze in die Rückwand der Silvia gestanzt. Der USB-Port ist von Neutrik und setzt auf der Innenseite auf eine USB-A-Buchse um. Ein USB-Kabel verbindet dann die Neutrik-Buchse mit dem Mikrocontroller.

Meine erste Maßnahme war das Schirmen der Kabel, die direkt an die Platine führen. Das hat allerdings nicht ausgereicht. Als nächstes habe ich zwischen Platine und Magnetventil eine Schirmung aus Alufolie angebracht — ebenso ohne Erfolg. Letztlich hat dann ein Entstörfilter (LC-Glied) direkt an der Pumpe funktioniert:

Silvia sieht nun innen so aus:

Der EMV-Filter ist im Vordergrund zu erkennen. Ausserdem sind alle Kabel in einen schwarzen, temperaturbeständigen EMV-Schutzschlauch eingepackt. Der Lohn der Mühe: Die Kaffeemaschine läuft nun störungsfrei, der Schaltplan ist vollständig. Schließt man einen Rechner via USB an, kann man Temperatur etc. in einer Konsole einstellen:

C8H10N4O2 menu
Press 'x' to leave, '?' for help
 b: print PID configuration
 o: toggle PID debug output
 +/-: increase/decrease adjustment delta, 
      current delta: 1.00000
 p/P: increase/decrease p gain
 i/I: increase/decrease i gain
 d/D: increase/decrease d gain
 r: reset PID configuration to default values
 s: save PID configuration to EEPROM
Current PID controller configuration:
 - temperature setpoint: 102.00000
 - P gain: 60.00000, I gain: 0.48000, 
   D gain: 1800.00000

Und nun?

Mögliche Erweiterungen in der Zukunft:

  • Ein automatischer Bezugstaster
  • Ein Durchflussmesser
  • Twitter-Anschluss

Stay tuned.

Comments


Mathias Dalheimer

Yours truly.

likes distributed & embedded systems

GPG key: B6501625
fingerprint: E7BA B68E A2D3 9B6A ECEF 4DE4 823E 0DBE B650 1625
github | twitter | flickr