Taglilie

Bodenfeuchte-Messung mit dem Raspberry Pi Pico

1. Einleitung

Anfang 2021 brachte die Raspberry Pi Foundation das Raspberry Pi Pico Mikrocontroller Board (im Weiteren RasPi Pico) auf den Markt.

Aufgrund der Vielfalt an integrierten Funktionen und Schnittstellen sowie des vergleichsweise geringen Preises erschien es mir lohnend, ein weiteres System im Umfeld der ferngesteuerten Pflanzenbewässerung zu entwickeln.

Eine komfortable Sache (wenn auch ein wenig eine Spielerei) wäre es zum Beispiel, einen Bodenfeuchte-Sensor in die Erde zu stecken und dann über eine Anzeige (z. B. mehrfarbige LED, Siebensegmentanzeige) eine Indikation zum aktuellen Feuchtegrad der Pflanzenerde zu erhalten.

Dies würde den Weg über die RasPi SSH-Shell bzw. eine App ersparen (ein Raspberry Pi ist kein Mikrocontroller Board, sondern ein vollwertiger Rechner mit Betriebssystem), falls kein Bedarf an einer genauen Messung besteht und man ohnehin vor Ort ist.

2. Projekt Bodenfeuchte-Kontrollsystem

Die Realisierung eines solchen Einsteigerprojektes ist mit dem RasPi Pico nicht sehr schwierig (hier kann man gleich zur Präsentation springen).

Man benötigt neben dem Board lediglich einen Bodenfeuchte-Sensor – ich benutze vorerst wiederum den preiswerten Iduino ME110 – sowie eine Lochrasterplatine (Steckboard geht natürlich auch) mit RGB-LED einschließlich Vorwiderstände zur Strombegrenzung.

2.1 Bauteile und Anschlüsse

Die in diesem Projekt genutzten Bauteile sind im Einzelnen:

  • RasPi Pico – Datenblatt, RP2040 Datenblatt
  • RGB-LED – Datenblatt
  • Resistiver Bodenfeuchte-Sensor ME110 – Datenblatt
  • 3xVorwiderstand für LED (siehe Abschnitt 2.2, 2.3)
  • Lochrasterplatine (z. B. mit 202 Kontakten)
  • Micro-USB Kabel
  • Buchsen- und Steckerleisten, Schaltlitze (0,14 mm² verwendet)

Verwendete Ports auf dem Mikrocontroller Board mit Zuordnung:

  • GP3 – blaue LED
  • GP4 – rote LED
  • GP5 – grüne LED
  • GP26 (ADC Eingang A0) – Sensorausgang S
  • Pin 36 – 3,3V Sensor-Versorgung1
  • Pin 8, Pin 38 – GND (AGND nicht benötigt)

1 es handelt sich hier um eine sog. ratiometrische Sensorschnittstelle da die Versorgungsspannung des Sensors gleichzeitig die Referenzspannung (Pin ADC_AVDD am RP2040) für den Analog-Digital-Wandler (ADC) darstellt

2.2 Kontrollrechnungen

Da ich keine 47 oder 56 Ohm Widerstände zur Hand hatte schaltete ich für die drei LEDs die ich verwenden wollte jeweils zwei 100 Ohm Widerstände parallel.

Der theoretische Strom durch eine grüne LED beträgt somit in etwa:

ILEDgr, th = (UGP5[V]-USchwell gr, th[V])/R[Ω] = (3,3-2,2)/50 = 22mA

Durch eine rote LED:

ILEDrot, th = (UGP4[V]-USchwell rot, th[V])/R[Ω] = (3,3-1,9)/50 = 28mA

Auch wenn mir Stromlimits der GP Ports nicht genau bekannt waren erwartete ich bei Strömen dieser Größenordnung an GP4 bzw. GP5 eigentlich keine Probleme (Messungen siehe Abschnitt 2.3).

Es sei noch erwähnt, dass der theoretische Strom über die (hier nicht verwendete) blaue LED aufgrund der vergleichsweise hohen Schwellenspannung (etwa 3,0V) weit geringer wäre.

Überhaupt sind LED-Schwellenspannungen Exemplarstreuungen unterworfen die durchaus beträchtlich sein können. Bei Bedarf sollte man daher Messungen am individuellen Bauteil durchführen.

Die Empfehlung für das Stromlimit an Pin 36 lautet 300mA (der Sensor benötigt weniger als 20mA), wobei der Bodenfeuchte-Sensor auch mit den +5V von Pin 40 (Signal VBUS, also USB-Spannung) versorgt werden könnte.

2.3 Kontrollmessungen

Für mich etwas überraschend waren Werte der Kontrollmessungen.

Der Strom am individuellen GP Port wird im Chip auf etwa 12 mA begrenzt, und man misst bei voller PWM-Ansteuerung (siehe weiter unten) z. B. der grünen LED nur noch eine Spannung von etwa 2,7V.

Im Datenblatt des RP2040 Mikrocontrollers gibt es in Kapitel 2.10.5. einen Hinweis zum Stromlimit; davon abgesehen ist es etwas unklar wie hoch “erlaubte” Ströme sein dürfen.

Der Ist-Strom durch die grüne LED berechnet sich mit den Messwerten nach (trennt man die Leitungen auf kann man den Strom auch direkt messen):

ILEDgr, ist = (UGP5[V]-USchwell gr, ist[V])/R[Ω] = (2,7-2,1)/50 = 12mA

Die praktische Maßnahme aus dieser Erkenntnis wäre nun alle Widerstandswerte zu erhöhen (für eine SMD LED zum Beispiel 470 Ohm, vgl. “user LED” an GP25), oder ein anderes Konzept etwa mit einer Transistorschaltung umzusetzen.

3. Coding mit MicroPython

MicroPython Skripte finden sich in meinem RasPi Github-Repository.

Dieser Code beinhaltet neben der LED-Ansteuerung zusätzlich Befehle zur Ansteuerung einer einzelnen Siebensegmentanzeige.

Anzumerken ist, dass der Sensor trotz Versorgung mit 3,3V einen Maximaloutput von circa 1,7V an Pin S aufweist (Wert aus dem ME110 Datenblatt für nasse Erde), was der Algorithmus berücksichtigen sollte2. Der erlaubte Bereich für die ADC-Eingangsspannung geht ohne externe Referenz bis 3,3V (Pin 35, ADC_VREF).

Logik: Die Helligkeit der grünen LED wird bei Kontakt mit dem Medium je nach Feuchtegrad linear in dem Maße verringert wie die Helligkeit der roten LED erhöht wird (und vice versa). Keine sonderlich brillante Mathematik; zum Testen und für Präsentationszwecke ist sie aber an der Stelle ausreichend.

Die Helligkeits-Steuerung selbst geschieht über eine sogenannte Pulsweitenmodulation (PWM) die zwei Parameter besitzt: Tastgrad und Frequenz.

Für die Erzeugung der PWM besitzt der Pico dedizierte Hardware. Somit erspart sich der Entwickler eine Implementierung via Software die ein paar Nachteile hat (für dieses Projekt würden diese keine Rolle spielen).

Verschiedenen Tastgrade der PWM zur Helligkeitssteuerung einer LED (Frequenz konstant)
Verschiedenen Tastgrade der PWM zur Helligkeitssteuerung einer LED (Frequenz konstant)

Ein 16bit-Wert bestimmt den Tastgrad (0% – 100%) der PWM, das heißt die Auflösung derselben erstreckt sich von 0 – 65.535.

Da ich keinen Motor o. Ä. ansteuere ist die Höhe der PWM-Frequenz nicht kriegsentscheidend (gewählt wurde für GP3, GP4, GP5 eine Frequenz von 500 Hertz). Aus offensichtlichen Gründen wäre es aber gut wenn die LEDs nicht flackern.

Das Programm fordert über den Befehl “ADC.A0.read_u16()” einen 16bit Wert an, etwas verwirrend aufgrund der Tatsache dass im Board eigentlich ein 12bit ADC implementiert ist (der 12bit Wert wird skaliert3). Dies gestaltet die weitere Verarbeitung für meinen Anwendungsfall komfortabel.

2 siehe Codebeispiel: in Python bzw. MicroPython erfolgt bei Rechenoperationen mit float und integer immer die implizite Umwandlung des Ergebnisses in float; der PWM Tastgrad muss ein integer-Wert sein

3 die in einer der libs verborgene Mathematik hinter dieser Skalierung ist nach meiner Kenntnis eine sog. Taylor-Expansion; Pseudocode: rohwert << (16 – 12) | rohwert >> (2 * 12 – 16)

4. Produktiver Test

Die Interaktion mit dem RP2040 findet ausschließlich über den USB-Anschluss statt.

Zunächst muss die MicroPython Firmware auf den Pico geflasht werden.

Eine Anleitung dazu – im Grunde ist es nur den BOOTSEL (Boot Selector) Taster während des Einsteckens gedrückt halten und anschließendes drag&drop eines .uf2-Files (USB Flashing Format) – und die aktuelle Version gibt es unter diesem Link.

4.1 Betrieb am Rechner

Ich benutze unter Windows das Tool Thonny, das man hier herunterladen kann. Mit diesem Programm ist ein live Update des Codes und eine sofortige Ergebniskontrolle möglich.

Auf einem Raspberry Pi ist Thonny normalerweise schon mitinstalliert, daher wäre ein ad-hoc Betrieb über einen RasPi USB-Port ebenfalls eine Option.

4.2 Flash des Skriptes

Der SW-“Flash” (eher ein banales Kopieren) ist via Raspberry Pi simpel: das Skript wird einfach als “main.py” in den Pico-Speicher abgelegt (mittels Thonny GUI).

Das Tool Thonny
Das Tool Thonny

Natürlich besteht daneben immer die Möglichkeit, ein kompiliertes C-Programm in Form eines .uf2-Files in den Speicher zu flashen, welches dann natürlich eine MicroPython Firmware (die selbst nichts anderes ist als ein kompiliertes C-Programm) oder andere bereits geflashte Dateien überschreibt4.

Ist diese Arbeit getan benötigt man nur noch die Spannungsversorgung; ein extra Rechnersystem wäre nun überflüssig da das Programm mit dem Einstecken automatisch startet.

4 ein .uf2-File wird in einen speziellen Speicherbereich des Pico abgelegt (” […] UF2 file […] is written to specified locations in RAM or Flash.”, Kapitel 2.8.3.1 im RP20240 Datenblatt); ein schon vorhandenes main.py Skript bleibt unangetastet da es sich in einem völlig anderen Speicherbereich befindet

5. Technische Erweiterungen

Der beschriebene Aufbau ist für den Einstieg gedacht und schöpft eher nicht die unzähligen SW-Möglichkeiten eines RasPi Pico, sowie von HW und Erweiterungen aus.

Besonders der verwendete Bodenfeuchte-Sensor weist aufgrund seines Messprinzips eine Reihe von Nachteilen auf und ist ein Kandidat für eine Aufwertungsaktion (das heißt Umstieg auf etwas teurere kapazitive Sensorik).

Da der Pico drei externe ADC-Pins besitzt (GP26, GP27, GP28) wäre ein Parallelbetrieb von bis zu drei Sensoren sehr einfach möglich. Eine externe “Shunt Referenz” (s. Pico Datenblatt Kapitel 4.3) kann außerdem die Leistungsfähigkeit des ADC erhöhen, obgleich diese integrierte Komponente leider inhärent Rausch- und Stabilitätsprobleme aufweist – eine zugekaufte ADC-Platine ist für sensiblere Anwendungen wohl die bessere Wahl.

Auch ein anderes Anzeige-Design sei der Phantasie des Entwicklers überlassen (z. B. LCD oder OLED-Display am I2C-Bus) und wird an dieser Stelle nicht weiter thematisiert.

Ein Projekt mit zwei Siebensegmentanzeigen ist jedoch auf meiner hackaday.io-Projektseite näher erläutert.

6. Literatur

1. Mikroprozessortechnik – Klaus Wüst, Vieweg+Teubner; ISBN 978-3-8348-0906-3 (4. Auflage)

2. Elektronik Tabellen: Betriebs- und Automatisierungstechnik – Michael Dzieia, Westermann; ISBN 978-3142350165 (4. Auflage)