---
# System prepended metadata

title: Simple device for measuring moisture level in soil

---

# Simple device for measuring moisture level in soil
Author Name: Ludvig Sandberg - Student credentials: ls224bn

This tutorial explains how to build a simple device for measuring moisture level in soil and display the data in percentage on the Pybytes cloud platform. The project will use Pycoms LoPy4 and a Capacitive Soil Moisture Sensor. This project took me around 8 hours in total to complete.
![](https://i.imgur.com/W3YU63v.jpg =600x600)

## Objective
The reason I chose this project was that I have a plant that is very sensitive for low moisture levels. There have been a couple of times when the plant almost gave up on me when the moisture levels were to low. The purpose of this project was to have a device that reports the moisture level to me in an easy to access platform so i could monitor the moisture level of the plant at all times. 

My interest of IoT-devices has been with me since i worked in a electronics store a couple of years ago. I had this project in my backlog for a long time, but i never managed to find the time to get it started. So this was the perfect opportunity to start developing this device! This project will give me the insights i need to continue the development of this device to the level i wish it to have.

## Material
Here is a list of the components that was used in this project:

* LoPy4 - Cost: €34,95 - https://pycom.io/product/lopy4/
* Expansion Board 3.0 - Cost €16,00 - https://pycom.io/product/expansion-board-3-0/
* Capacitive Soil Moisture Sensor - Cost: ≈€7,54 - https://hitechchain.se/arduinokompatibel/kapacitiv-jordfuktighet-sensor
* Breadboard - Cost: ≈€5,63 - https://www.electrokit.com/produkt/kopplingsdack-400-anslutningar/
* Connecting wires - Cost: ≈€3,43 - https://www.electrokit.com/produkt/kopplingstrad-byglar-for-kopplingsdack-mjuka-65st/

### LoPy4 and Expansion Board 3.0
The LoPy4 is a development board that is enabled with MicroPython. It has several bands of connectivity, such as WiFi, LoRa, SigFox and more. For more information about the device check the link that is present in the list above. The Expansion Board is a complementary device for the LoPy4. It is necessary to have because it has an USB-port and also a JST battery connector, that is useful for the mobility of the final product.
![](https://i.imgur.com/X0BzJO5.png =300x300)


### Capacitive Soil Moisture Sensor
This sensor measures the levels of soil moisture through capacitive sensors. It is made of corrosion resistant material. The sensor contains a built-in voltage regulator that offers a voltage range of 3.3 ~ 5.5V. For more information about this sensor, check the following link: https://wiki.dfrobot.com/Capacitive_Soil_Moisture_Sensor_SKU_SEN0193
![](https://i.imgur.com/G5DLNSn.png)


## Computer Setup
In this project i used the IDE Atom with the pymakr plugin. To download Atom just visit their website and download the IDE: https://atom.io/. When the installation of Atom is complete, head to the Settings. In the Settings, click on the Install option and search for the pymakr package as seen in Fig 1.
![](https://i.imgur.com/C4c8COY.png "Fig 1")

NOTE: If you use Windows, as i do, you have to download Node.js for the plugin to work. You can download Node.js from the following link: https://nodejs.org/en/.

When the plugin is installed and you connect the device to a USB-port on your computer, a new window will appear with the REPL command line interface. This interface was used to communicate with the LoPy4 during the project. It is used to upload or download code to/from the device and to run the code. In Fig 2 you can see the REPL interface.

![](https://i.imgur.com/LM2bver.png "Fig 2")

More information about the pymakr plugin can be found here: https://atom.io/packages/pymakr.

You may have to update the firmware of the LoPy4 device. To do this follow the instructions here: https://docs.pycom.io/gettingstarted/installation/firmwaretool/. 
This firmwaretool will also come in handy during the process of connecting the device to the Pybytes platform. More on that later.

In the instructions it is mentioned that a update of the firmware of the Expansion Board is necessary before you can update the firmware of the LoPy4. I would recommend that you do this, follow the instructions here: https://docs.pycom.io/pytrackpysense/installation/firmware/. However, during this project i did not manage to update the firmware of the Expansion Board. The instructions of updating the firware on Windows was hard to follow, so i decided to continue without updating the firmware of the Expansion Board and see if it would work anyway. In my case it worked out fine, but i still recommend that you update the firmware of the Expansion Board.

## Putting everything together
This is how i connected the sensor to the Pycom device:
![](https://i.imgur.com/MHEzd5F.jpg)

Unfortunately i do not know how to draw a circuit diagram, so i am going to explain where i connected to cables instead. The black cable represents the ground (GND). There is a pin next to the JST-connector on the Expansion Board that says GND, so i connect that pin to the black cable from the sensor. The red cable represents the voltage. As i mentioned before, this sensor has a built-in voltage regulator that offers a voltage range of 3.3 ~ 5.5V. Luckily the Pycome device can provide 3,3V output. Next to the GND pin on the device there is a pin that says 3V3. Connect the red cable to that pin. Lastly the yellow cable represents the data cable. The sensor provides the data as an analog signal. To use this data, the Pycom device has to convert the analog signal to a digital signal. To be able to convert the signal you must connect the data cable to any of the pins P13-P20, more on this during the code explanation. In this project, i connected the yellow cable to pin P13.

The goal of the project is not to build a device that is ready for production, the goal is to make a simple device for experimental use. That is why the "building" of the actual device is very simple.

## Platform
For this project i decided to use the Pytbytes platform. The Pybytes platform is a free cloud-based device mangement platform available for all Pycom development boards and modules. According to me, it is an easy to use platform with alot of potential. On this platform you can add your Pycom devices and manage them in a browser or on a mobile application. You can see all the signals the devices sends to the platform and create dashboards for displaying this data in a neat way. Pybytes have features such as, integration with other cloud providers, network mangement, device monitoring and tracking etc.

For now the Pybytes platform fits for all my needs. In the future i may continue using it or change platform, i have not decided on that decision yet.

## The code
Here is all the MicroPython code i used during this project:
```
import time
from machine import ADC

adc = ADC()
apin = adc.channel(pin='P13', attn=ADC.ATTN_11DB)

DRY = 3740 #in_max
WET = 1660 #in_min

def arduino_map_percentage_calc(x, in_min, in_max, out_min, out_max):
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min

while True:
    val = arduino_map_percentage_calc(apin(), DRY, WET, 0, 100)
    time.sleep(10)
    if val < 0:
        print("0")
        pybytes.send_signal(1,"0")
    elif val > 100:
        print(100)
        pybytes.send_signal(1,"100")
    else:
        print(val)
        pybytes.send_signal(1, val)

```
As you can see, there is not much code needed for this project. The main component of this code is the ADC-class from machine. ADC stands for Analog to Digital Conversion. First i create an object from the class ADC, called adc. This object i needed to associate a channel to a pin. When the object is created, the method channel(pin,attn) is called.

The method channel() creates an analog channel on the selected pin. In this case i create a analog channel on P13 with an attenuation level of 11dB. This means that the output voltage from the sensor is at maximum 3,3V. The supported values of the attenuation are: 0dB, 2,5dB, 6dB and 11dB. During this project all the different values were tested, but the highest value of 11dB gave the most relevant result according to myself. So i decided to use that. More information about this class can be found here: https://docs.pycom.io/firmwareapi/pycom/machine/adc/.

There are 2 constants in the code, DRY and WET. These constants are needed to calibrate and calculate the percentage of the moisture level in the soil. The output data from the sensor is in millivolts. The constant DRY is when the sensor is not in contact with any moisture, so the sensor is dry. To get this value you just keep the sensor in the air and print the value of apin() (print(apin())). You should get some value close to 3300 mV because that is the highest value the sensor can provide (See this link for more information about the sensor: https://wiki.dfrobot.com/Capacitive_Soil_Moisture_Sensor_SKU_SEN0193). The higher the value, the drier the sensor is. To get the value for WET you do the opposite, you put the sensor in a glass of water. Be careful to expose the sensitive part of the sensor to any water, see Fig 3:
![](https://i.imgur.com/BbnES6u.png "Fig 3" =300x)
(Figure reference: https://wiki.dfrobot.com/Capacitive_Soil_Moisture_Sensor_SKU_SEN0193)

Lets continue and explain the function arduino_map_percentage_calc(). This function is used for remapping one value to another. In this case, to convert the output value from the sensor to percentage. The function is based from the function map() in Arduino, see reference: https://www.arduino.cc/reference/en/language/functions/math/map/. 

In the while-loop the following occurs. First, we read the analog value from the sensor and convert that into percentage like this:
```
val = arduino_map_percentage_calc(apin(), DRY, WET, 0, 100)
```
Here the parameters are apin(), DRY, WET, 0, 100. Parameter apin() is retrieving the value from the sensor, DRY and WET is the range we want to convert into a range of 0 to 100 instead. The program waits for ten seconds before it prints out the value and sends the data to Pybytes via the method send_signal(). If the value is below 0, it just prints 0%, if the value is above 100 it prints out 100%.

## Transmitting the data
To be able to send data to the Pybytes platform, you need to first create an account on Pybytes and add a device to that account. First create a project. In Pybytes click the Projects option and go through all the steps. For this project it is necessary to choose WiFi and type in your local WiFi-credentials. When that is done add a device to that project. You have to add the device to you Pybytes-account first. It is possible to add devices through the mobile application, but i would recommend to add the device via USB. 

When does steps are done it is time to activate the device and link it to Pybytes, see Fig 4:
![](https://i.imgur.com/GaiW8Zc.png "Fig 4" =500x)
I would recommend to use the firmwaretool that you downloaded before. Generate an activation token as you can see in Fig 4 and copy it. Then open your firmwaretool Pycom Upgrade (Note: Be sure to close down Atom before doing this). 
![](https://i.imgur.com/K829YoB.png "Fig 5")
As you can see in Fig 5, be sure to select pybytes as type and check the "Force update Pybytes registration" box before continuing. 

![](https://i.imgur.com/cw19SL8.png "Fig 6")
Paste the activation token from Fig 4 and continue the upgrade process. When this is done your device should be connected to Pybytes. The signal is now transmitting over WiFi with the MQTT-protocol from the pycom device to the Pybytes platform.

## Presenting the data
The data that is presented in a graph on my Pybytes dashboard, see Fig 7:

![](https://i.imgur.com/M3ubNDf.png "Fig 7")
In the bottom graph is the moisture level from the device shown. When this screenshot was taken, the sensor was laying on the table. That is why the values are only 2-4%. I will now present some screenshots from the graph during calibration and when it was in dry and wet soil.

This is the data received when calibrating the DRY constant:
![](https://i.imgur.com/0WZn0wz.png)
![](https://i.imgur.com/loPn0Qc.png)

This is the data received when calibrating the WET constant:
![](https://i.imgur.com/MifF3cM.png)
![](https://i.imgur.com/NPIvUu2.png)


The data received when the sensor was in very dry soil:
![](https://i.imgur.com/7yVUsAf.png)
![](https://i.imgur.com/RpQghIf.png)

And lastly, the data received when the sensor was in very wet soil:
![](https://i.imgur.com/rV0wp9m.png)
![](https://i.imgur.com/Iy5LYtS.png)

This data is saved for one month in Pybytes. This is not really necessary for the purpose of the project, but it wont hurt if the data is saved longer than needed.

## Finalizing the design
The final result of this project can be summarized in the following figure:
![](https://i.imgur.com/MeG6epE.jpg)
The final result is a graph of the moisture level of a plant that is displayed in Pybytes in percentage instead of volts. I think the project went pretty good. I ordered the components a little late so it got pretty stressful when i finally received the parts. This is a good start of a product that i will continue to develop in the future. 

My goals of this project from the beginning was to develop a simple mobile or web app that could display the data and possibly send notifications when the moisture level was low. Unfortunately i did not have the time to do that right now, so that will be a future project to solve. The goal is also to build some type of weather proof case for the device, so it could be used outside aswell.

Thank you for following this tutorial, and i hope it helped in some way!