Kapazitiven Erdfeuchtigkeitssensor „Giess-o-Mat“ am Raspberry Pi auslesen
Im Bereich der Raspberry Pi Bodenfeuchtigkeitsmessung gibt es resistive und kapazitive Sensoren, welche jeweils Vor- und Nachteile haben. Der neuartige Raspberry Pi Giessomat / „Giess-o-Mat“ Sensor bietet eine dauerhaft präzise kapazitive Messung, was u.a. in unserem Raspberry Pi Gewächshaus sehr interessant sein kann.
In diesem Tutorial geht es um den Aufbau des Raspberry Pi Giessomat sowie dem Auslesen der Frequenz, mit Hilfe derer die relative Erdfeuchte errechnet werden kann.
Da ich nun von mehreren Usern gebeten wurde und es zu dem Thema (im Hinblick auf den Raspberry Pi) nicht viel Stoff gibt, hoffe ich, dass dieses Tutorial die Benutzung etwas vereinfacht.
Zubehör
Dazu habe ich folgendes Zubehör bzw. Bauteile genommen:
- Raspberry Pi 3
- kapazitiver Giess-o-Mat Feuchtigkeitssensor (Alternative)
- optional: Frequenzteiler
- alternativ: vielfaches vom 100kΩ Widerstand
- Jumper Kabel
- Lötkolben + Lötzinn
Ich empfehle gleich die beschichtete Version der Platine zu nehmen, da diese ansonsten in jedem Fall aufwändig per Hand versiegelt werden muss. Die mitgelieferten Bauteile der Platine/Sensor (weiter unten gelistet) sind im SMD Format und daher nicht unbedingt für Löt-Anfänger geeignet. Mit ein wenig Geschick sollte die Größe aber kein Problem darstellen.
Der Frequenzteiler kann auch durch einen Widerstand ersetzt werden. Dabei wird der 100kΩ Widerstand an Position R3 (siehe weiter unten) um einen größeren getauscht: Soll die Frequenz halbiert werden, so wird ein doppelt so großer Widerstand genommen, usw. Dabei ist es natürlich möglich mehrere Widerstände zu kombinieren.
Vorteile gegenüber resisitiven Feuchtigkeitssensoren


Resisitive Erdfeuchtigkeitssensoren sind oft nicht von Dauer.
In einem vorherigen Tutorial haben wir die sehr günstigen Bodenfeuchtigkeitssensoren am Raspberry Pi angeschlossen und ausgelesen. Diese Bauart hat allerdings ein Problem, welches im Laufe der Zeit auftritt: Korrosion. Nach längerer Benutzung bei gleicher Polung zersetzen sich oftmals die Sensoren teilweise. Dies ist weder für das Messverhalten noch für die Bodenwerte gut.
Diese Gefahr besteht bei kapazitiven Sensoren hingegen nicht. Dabei wird allerdings kein analoges Signal ausgegeben, welches mit einem MCP3008 ADC ausgelesen werden kann, sondern eine Frequenz, die unterschiedlich hoch ausfällt – je nach Feuchtigkeit der Erde (je nasser, umso niedriger).
Die ausgegebene Frequenz (bis 450kHz) ist zu viel für den Raspberry Pi, weshalb wir entweder einen Frequenzteiler nehmen, der diese eben um einen gewissen Dividenden teilt, oder einfach einen größeren Widerstand. Der Nachteil eines Frequenzteiler ist der Preis, da ein einfacher Widerstand quasi nichts kostet.
Zusammenbau des Raspberry Pi Giessomat
Der Giess-o-Mat kommt gewöhnlicherweise nicht zusammengebaut, weshalb die einzelnen SMD Bausteine erst noch auf die Platine gelötet werden müssen. Da diese sehr klein sind, hilft ein Blick auf derern Beschriftung. Außerdem habe ich versucht jeden Schritt mit Bildern zu dokumentieren, damit nichts schief geht.
Folgender Hilfszettel findet sich in der Tüte der Bauteile:
Bezeichnung | Typ | Aufschrift | Funktion |
---|---|---|---|
T1 | BC847B | 1Ft od. 1FW | Transistor |
C1 | 10μF 10V | Kondensator | |
IC1 | 74HC14D | HC14 | IC |
D1 | BZX84B5V6 | T12 oder Z3 | Zehnerdiode 5v6 |
R1 | 1k | 102 od. 1001 | Widerstand 1k |
R2 | 100R | 101 od. 1000 | Widerstand 100R |
R3 | 100k | 104 od. 1003 | Widerstand 100k |
Beginnen wir mit dem IC. Dabei ist es wichtig, dass die Seite mit der Markierung „nach oben“ zeigt, wo auf dem PCB die kleine runde Einkerbung zu sehen ist.
Der Kondensator (C1) hat keine Aufschrift und es spielt keine Rolle, welche Seite wo verlötet wird:
Bei den Widerständen (R1, R2, R3) musst du vorsichtig sein, da die SMD Beschriftung nicht der eigentlichen Größe entspricht. Auf dieser Seite kannst du einfach den abgebildeten Wert des SMD Widerstands eingeben und dir die echte Größe berechnen lassen.
Falls du keinen Frequenzteiler hast, kannst du (wie oben beschrieben) auch einfach einen größeren Widerstand anstelle von R3 nutzen.
Anschließend fehlen nur noch Transistor (T1) und Zehnerdiode (D1), welche die gleiche Form haben. Hier hilft wieder die Beschriftung von oben:
Zusammenbau Frequenzteiler (optional)
Auf die gleiche Weise wie den Giessomat bauen wir auch den Frequenzteiler zusammen, sofern wir einen besitzen.
Zunächst die Tabelle:
Bezeichnung | Typ | Aufschrift | Funktion |
---|---|---|---|
T1 | BC847B | 1Ft, 1F-, 1FW | Transistor |
C1 | 10μF 10V | Kondensator | |
IC1 | 74HC4040 | HC4040 | IC |
D1 | BAS40 | 43t, 43-, 43p, 43W | Schottky Diode |
R1, R2 | 2k2 | 222, 2201 | Widerstand 2k2 |
Auch hier beginnen wir mit dem IC, dem Kondensator sowie den Widerständen. Die Größe von R1 und R2 ist identisch.
Fehlen noch Transistor (T1) und die Diode (D1). Achte dabei wieder auf die Beschriftung, da die Bauform identisch ist:
Zu guter letzt werden die beiden Kontakte von „:16“ zusammengelötet, wodurch eine 16-fach geringere Frequenz ankommt.
Außerdem habe ich die beiden Platinen noch miteinander verlötet und an den Frequenzteiler ein paar Kontakte für die Jumper Kabel angelötet.
Skript zum Auslesen der Frequenz
Schließe zunächst V+ and 3.3V vom Raspberry Pi an, GND an GND und OUT z.B. an GPIO21.
Zum Auslesen der Frequenz am Raspberry Pi eignet sich die PiGPIO Bibliothek, welche Bibliotheken für C(++), Python, etc. mitbringt. Auf gewöhnlichen Raspbian Versionen (nicht Lite) ist es bereits vorinstalliert, ansonsten können wir es hiermit nachinstallieren:
sudo apt-get update sudo apt-get install pigpio python-pigpio python3-pigpio
Anschließend erstellen wir eine neue C-Datei, welche zum Auslesen der Frequenz da ist:
sudo nano freq_count_1.c
Diese Datei bekommt folgenden Inhalt (Beispiel von hier). Mit STRG+O speichern und STRG+X zum Terminal zurückkehren.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
#include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <unistd.h> #include <pigpio.h> /* 2014-08-20 gcc -o freq_count_1 freq_count_1.c -lpigpio -lpthread $ sudo ./freq_count_1 4 7 8 This program uses the gpioSetAlertFunc function to request a callback (the same one) for each gpio to be monitored. EXAMPLES Monitor gpio 4 (default settings) sudo ./freq_count_1 4 Monitor gpios 4 and 8 (default settings) sudo ./freq_count_1 4 8 Monitor gpios 4 and 8, sample rate 2 microseconds sudo ./freq_count_1 4 8 -s2 Monitor gpios 7 and 8, sample rate 4 microseconds, report every second sudo ./freq_count_1 7 8 -s4 -r10 Monitor gpios 4,7, 8, 9, 10, 23 24, report five times a second sudo ./freq_count_1 4 7 8 9 10 23 24 -r2 Monitor gpios 4, 7, 8, and 9, report once a second, sample rate 1us, generate 2us edges (4us square wave, 250000 highs per second). sudo ./freq_count_1 4 7 8 9 -r 10 -s 1 -p 2 */ #define MAX_GPIOS 32 #define OPT_P_MIN 1 #define OPT_P_MAX 1000 #define OPT_P_DEF 20 #define OPT_R_MIN 1 #define OPT_R_MAX 10 #define OPT_R_DEF 5 #define OPT_S_MIN 1 #define OPT_S_MAX 10 #define OPT_S_DEF 5 static volatile int g_pulse_count[MAX_GPIOS]; static volatile int g_reset_counts; static uint32_t g_mask; static int g_num_gpios; static int g_gpio[MAX_GPIOS]; static int g_opt_p = OPT_P_DEF; static int g_opt_r = OPT_R_DEF; static int g_opt_s = OPT_S_DEF; static int g_opt_t = 0; void usage() { fprintf (stderr, "\n" \ "Usage: sudo ./freq_count_1 gpio ... [OPTION] ...\n" \ " -p value, sets pulses every p micros, %d-%d, TESTING only\n" \ " -r value, sets refresh period in deciseconds, %d-%d, default %d\n" \ " -s value, sets sampling rate in micros, %d-%d, default %d\n" \ "\nEXAMPLE\n" \ "sudo ./freq_count_1 4 7 -r2 -s2\n" \ "Monitor gpios 4 and 7. Refresh every 0.2 seconds. Sample rate 2 micros.\n" \ "\n", OPT_P_MIN, OPT_P_MAX, OPT_R_MIN, OPT_R_MAX, OPT_R_DEF, OPT_S_MIN, OPT_S_MAX, OPT_S_DEF ); } void fatal(int show_usage, char *fmt, ...) { char buf[128]; va_list ap; va_start(ap, fmt); vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); fprintf(stderr, "%s\n", buf); if (show_usage) usage(); fflush(stderr); exit(EXIT_FAILURE); } static int initOpts(int argc, char *argv[]) { int i, opt; while ((opt = getopt(argc, argv, "p:r:s:")) != -1) { i = -1; switch (opt) { case 'p': i = atoi(optarg); if ((i >= OPT_P_MIN) && (i <= OPT_P_MAX)) g_opt_p = i; else fatal(1, "invalid -p option (%d)", i); g_opt_t = 1; break; case 'r': i = atoi(optarg); if ((i >= OPT_R_MIN) && (i <= OPT_R_MAX)) g_opt_r = i; else fatal(1, "invalid -r option (%d)", i); break; case 's': i = atoi(optarg); if ((i >= OPT_S_MIN) && (i <= OPT_S_MAX)) g_opt_s = i; else fatal(1, "invalid -s option (%d)", i); break; default: /* '?' */ usage(); exit(-1); } } return optind; } void edges(int gpio, int level, uint32_t tick) { int g; if (g_reset_counts) { g_reset_counts = 0; for (g=0; g<MAX_GPIOS; g++) g_pulse_count[g] = 0; } /* only record low to high edges */ if (level == 1) g_pulse_count[gpio]++; } int main(int argc, char *argv[]) { int i, rest, g, wave_id, mode; gpioPulse_t pulse[2]; int count[MAX_GPIOS]; /* command line parameters */ rest = initOpts(argc, argv); /* get the gpios to monitor */ g_num_gpios = 0; for (i=rest; i<argc; i++) { g = atoi(argv[i]); if ((g>=0) && (g<32)) { g_gpio[g_num_gpios++] = g; g_mask |= (1<<g); } else fatal(1, "%d is not a valid g_gpio number\n", g); } if (!g_num_gpios) fatal(1, "At least one gpio must be specified"); printf("Monitoring gpios"); for (i=0; i<g_num_gpios; i++) printf(" %d", g_gpio[i]); printf("\nSample rate %d micros, refresh rate %d deciseconds\n", g_opt_s, g_opt_r); gpioCfgClock(g_opt_s, 1, 1); if (gpioInitialise()<0) return 1; gpioWaveClear(); pulse[0].gpioOn = g_mask; pulse[0].gpioOff = 0; pulse[0].usDelay = g_opt_p; pulse[1].gpioOn = 0; pulse[1].gpioOff = g_mask; pulse[1].usDelay = g_opt_p; gpioWaveAddGeneric(2, pulse); wave_id = gpioWaveCreate(); /* monitor g_gpio level changes */ for (i=0; i<g_num_gpios; i++) gpioSetAlertFunc(g_gpio[i], edges); mode = PI_INPUT; if (g_opt_t) { gpioWaveTxSend(wave_id, PI_WAVE_MODE_REPEAT); mode = PI_OUTPUT; } for (i=0; i<g_num_gpios; i++) gpioSetMode(g_gpio[i], mode); while (1) { for (i=0; i<g_num_gpios; i++) count[i] = g_pulse_count[g_gpio[i]]; g_reset_counts = 1; for (i=0; i<g_num_gpios; i++) { printf(" %d=%d", g_gpio[i], count[i]); } printf("\n"); gpioDelay(g_opt_r * 100000); } gpioTerminate(); } |
Anschließend kompilieren wir die Datei:
gcc -Wall -pthread -o freq_count_1 freq_count_1.c -lpigpio -lrt
Nun kann das Programm bereits aufgerufen werden. Dabei muss nur der entsprechende GPIO Pin angegeben werden, an welchem „OUT“ verbunden ist (bspw. 21):
sudo ./freq_count_1 21
Anschließend wird die Nummer des GPIOs, gefolgt von der Frequenz (in Hz) angezeigt. Als Test kannst du den Sensor in ein Glas Wasser stellen und wirst beobachten, wie sich die Frequenz verringert.
Im einem Projekt wie dem Raspberry Pi Gewächshaus gilt es nun, den optimalen Wert herauszufinden. Dies ist allerdings abhängig von der Erde, der Bewässerung und den Pflanzen und kann daher nicht eindeutig beantwortet werden. Bei mir ergab volle Nässe (Glas Wasser) eine Frequenz von ca. 1000Hz, wobei totale Trockenheit (kein leitendes Material) ungefähr 10kHz (mit einem Frequenzteiler von 16).
Solltest du ein Python Skript nutzen, so kannst du das obere C-Programm auch erweitern/verkürzen und in dein Python Skript einbinden.
Weitere Informationen zum Thema Giess-o-Mat
Weiterführende Informationen zu dem Gießomat gibt es u.a. auf den nachfolgenden Seiten, wobei es sich dabei meist um die Benutzung mit Arduino und/oder ESP8266 und weniger mit dem Raspberry Pi geht. Dennoch denke ich, dass es lesenswerte Links für Interessierte sein können:
- https://www.mikrocontroller.net/articles/Giess-o-mat
- https://github.com/Zentris/erdfeuchtemessung
- http://www.n8chteule.de/zentris-blog/category/erdfeuchtemessung/
- https://wwwvs.cs.hs-rm.de/vs-wiki/index.php/Internet_der_Dinge_WS2015/SmartPlant#Messmethode_2:_Kapazitiv
Falls du eine weitere gute Quelle kennst, kannst du sie gerne als Kommentar posten, sodass ich die Liste erweitern kann.