Arduinoeinstieg mit dem Bioreaktor

//** Rev. 0.2 vom 31.05.2017 S. Schlote

Ziel

Aufbau und Testen einer Bioreaktorbasis. Die leichte Verfügrbarkeit und biologische Sicherheit prädestiniert Bäckerhefe als Versuchsorganismus. Die alkoholische Gärung im Batchverfahren liefert den zu überwachenden, biotechnischen Vorgang. Zu überwachen sind:

  • Temperatur,
  • Luftalkoholkonzentration,
  • CO2-Konzentration
  • Schaum.

Materialliste

  • Becherglas 1 Liter
  • Magnetrührer
  • Labornetzgerät
  • Teflonbeschichtetes Magnetrührstäbchen
  • Stativ, Kreuzmuffen, Zangen
  • Tüte
  • Arduino NANO V 3.0
  • Steckbrett
  • Flexible Steckbrücken
  • 4,7 k Widerstand
  • 2 x 47 M Widerstände
  • Alufolie (5 x 5 cm²)
  • Silber- oder Kupferdraht
  • 24 V 20 W Heizfolie z.B. diese von Reichelt
  • Mosfet-Treiberboard z.B. dieses von Pollin
  • Alkoholsensor (MQ-3) z.B. dieser bei Amazon
  • Wasserdichter DS18B20-Temperatursensor z.B. dieser von Adafruit
  • CO2-Sensor MH-z19 z.B. dieser bei eBay

Wegbeschreibung

Neueinsteiger überfliegen vielleicht zunächst mit einem der  einführenden Tutorials das Wissenswerte von der Arduino-Famile und ihrer IDE (IDE = Integrated Development Environment = integrierte Entwicklungsumgebung). Neben Beispielen bietet die IDE während der Entwicklung vor allem einen schnellen Zugriff auf die Referenz (Strg + Umsch + F) der Befehle nebst Erläuterungen und Hinweisen.

Durch Anpassung der Beispiel-Sketche aus der Entwicklungsumgebung sowie durch Nutzung von Quellen mit Beispielcode aus dem Internet erschließt sich zunächst die Nutzung der unterschiedlichen Sensoren. OpenSource in Soft- und Hard: „Schreibe und entwickle nie von Grund auf neu, was anerkannt funktionierend schon frei verfügbar ist.“

Vor dem Finale steht die angeleitete Eigenentwicklung eines Schaumsensors bevor alle Sensoren und Aktoren zu einem einfachen Bioreaktorsystem zusammengefasst, programmiert und im Test betrieben werden.

Arduinoeinführungen / Tutorials

Freier Arduino-Einstieg 3 x sehr gut, 3 x anders

Nicht immer muss es ein Arduino UNO sein. In der Technik-Garage verwenden wir meist den Arduino NANO, denn der lässt sich sowohl auf einem Steckbrett / Breadboard als auch in Schaltungen wie ein Bauteil einsetzen.

Bei Arbeiten mit diesem Baustein sollte ein Pinout stets in Reichweite liegen. Alle Angaben auf diesen Seiten beziehen sich auf das Pinout der NANO-Rev. 3.0.

Nicht immer steht darauf, wenn Arduino drin steckt. Sehr viele 3D-Drucker basieren auf dem Arduino Mega. Der Mega bietet mehr Speicher, mehr Pins und vor allem mehr Kommunikationskanäle (digitale Busse).

Arduino UNO / Nano / Mega … das sind:

  • kleine Computer bestehend aus Prozessor (Mikrocontroller z.B. ATmega328P), Spannungsversorgung (benötigt werden 6 – 20 V Gleichspannung) und USB-Schnittstellenbaustein zur Kommunikation mit z.B. einem PC.
  • Computer mit einem Betriebssystem das Bestandteil des verwendeten Mikroprozessors ist.
  • Computer mit einem kleinen Arbeits- und einem kleinen Programmspeicher.

Weiteres ist den obigen Tutorien zu entnehmen.

Massimo Banzi war mit dem Arduino Starter einer neuen Entwicklungssystemfamilie. Ein Entwicklungssystem besteht aus Soft- und Hardware.

Neue und modernere Versuche in der Welt der Entwicklungssysteme für Mikrocontroller sind zum Beispiel das ESP8266- und ESP32-System von Espressif, die über wesentlich höhere Taktraten/Arbeitsgeschwindigkeiten und Speicher verfügen. Es gibt keinen ausgereifteren Mikrokosmos als den des Arduino. Auch ein ESP8266 kann mit Hilfe der Arduino-IDE programiert werden.

Der RaspberryPi zielt in eine andere Richtung, denn er verfügt zwar über einen größeren Speicher und eine höhere Arbeitsgeschwindigkeit, aber er verwendet ein höchst komplexes Betriebssystem, das für viele Anwendungen zu komplex und vor allem zu wenig echtzeitfähig ist.

Von „Blink“ bis „Bioreaktor“

In den meisten Steuerungen und vielen Regelungsprogrammen sind regelmäßig wiederkehrende Aufgaben zu erledigen. Die Funktion delay() (verzögere) verspricht einen einfachen Weg zur Programmierung von Pausen / Intervallen in Arduino-Sketches.

Der „Blink“-Sketch in der klassischen Version findet sich im oben zitierten Tutorial des OV-Meschede. In einer neuen Version ist er als Demo in jede Arduino-Entwicklungsumgebung >1.80 unter „Datei“ -> Beispiele -> 01. Basics -> „Blink“ eingebunden. Hier wird eine vordefinierte Variable „LED_BUILTIN“ für die Pinbezeichnung verwendet. In beiden Versionen übernimmt die Funktion „delay()“ die Zeitverzögerung, wobei die Angabe der Zeitverzögerung in Millisekunden anzugeben ist.

„Blink“ ist ein Steuerprogramm. Es bewirkt unbedingte Aktionen (Ein- und Ausschalten einer LED in festgelegten Zeitabständen). Für eine Regelung erforderliche Rückmeldungen in Form von Sensordaten haben keinen Einfluss auf den Programmablauf, weil der Mikrocontroller die in delay() angegebene Zeit nur mit Warten verbringt.

Aufgabe: Bilden Sie zwei Beispiele als Begründung, warum diese Form der Steuerung für Systeme in Zusammenwirkung mit biologischen Prozessen weniger geeignet erscheint.

Das Programm verwendet die delay()-Funktion zu der es in der Referenz heißt: „the use of delay() in a sketch has significant drawbacks. No other reading of sensors, mathematical calculations, or pin manipulation can go on during the delay function, so in effect, it brings most other activity to a halt.“ Die Serielle Kommunikation und die PWM-Funktion sind glücklicherweise nicht betroffen. Die Nachteile bei Verwendung der delay()-Funktion sind für den Fall einer Verzögerung von mehr als 10ms jedoch so groß, dass von ihrer Verwendung abgeraten werden muss.

Auch die Verwendung von delayMicroseconds() anstelle von delay() ist nur gelegentlich möglich. Hier bleiben die Interruptfunktion zwar erhalten, aber bei Verzögerungen von weniger als 3 und mehr als 16363 Mikrosekunden (circa 16 Sekunden) arbeiten die delayMicroseconds nach Aussage der Referenz unzuverlässig.

Also: delay() und delayMicroseconds() sind sparsam und mit Umsicht zu verwenden. Das delay() zum Entprellen von Schaltern erledigt ein kleiner Keramikkondensator mindestens so gut,

Wege aus dem Dilemma

Mit jedem neuen Programmstart (und jedem erneuten Öffnen des seriellen Monitors beim UNO) startet im Hintergrund ebenfalls ein Timer. Er zählt die seit dem Millisekunden seit dem Start des Programms. Diese Zeit ist mit der Funktion „millis()“ abzufragen. „millis()“ gibt einen Zahlenwert vom Typ „unsigned long“ zurück. Nach 50 Tagen läuft diese Variable allerdings über. Das bedeutet, der größte mögliche Wert dieses Variablentyps wird überschritten. Praktisch beginnt die Zählung dann wieder bei „0“. Wird millis() für das Erzeugen von Intervallen verwendet, ist alle 50 Tage das vom Übergang betroffene Intervall von falscher Dauer.

Ein Beispiel aus der Arduino-IDE gibt einen Hinweis auf eine mögliche Implementation. Aufzurufen unter: „Datei“ -> Beispiele -> 02. Digital -> „BlinkWithoutDelay“  oder auf der Arduino-Webseite.

https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay

Um beliebige Zeitintervalle erfassen zu können, benötigt der Sketch zwei Variablen zum Speichern von Zeitpunkten. Zeitvariable sollten in Arduino Sketchen vom Variablentyp „unsigned long“ sein. Eine erste Zeitvariable wird zu Beginn im Deklarationsteil definiert und mit dem Startwert 0 initialisiert.

unsigned long previousMillis = 0;

Zu Beginn der Endlosschleife „loop()“ innerhalb derer alle Anweisungen untergebracht werden, die nacheinander stets wiederholt ausgeführt werden sollen. Zu Beginn eines jeden Durchlaufs der Schleife wird zunächst der aktuelle Zeitstempel des Timers mit Hilfe von „millis()“ in die dafür vorgesehene Variable „currentMillis“ übernommen.

unsigned long currentMillis = millis();

Zu diesem Zeitpunkt gibt es also zwei gespeicherte Zeitpunkte: „previousMillis“ und „currentMillis“. Die Bedingung der if-Verzweigung wird erst dann erfüllt, wenn der Unterschied der beiden Zeitpunkte größer oder gleich der in „interval“ angegebenen Größe ist. Erst dann wird die mit der geschweiften Klammer eingeletete Anweisung ausgeführt. Im konkreten Fall wird der Variablen previousMillis der Wert currentMillis zugewiesen. Gegebenenfalls werden weitere, innerhalb dieser geschweiften Klammerung befindlichen Anweisungen ausgeführt.

if (currentMillis previousMillis >= interval) {

previousMillis = currentMillis;

}

Alle Ausführungen von etwaigen Funktionen benötigen ihre Zeit. Im nächsten Durchgang der loop()-Schleife weist die millis()-Funktion der Variablen currentMillis den dann aktuellen Zeitstempel zu. Ist der Unterschied zwischen currentMillis und previousMills noch nicht hinreichend groß, durchläuft das Programm die loop()-Schleife und verzweigt nicht in die Anweisung des if-Zweiges. Dieser Vorgang wiederholt sich so lange bis der Unterschied zwischen den beiden Zeitvariabelen den in interval angegebenen Betrag überschreitet.

Dieses Vorgehen sorgt dafür, dass alle innerhalb der loop()-Schleife befindlichen Anweisungen unverzüglich und stets erneut ausgeführt werden. Eine Verzögerung dieser Anweisungen durch einen Wartebefehl gibt es nicht.

Schnapsnase liest analogen Alkoholsensor (MQ-3)

Im folgenden Beispiel liest ein Arduino über einen analogen Eingang Messdaten eines Alkoholsensors aus. Der Sensor ist nicht 100% spezifisch für Ethanol. Er ist nicht kalibrierbar. Seine Empfindlichkeit wird durch die Luftfeuchtigkeit wesentlich beeinflusst. Da eine beheizte Keramik die Grundlage des Sensors bildet, muss diese zunächst ihre Arbeitstemperatur erreichen bevor halbwegs stabile und verlässliche Relativwerte angezeigt werden. Der Sensor benötigt eine Aufheizzeit von etwa 3 Minuten. Das folgende Programm verwendet die im Arduino Uno bzw. NANO eingebaute LED um Überschreitungen eines fiktiven Grenzwertes anzuzeigen. Hierfür wertet das Programm einen digitalen Eingang kontinuierlich in einer if-Verzweigung aus. Auch eine Bewertung der analog gemessenen Messwerte könnte als Basis zur Anzeige einer Grenzwertüberschreitung herangezogen werden.

Zum Hintergrund und der Arbeitsweise dieser Art von Sensoren:
https://playground.arduino.cc/Main/MQGasSensors

Aufgaben:

  1. Verändern Sie den unter „MQ-3 Alcohol Sensor Circuit Built with an Arduino“ angeführten Sketch in einer Weise, dass es die delay()-Funktion vermeidet und speichern Sie das Programm.
  2. Recherchieren Sie die Reaktionsgleichung der alkoholischen Gärung. Neben einer bestimmten Menge Alkohol setzt die Reaktion auch Kohlendioxid frei, dessen Konzentration mit dem Ihnen bekannten CO2-Sensor gemessen werden kann. Ermitteln Sie insbesondere die Bedingungen unter denen diese Reaktion optimal mit Sacchromyces cerevisiae optimal verläuft.

Bestimmung der CO2-Konzentration mittels MH-Z19

Der Kohlendioxidsensor MH-Z19 vermag sein Ergebnis sowohl über seine serielle Schnittstelle als auch als pulsweitengesteuertes Signal zu übermitteln. Die serielle Kommunikation des MH-Z19 benötigt eine Spannung von 3.3 V, die serielle Kommunikation des Arduino hingegen verläuft bei 5 V. Die Kommunikation würde also Sensor und Arduino zerstören, wenn keine geeigneten Maßnahmen ergriffen werden. Die Ausgabe der Messwerte als pulsweitengesteuertes 3.3 V Signal und deren Empfang aus einem Digitalpin des Arduino hingegen ist gefahrlos möglich, erfordert jedoch den Einsatz von Interrupts.

Ihor Melnyk stellt seinen Entwurf eines CO2-Messgeräts auf Basis des Arduino Pro Micro und des SO2-Sensors MH-Z19 vor. Dafür entwarf er diesen Sketch, der er auf GitHub teilt. Sein Sketch nimmt Bezug auf ein Grafikdisplay und den Arduino-Micro. Sein Code diente als Basis für den hier vorgestellten Code:

Dieser Code verwendet wiederum die delay()-Funktion, die es durch ein geeignetes Konstrukt zu ersetzen gilt.

Unter der Voraussetzung einer regulären Gärung sollte die CO2-Freisetzung proportional zur Ethanolproduktion erfolgen, wobei sowohl Ethanol als auch Kohlendioxid bis zu einem gewissen Maß im wässrigen Medium löslich sind.

Die Akitvität der verwendeten Hefe (Backhefe) oder (falls die Zellen nicht vital sein sollten) der freigesetzten Enzyme des Gärungsstoffwechsels hängt sowohl vom verwendeten Substrat (Saccharose oder/und Stärke) als auch in hohem Maße von der Umgebungstemperatur ab. Vermehrung und Stoffwechsel der Hefe lassen sich gezielt durch Inkubationstemperatur und Druck regulieren. Das vorliegende Experiment belässt den anliegenden Druck bei regulärem Luftdruck. Die Temperatur hingegen ist eng zu regeln. Hierfür bieten die vorangegangene Aufgabe zur Kalibration und Rückführung des DS18B20 Thermosensors sowie die PID-Regelung die wesentliche Grundlage. Abweichend vom Aufbau des PID-Regelkreises ist jedoch nicht ein Darlington-Transistor TIP120 und ein 100 Ohm-Widerstand sondern ein Mosfet-Treiber-Board und eine 24V Heizfolie einzusetzen. Die für diesen Aufbau erforderliche 24V-Spannungsversorgung ist durch regelbare Labornetzgeräte zu gewährleisten. Die Leistung der Heizfolien ist auf 20W zu begrenzen. Für den ersten Ansatz genügt eine einfache On-Off-Regelung mit einer Hysterese von 1°C vollständig.

Der Ansatz ist dem Buch „Make: Action“ von Simon Monk entnommen. Der Code dazu befindet sich auf GitHub unter: https://github.com/simonmonk/make_action/tree/master/arduino/experiments/simple_thermostat

Die Steuerung des Mosfet-Treiberboards erfordert eine Kopplung der Erdung (GND, Ground) von Arduino-Board und Treiberboard. Digitale Ausgänge der Arduino-Boards können unmittelbar ohne Vorwiderstand mit dem Treiberboard verbunden werden. Es ist darauf zu achten, dass die Leistungsseite des Treiberboards galvanisch von der Steuerseite getrennt bleibt. Näheres ist der Anleitung des Boards zu entnehmen.

Schaltung und Fritzing-Diagramm folgen

Schaumerkennung

Beim Betrieb von Bioreaktoren kann es zu Schaumbildung kommen. Dieser Schaum kann die Sensoren innerhalb des Reaktors und damit den geregelten Betrieb beeinträchtigen.

Versuche:

Bestimmung des spezifischen Widerstands von Schaum aus Seife (Haarwaschmittel/ Geschirrspülmittel) und Gärschaum eines Hefeansatzes (10% Saccharose in 50% fettarme. Haltbare Milch, 50% dem. Wasser).

Kurze Wiederholung: Der spezifische Widerstand ist eine Materialkonstante. Sie gibt den Widerstand eines Stoffes bezogen auf eine Wirklänge an und wird in

oder wissenschaftlich in

angegeben. Zu seiner Bestimmung bedarf es also einen Aufbaus zweier Elektroden, die sich in einem definierten Abstand befinden sowie eines Ohmmeters.

Der spezifische Widerstand wird dann nach folgender Formel ermittelt:

In Schaum kann nicht von der geforderten gleichmäßigen Verteilung der Stromdichte ausgegangen werden. Bei gleicher Grundsubstanz des Schaumes spielt die Dichte / Porosität des Schaums eine entscheidende Rolle. Mit zunehmender Dichte sinkt der spezifische Widerstand. Dies ist sowohl bei der Gestaltung der Elektroden als auch bei der Auswertung der Ergebnisse zu berücksichtigen.

https://de.wikipedia.org/wiki/Spezifischer_Widerstand

Auch eine einzelne, große Schaumblase kann einen CO2-Sensor zerstören, darum ist die sichere und frühzeitige Erkennung von Schaum essentiell.

Teil A: Bestimmung des spezifischen Widerstands von Schaum

 

  • Protokoll zu Konstruktion und Aufbau einer Einrichtung zur Bestimmung des spezifischen Widerstands von Schaum aus Haarwaschmittel bzw. Gärschaum (inkl. Skizze).
  • Messergebnisse
  • Auswertung

Teil B: Konstruktion und Verifikation eines Schaumsensors

  • Protokoll zu Konstruktion und Aufbau einer Einrichtung zur automatisierten Schaumdetektion mit Hilfe des Arduino Nano.
  • Programm / Sketch
  • Messergebnisse
  • Auswertung und Bewertung

Es ist zu berücksichtigen, dass die Konstruktionen aus Alufolie auf Drahtrahmen über elektronisch wirksame Vorder- und Rückseiten verfügen.

Bilder, Schaltung und Sketch sowie Auswertungen folgen.