We're going to use CircuitPython, Mu, and the capacitive touch pads on Circuit Playground Express to plot soil moisture sensing. We'll run this code on our Circuit Playground Express and use Mu to plot the soil moisure data that CircuitPython prints out.

The hardware you'll need for this project is the Circuit Playground Express, an alligator clip and a nail. You'll also need at least two soil samples, one wet and one dry, for calibrating the code.

Assembly is as simple as connecting one end of your alligator clip to pad A1 on the Circuit Playground Express, and the other end of your alligator clip to the top of your nail.

Save the following as code.py on your Circuit Playground Express board, using the Mu editor:

# SPDX-FileCopyrightText: 2018 Kattni Rembor for Adafruit Industries
# SPDX-License-Identifier: MIT

import time
from adafruit_circuitplayground.express import cpx
import touchio
import simpleio
import board

cpx.pixels.brightness = 0.2
touch = touchio.TouchIn(board.A1)

DRY_VALUE = 1500  # calibrate this by hand!
WET_VALUE = 2100  # calibrate this by hand!

while True:
    value_A1 = touch.raw_value

    # fill the pixels from red to green based on soil moisture
    percent_wet = int(simpleio.map_range(value_A1, DRY_VALUE, WET_VALUE, 0, 100))
    cpx.pixels.fill((100-percent_wet, percent_wet, 0))

First we import the libraries we need. The first library is time. Next, you'll see we import a specific part of of the second library by saying from adafruit_circuitplayground.express import cpx. This way we can call this library by typing cpx instead of the longer library name. Then we import touchio, simpleio, and board.

We set the pixel brightness. Pixel brightness is set by a number between 0 and 1, representing 0-100%, i.e. 0.3 would be 30%. So we set our brightness to 20% with cpx.pixels.brightness = 0.2.  Then we create the touch object so we can use it as our moisture sensor. We are going to use pin A1 in this project, so we provide board.A1.

To sense whether the soil is dry or wet, we're going to use the raw capacitive touch values from the capacitive touch pad on the Circuit Playground Express. We create two variables, DRY_VALUE and WET_VALUE and assign them to the raw capacitive touch values associated with dry and wet soil.

We find these values in the main loop. We assign value_A1 = touch.raw_value, and then print the results of value_A1. This allows us to view the results of the raw capactitive touch values in the serial output. Wet soil has a higher raw capacitive touch value than dry soil, and we can use this to track whether the soil is wet or dry. The code comes with default values for both of these variables, however, the your actual results may be different. Therefore, you should calibrate these values first.

Note that the Mu plotter looks for tuple values to print. Tuples in Python come in parentheses () with comma separators. If you have two values, a tuple would look like (1.0, 3.14). Since we have only one value, we need to have it print out like (1.0,) note the parentheses around the number, and the comma after the number. Thus the extra parentheses and comma in print((value_A1,)).

DRY_VALUE and WET_VALUE both need to be calibrated by hand. To calibrate them, place the nail into your soil sample, and open the serial console (REPL) in Mu. Then you can see what the returned value is and you can change your variables to reflect it.

First place your nail into your dry soil sample.


As you can see, the dry value we are getting back is a little bit different than the default number. So let's change DRY_VALUE to reflect our results.


Now we'll do the same to get our wet value.

Place the nail into your wet soil sample.


Now look at the values in the serial output. Our wet value is a little bit different, so let's change WET_VALUE as well


We've determined our wet and dry values. Now we'll use these values to make the LEDs green when the soil is 100% wet, and red when the soil is dry, or 0% wet. This is how you'll know your plant needs to be watered!

LED colors are set using a combination of red, green, and blue, in the form of an (RG, B) tuple. Each member of the tuple is set to a number between 0 and 255 that determines the amount of each color present. Red, green and blue in different combinations can create all the colors in the rainbow! So, for example, to set the LED to red, the tuple would be (255, 0, 0), which has the maximum level of red, and no green or blue. Green would be (0, 255, 0), etc.

So, we're going to need to map the raw capacitive touch values to fit within the values needed for an RGB tuple. To do this, we're going to use simpleio.map_range. This works by providing the value we're going to use (value_A1), the minimum value we expect value_A1 to be (which is DRY_VALUE), the maximum value we expect value_A1 to be (WET_VALUE), and then the minimum and maximum numbers we'd like to match it to, which is 0 and 100. By assigning percent_wet = int(simpleio.map_range(value_A1, DRY_VALUE, WET_VALUE, 0, 100)), we are taking the raw capacitive touch values and mapping them to a whole number (int) between 0 and 100 to get a percentage.

We use this percentage to set the LEDs to be red when dry, green when wet, and a yellowish color in between as the soil is slowly drying out. We light up all the pixels with cpx.pixels.fill((100-percent_wet, percent_wet, 0)), which uses the percent_wet we get from the previous line.

When the soil is 100% wet, the first member of the tuple is 0 (100-percent_wet if percent_wet=100 is 0), and the second member is 100 (because percent_wet=100). So the tuple when the soil is wet is (0, 100, 0) which means the LEDs will be green. This is how you know you don't need to water your soil!

When the soil is 0% wet, the first member of the tuple is 100 (100-percent_wet if percent_wet=0 is 100), and the second member is 0 (because percent_wet=0). So the tuple when the soil is wet is (100, 0, 0) which means the LEDs will be red. This is how you know it's time to water your soil!

But what about when your soil is sort of wet and sort of dry? When the soil is 50% wet, the first member of the tuple is 50 (100-percent_wet if percent_wet=50 is 50), and the second member is 50 (because percent_wet=50). So the tuple when the soil is half dry is (50, 50, 0) which means the LEDs will be yellow. The yellow color will range from a greenish-yellow to a reddish-yellow as your soil goes from moist to slowly drying out. This is how you'll know it'll be time to water your soil soon!

Finally, we include a time.sleep(0.5) to slow down the speed of reading the data. Soil dries out slowly so there's no need for reading the data super quickly.

Once you have everything setup and running, try placing your nail into wet soil, and watch the plotter immediately react! Place your nail into dry soil to watch the plotter go down. Place it into soil that's only sort of wet to watch it go up a little Place it back into wet soil and watch it go up higher!

This is a great way to see see soil moisture levels using the capacitive touch pad, and plot the changes as the soil slowly dries out!

This guide was first published on Apr 09, 2018. It was last updated on Apr 09, 2018.

This page (Soil Moisture) was last updated on May 19, 2022.

Text editor powered by tinymce.