• First Steps
  • General
  • Projects
Facebook Twitter YouTube
Tutorials for Raspberry Pi Tutorials for Raspberry Pi
  • Hardware & GPIO
  • Sensors & Components
  • Scale
  • Cases
  • Fingerprint
  • Gas Sensor
  • Heartbeat
  • German
  • French
Tutorials for Raspberry Pi Tutorials for Raspberry Pi
Home»Hardware & GPIO»Read Capacitive Soil Moisture Sensor DFROBOT Gravity on the Raspberry Pi

Read Capacitive Soil Moisture Sensor DFROBOT Gravity on the Raspberry Pi

Facebook Twitter LinkedIn Tumblr Email Reddit
Capacitive Moisture Sensor Raspberry Pi
Share
Facebook Twitter LinkedIn Email Tumblr Reddit Telegram WhatsApp

In the field of Raspberry Pi soil moisture measurement, there are resistive and capacitive sensors, which each have advantages and disadvantages. The innovative Raspberry Pi casting machine / DFROBOT Gravity or “Giess-o-Mat” sensor provides a permanently accurate capacitive measurement, which a.o. in our Raspberry Pi greenhouse can be very interesting.

This tutorial is about the structure of the Raspberry Pi casting machine as well as the reading of the frequency, with the help of which the relative soil moisture can be calculated.

Since I have been asked by several users and there is not much material on the subject (in terms of the Raspberry Pi), I hope that this tutorial will make using it a bit easier.

 

Required Hardware Parts

For this I have taken the following hardware parts or components:

  • Raspberry Pi 4
  • Capacitive DFROBOT Gravity or “Giess-o-Mat” moisture sensor
  • optional: frequency divider
  • alternatively: multiple 100kΩ resistors
  • Jumper Cable
  • Soldering iron + solder

I recommend to take the coated version of the board right away, otherwise, it will anyway have to be manually sealed by hand. The supplied components of the board/sensor (listed below) are in SMD format and therefore not really suitable for beginners. With a little skill, the size should not be a problem.

The frequency divider can also be replaced by a resistor. In this case, the 100kΩ resistor at position R3 (see below) is replaced by a larger one: If the frequency is halved, a twice as large resistance is taken, etc. It is, of course, possible to combine several resistors.

 

Advantages over Resisitive Moisture Sensors

Resistive earth moisture sensor
Resistive earth moisture sensors often do not last long.

In a previous tutorial, we connected and read out a very low-priced soil moisture sensors on the Raspberry Pi. However, this design has a problem that occurs over time: corrosion. After prolonged use with the same polarity, the sensors often partially decompose. This is not good for the measuring behaviour nor for the soil values.

This danger does not exist with capacitive sensors. In this case, however, no analog signal is output, which can be read with an MCP3008 ADC, but a frequency that varies in height – depending on the humidity of the earth (the wetter, the lower).

The output frequency (up to 450kHz) is too much for the Raspberry Pi, which is why we either use a frequency divider that divides it by a certain dividend, or simply a bigger resistor. The disadvantage of a frequency divider is the price because a simple resistor costs almost nothing.

 

Assembly of the Raspberry Pi casting machine

The Giess-o-Mat usually does not come assembled, which is why the individual SMD components have yet to be soldered onto the board. Since these are very small, a look on the label helps. I also tried to document each step with pictures, so nothing goes wrong.

The DFROBOT Gravity sensor is easier to handle: There is no soldering required, so you can ignore this step.

The following help sheet can be found in the bag of the components:

Description Type Label Function
T1 BC847B 1Ft od. 1FW Transistor
C1 10μF 10V Condenser
IC1 74HC14D HC14 IC
D1 BZX84B5V6 T12 or Z3 Zener diode 5v6
R1 1k 102 od. 1001 Resistor 1k
R2 100R 101 od. 1000 Resistor 100R
R3 100k 104 od. 1003 Resistor 100k

Let’s start with the IC. It is important that the side with the “up” mark shows where the little round notch can be seen on the PCB.

The capacitor (C1) has no label and it does not matter which side is soldered where:

With the resistors (R1, R2, R3) you must be careful since the SMD inscription does not correspond to the actual size. On this page, you can simply enter the imaged value of the SMD resistor and get the real size calculated.

If you do not have a frequency divider, you can also use a larger resistor instead of R3 (as described above).

 

Subsequently, the only transistor (T1) and Zener diode (D1), which have the same shape, are missing. Here again, helps the label from above:

 

Assemble Frequency Divider (optional)

In the same way as the casting machine, we also build the frequency divider if we have one.

First the table:

Description Type Label Function
T1 BC847B 1Ft, 1F-, 1FW Transistor
C1 10μF 10V Condenser
IC1 74HC4040 HC4040 IC
D1 BAS40 43t, 43-, 43p, 43W Schottky Diode
R1, R2 2k2 222, 2201 Resistor 2k2

Again, we start with the IC, the capacitor and the resistors. The size of R1 and R2 is identical.

frequency divider

Still missing transistor (T1) and the diode (D1). Pay attention again to the label, as the design is identical:

frequency divider 2

 

Last but not least, the two contacts of “: 16” are soldered together, resulting in a 16 times lower frequency.

In addition, I have soldered the two boards together and soldered to the frequency divider a few contacts for the jumper cable.

Raspberry Pi Giessomat

 

 

A Script for reading the Frequency

First connect V + and 3.3V from the Raspberry Pi, GND to GND and OUT e.g. at GPIO21.

To read the frequency on Raspberry Pi is the PiGPIO library, which brings libraries for C (++), Python, etc. It is already preinstalled on ordinary Raspbian versions (not Lite), otherwise we can install it afterwards:

sudo apt-get update
sudo apt-get install pigpio python-pigpio python3-pigpio

 

Then we create a new C-file, which is there to read the frequency:

sudo nano freq_count_1.c

This file gets the following content (example from here). Save with CTRL + O and return CTRL + X to the terminal.

C++
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();
}
 
 

Then we compile the files:

gcc -Wall -pthread -o freq_count_1 freq_count_1.c -lpigpio -lrt

Now the program can already be called. Only the corresponding GPIO pin must be specified, to which “OUT” is connected (eg 21):

sudo ./freq_count_1 21

Then the number of the GPIO followed by the frequency (in Hz) will be displayed. As a test, you can put the sensor in a glass of water and watch the frequency decrease.

In a project like the Raspberry Pi greenhouse, it is now important to find out the optimal value. However, this depends on the soil, the irrigation and the plants and therefore can not be answered clearly. For me, full wetness (glass of water) gave a frequency of about 1000Hz, with total dryness (no conductive material) about 10kHz (with a frequency divider of 16).

If you use a Python script, you can also extend/shorten the upper C program and integrate it into your Python script.

 

Further information on Giess-o-Mat

Further information about the casting machine is available a.o. on the following pages, most of which are for use with Arduino and/or ESP8266 and less with the Raspberry Pi. Nevertheless, I think that it can be worth reading links for those interested:

  • 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

If you know another good source, you can post it as a comment so I can expand the list.

detection module Frequency Humidity Humidity Detection Hygrometer Moisture soil moisture
Share. Facebook Twitter Pinterest LinkedIn Tumblr Email
Previous ArticleRaspberry Pi RetroPie Guide – SNES Classic Spielekonsole selber bauen
Next Article Raspberry Pi Web Server Installation Part 6 – DNS Server via No-IP

Related Posts

How to build a ESP8266 Scale (with Weight Sensor HX711)

How-To: Bluetooth Connection between ESP32’s and Raspberry Pi’s

How to create a Solar Powered Raspberry Pi Bitcoin Miner

How to build a Smart Agriculture System using IoT

Leave A Reply Cancel Reply

Run a Raspberry Pi on rechargeable Batteries

How to connect and control a Raspberry Pi WS2801 RGB LED Strip

Connect and Control WS2812 RGB LED Strips via Raspberry Pi

Install and set up Raspberry Pi Wifi Stick

Raspberry Pi: Measure Humidity and Temperature with DHT11/DHT22

Measuring Soil Moisture with the Raspberry Pi

Subscribe to Blog
Subscribe to Raspberry Pi Tutorials and don't miss any new Tutorial!
Subscribe

Thank you!

We will contact you soon.

Tutorials for Raspberry Pi
Facebook Twitter YouTube
  • Contact & Disclaimer

Type above and press Enter to search. Press Esc to cancel.