Artisan – und ein paar Tweaks
Wir verwenden zum Rösten die Software Artisan. Artisan ist Open Source und läuft auf allen Plattformen. Wir haben es von Anfang an (seit 2015) im Einsatz. Artisan ist wahnsinnig flexibel, kann mit fast allen bekannten Röstmaschinen verwendet werden und ist aufgrund vieler standardisierter Schnittstellen auch für Eigenbauprojekte sehr gut verwendbar. Letzteres ist für das Umfeld in der dunkelhell Kaffeerösterei unverzichtbar.
Dieser Artikel zeigt nicht, wie wir genau Artisan verwenden (der kommt später). Hier möchte ich auf einen Tweak eingehen, den ich am Quellcode von Artisan vorgenommen habe, da mir eine Funktion, die für die Art und Weise, wie ich Artisan verwende noch gefehlt hat (wobei ich nicht ausschließe, dass man das Ergebnis auch mit bereits vorhandenen Mitteln erreichen hätte können, für mich war das hier dann jedoch die naheliegendere Art der Umsetzung).
Wie ich Artisan bisher verwendet habe
Artisan hat die Funktion „Alarms“. Damit kann man ein Art Ablaufprogramm für einen Röstvorgang erstellen.
Die Alarms-Tabelle. Hier werden hauptsächlich in Abhängigkeit von der aktuellen Bohnentemperatur (BT) Schritte gesetzt. Achtung! Die Tabelle wird nicht zwangsweise von oben nach unten abgearbeitet. Die Zeilen können auch wie in diesem Beispiel nach Thematik geordnet werden. Jede Zeile steht für eine Bedingung, die eintreten muss, damit die zugehörige Action ausgelöst wird.
Die Zeilen 4-8 steuern den Airflow.
9-11 die Ablufttemperatur des Katalysators.
Das meiste danach ist die Steuerung des Gasbrenners.
Bevor ich so eine Alarms-Tabelle für ein bestimmtes Röstprofil (bzw. für eine bestimmte Bohne) erstelle, röste ich diesen Kaffee meistens ein paar mal mit manueller Kontrolle. Zumindest war das so, nachdem ich die neue Röstmaschine in Betrieb genommen habe.
Was in der ersten Phase auch eine gute Hilfe ist, dass man Artisan eine bereits aufgezeichnete Röstkurve („Background“) mit allen ihren (manuell ausgeführten) Events nachfahren lassen kann. Dabei kann man nötigenfalls auch wieder manuell eingreifen. Auf diese Weise kann man sich an die gewünschte Röstkurve heranarbeiten.
Man könnte es auch dabei belassen und danach weitere Röstungen immer auf Basis einer vorhergegangenen ausführen. Ich persönlich tu mir aber leichter, wenn ich ein Röstprofil in einer Alarms-Tabelle habe. Die kann man dann auch bei Bedarf editieren und anpassen.
Was für mich aber noch viel wichtiger ist, dass man alle möglichen weiteren Funktionen dazu konfigurieren kann. Hier wären das die Sprachausgabe, Hinweis, dass der Kaffee im Cooling Tray entleert werden sollte, Airflow, Katalysator, Gas ein/aus, Kühlung usw. Das soll zwar teilweise auch über Event-Aufzeichnung mit der Background-Kurve gehen, bzw. als Kombination Background-(Events-)Replay und Alarms, ich finde die Variante über die Alarms jedoch klarer.
Und hier kommt der Schwachpunkt dieser Vorgangsweise ins Spiel, bzw. der Grund für den Tweak
Die Alarms hier arbeiten stur nach aktueller Bohnentemperatur. Erst wenn der jeweilige Schwellwert erreicht wird, wird eine Action ausgeführt. Das funktioniert in diesem Setup schon wirklich sehr gut. Ein Eingreifen ist nicht mehr oft nötig und die Röstungen können vom Start („Charge“) bis zum Ende („Drop“) weitgehend durch die Alarms automatisiert durchlaufen.
Es kann aber trotzdem zu Abweichungen kommen: Raum- Luft- und Bohnentemperatur, Luftfeuchtigkeit, Schwankungen bei den Eigenschaften einer Bohnensorte, Schmutzablagerungen in den Abluftrohren, Drift bei der Brennerleistung, …
Und das führt dazu, dass die Bohnentemperatur nicht immer gleich auf die vorhandenen Brennereinstellungen reagiert und somit die Röstkurven Abweichungen zwischen den Batches aufweisen können.
Warum nicht mit PID?
Artisan kann Röstungen mittels einem implementierten Software-PID steuern. Das ist Regeltechnik. Man gibt (wieder) eine Background-Kurve vor, die Artisan mittels PID nachfahren soll.
Jedoch muss man einen PID-Regler sehr achtsam per Parameter konfigurieren. Wenn man da daneben liegt, kommt es zu Übersteuerungen. Die Röstkurve schwingt um den Sollwert, anstatt sanft der Vorgabe zu folgen.
Stark vereinfacht gesagt, reagiert ein PID immer nur auf die aktuelle Abweichung vom Sollwert. Während einer Röstung gibt es verschiedene Phasen, in denen die Bohnen nicht immer gleich auf Einwirkungen von außen reagieren. Man müsste den PID für jede dieser Phasen umkonfigurieren. Andererseits gibt es während der Röstung zu erwartende Störungen bei bestimmten Temperaturen. Ein PID kann auch auf diese nur reagieren und sie nicht vorhersehen.
Eine Kaffeeröstmaschine ist ein sehr träges System. Änderungen an der Brennerleistung wirken sich oft erst 30 bis 60 Sekunden später merklich auf den Anstieg der Bohnentemperatur aus. Nötige Anpassungen sind oft deutlich _vor_ dem erwarteten Ereignis nötig. Das ist nicht unbedingt das, was ein PID am besten kann.
Ich habe in meinen Anfängen (2015) ein wenig mit PID experimentiert und mir damals zwar nicht die Finger, aber dafür viele Bohnen verbrannt. Letztendlich war die Alarms-Vorgangsweise für mich dann die praktikablere und sicherere Variante teilautomatisiert zu rösten.
Und jetzt trotzem – der Tweak mit dem PID
Ganz zufrieden war ich mit meiner Alarms-Methode aufgrund der Abweichungen dann aber noch nicht. Und hier hatte ich die Idee, ob man nicht bei den Alarms mit der stufenweise vorgegebenen Reduktion der Brennerleistung bei bestimmten Bohnentemperaturen bleiben kann aber zusätzlich einen PID aufschaltet, der auf kleine Abweichungen von der Sollkurve mit kleinen Eingriffen in die Brennerleistung reagiert und somit nur die Feinabstimmung übernimmt.
Und genau diese Möglichkeit habe ich in der aktuellen Artisan-Version nicht gefunden. Bisher war es so, dass man den Brennerregler manuell oder per Alarms auf die nötigen Werte einstellt. Wenn man dann während der Röstung den PID aktiviert, hat dieser komplett übernommen. Ich hätte was gesucht, dass der PID zwar aktiv mitregelt, man ihm aber z.B. eine Minute vor dem First Crack sagen kann, geh jetzt um 20% mit dem Brenner runter und fahre trotzdem die Sollkurve weiter nach.
Bzw. wollte ich bei meiner Alarms-Vorgangsweise bleiben und den PID nur als Unterstützung dazu nehmen.
Der Tweak
Mit ein paar Zeilen Code habe ich Artisan eine Funktion beigebracht, die ich „Power Offset“ nenne. Das ist ein Wert, den man Artisan mitteilen kann. Dieser Wert wird dem Brenner-Regler dazu gerechnet. Der Brenner-Regler zeigt dann die Summe aus dem PowerOffset und vorherigen manuellen oder PID-bedingten Brennereinstellungen an und dieser summierte Wert wird auch an den Brenner weitergegeben.
Der Wert lässt sich durch die Artisan-Commands „setPwrOffset“ auf einen bestimmten Wert setzen, bzw. durch „modifyPwrOffset“ um einen Wert (+/-) verändern.
Artisan-Commands sind interne Befehle, die man sich etwa auf konfigurierbare Buttons in der Programmoberfläche legen kann. Artisan-Commands kann man nicht direkt aus den Alarms ausführen. Aber man kann in den Alarms Buttons aktivieren und über diesen Umweg somit auch Commands ausführen, etwa das Setzen des Offsets.
Wozu ist das nun gut
Man könnte eine Röstung wie bisher per PID und Backgroundkurve durchfahren lassen. An bestimmten Stellen (Bohnentemperatur) könnte man etwa sagen „modifyPwrOffset(-20)“ (etwa kurz vor dem First Crack). Der PID bekommt davon nichts mit und fährt stur die Backgroundkurve weiter. Allerdings wird die Brennerleistung gleich um 20% verringert und die Röstkurve wird wie von selbst etwas flacher, bevor der PID überhaupt merkt, dass er überschießt.
Oder – wie in meinem Anwendungsfall: Ich regle in meinen Alarms nicht mehr den Brenner direkt, sondern setze einen Power Offset (Zeilen 14 – 25). Der Brenner-Regler reagiert darauf genauso, wie wenn man den „Slider Burner“ direkt gesetzt hätte mit einem Unterschied. Wenn man dann den PID dazu schaltet, dann übernimmt nicht der PID komplett den Brenner, sondern zusätzlich. Somit brauche ich in meinen Alarms nur geringfügige Änderungen vornehmen und kann den PID zu meiner grundlegenden groben Steuerung einfach dazu oder auch wieder wegschalten. Die groben Regelschritte in den Alarms garantieren mir eine einigermaßen gelungene Röstkurve. Der PID kümmert sich nur um kleine Abweichungen.
Die Grafik zeigt die zweite Röstung mit dieser Methode (die erste zeige ich hier nicht, da waren die PID-Parameter noch so weit daneben, dass die Röstung ziemlich davongefahren ist und gerade noch zu retten war).
Hier ist die Röstkurve fast deckungsgleich mit der Background-Kurve. Allerdings stimmen die groben Alarms-Schritte für den Brenner schon so genau, dass der PID nur sehr wenig eingreifen musste.
Die PID-Eingriffe sind die beiden „Hügeln“ im unteren Bereich. Die Brennerregelung passiert permanent (bei aktivem PID), wird aber nur dann aufgezeichnet (die rote absteigende Treppe in der unteren Hälfte), wenn die Alarms Schritte setzen.
Der Vollständigkeit halber hier noch die Button-Konfiguration. Die Buttons sind frei konfigurierbar. Man sieht sie im Bild mit den Kurven am unteren Rand.
Bei den Buttons habe ich noch einiges dabei, was ich in Zukunft noch anpassen werde. Button 20 und 21 sind hier nur zum Testen von Power Offset (bzw. das Zurücksetzen auf 0 kann durchaus sinnvoll sein). 22 und 23 dienen zum manuellen Nachkorrigieren um +/-2% Brennerleistung.
Den Buttons kann man seit kurzem auch Werte übergeben (danke Marko!). Das sieht in diesem Beispiel beim Aufruf aus den Alarms dann etwa so aus:
Action: Event Button
Description: 20>40
Damit wird der Button Nr. 20 aktiviert und ihm gleichzeitig der Wert 40 übergeben.
Anmerkungen zum Schluß
Die „paar Zeilen Code“ um die ich das lokal aus den Sourcen installierte Artisan erweitert habe, waren in Wirklichkeit schon etwas mehr Aufwand. Artisan ist riesig. Und ebenso sein Quellcode. Mit ein wenig Ahnung von Python, aber sehr wenig Idee von Qt und parallelen Python-Threads und dazu die gewachsene Struktur von Artisan. Da macht man am Anfang ordentlich Blödsinn bis es stabil läuft.
Die hier besprochene Idee an sich ist wohl auch eher eine Anwendungs-Nische und mit den bisherigen Möglichkeiten von Artisan vermutlich mit ähnlichen Ergebnissen erzielbar. Weiters ist meine Implementierung vermutlich noch nicht ganz so, dass sie genauso übernommen werden könnte.
Auch sehe ich PID vielleicht etwas zu kritisch und könnte mit ausreichend Trial&Error und Auseinandersetzung mit der Literatur zur einem erfolgreichen Einsatz eines grundlegenden PID-Reglers kommen. Es gibt da draußen im Netz ganz viele, die auf PID schwören und damit am liebsten alles derschlagen würden. Meine bisherigen Erfahrungen mit dem Thema haben mir allerdings schon zu viele verbrannte Bohnen gekostet. Meine Experimentierfreudigkeit hat leider etwas darunter gelitten.
Ich werde auf alle Fälle meine Alarms anpassen und in der nächsten Zeit mit dieser Erweiterung rösten. Es bleibt auch spannend, ob der PID in dieser Kombination wirklich eine gute Unterstützung ist und ob ein einziges Parameter-Set dann für alle Kurvendesigns funktioniert.
Artisan wollte ich schon sehr lange einmal auch von innen kennenlernen. Dazu war dieses kleine Projekt jedenfalls ein guter Anlass.
Werden nur wenige brauchen können, aber hier gäbe es die Konfigurationsdatei meiner Artisan-Installation zum Downloaden: Artisan_dunkelhell_aset.zip





