Capacitive Soil Moisture Sensor with Raspberry Pi Pico
Measure Soil Humidity percentage using Raspberry Pi Pico, Capacitive Soil Moisture Sensor V2.0 & OLED Display with MicroPython Code
- Suitable forB.Tech/Diploma RPi Pico students
- Build time1-2 weeks
- LevelBeginner
- Available atAjvika Labs, Kakinada
About this project
Overview
In this project, we will build a Soil Moisture Meter using Capacitive Soil Moisture Sensor V2.0 and Raspberry Pi Pico. We will display the measured Soil Moisture value on a 0.96″ I2C OLED Display.
This capacitive soil moisture sensor is different from most resistive sensors on the market, avoiding the problem that resistive sensors are easily corroded and greatly extending their working life. The Capacitive Soil moisture sensor can be inserted into the soil to measure the relative soil moisture content, which is commonly used in soil moisture monitoring,
agricultural irrigation
& forestry protection.
Components Required
In this guide, I used
Elecrow Raspberry Pi Pico Starter Kit
to test different Modules. You can buy the kit and perform some other operations as well. From this kit, you can use the following components.
1. Raspberry Pi Pico Board – 1
2. SSD1306 OLED Display – 1
3. Capacitive Soil Moisture Sensor V2.0 – 1
4. Breadboard – 1
5. Jumper Wires – 10
6. Micro-USB Cable – 1
Capacitive Soil Moisture Sensor V2.0
This capacitive soil moisture sensor V2.0 measures soil moisture levels by capacitive sensing rather than resistive sensing like other sensors on the market. It is made of corrosion-resistant material which gives it excellent service life. Insert it into the soil around your plants and impress your friends with real-time soil moisture data!
This module includes an onboard voltage regulator which gives it an operating voltage range of 3.3 ~ 5.5V. It is perfect for low-voltage MCUs, both 3.3V, and 5V. The Capacitive Soil Moisture Sensor can work with Raspberry Pi Pico via ADC.
The Capacitive Soil Moisture Sensor V2.0 works better and have improved result compared to its version of
Capacitive Soil Moisture Sensor V1.2
SSD1306 OLED Display
This is a 0.96-inch blue OLED display module. The display module can be interfaced with any microcontroller using SPI/IIC protocols. It is having a resolution of 128×64. The package includes a display board, a display, and 4 pin male header pre-soldered to the board.
OLED (
Organic Light-Emitting Diode
) is a self-light-emitting technology composed of a thin, multi-layered organic film placed between an anode and cathode. In contrast to LCD technology, OLED does not require a backlight. OLED possesses high application potential for virtually all types of displays and is regarded as the ultimate technology for the next generation of flat-panel displays.
A detailed tutorial on
OLED Display & Raspberry Pi Pico
interfacing is explained in the previous article. You can go through the article in detail to learn more about the OLED Display.
Interfacing Capacitive Soil Moisture Sensor & Raspberry Pi Pico
Now let us interface the Capacitive Soil Moisture Sensor with Raspberry Pi Pico & 0.96″ OLED Display. The connection diagram is very simple.
The SSD1306 OLED Display is an I2C Module. Therefore connect its SDA & SCL Pin to GP0 & GP1 of Raspberry Pi Pico. Power the OLED Display via 5V & GND pin of Raspberry Pi Pico.
The Capacitive Soil Moisture Sensor is an Analog Sensor. Connect its Analog output pin to GP26 of Raspberry Pi Pico. Power the Capacitive Soil Moisture Sensor via the 3.3V & GND pin of Raspberry Pi Pico.
MicroPython Code/Program
The code is divided into 2 parts. The 1st one is
ssd1306.py
and the other is
main.py
. The OLED Display doesn’t work directly as it requires SSD1306 Module library.
ssd1306.py
Copy the following code and save it as
ssd1306.py
in Raspberry Pi Pico.
# MicroPython SSD1306 OLED driver, I2C and SPI interfaces
from
micropython
import
const
import
framebuf
# register definitions
SET_CONTRAST
=
const
(
0x81
)
SET_ENTIRE_ON
=
const
(
0xA4
)
SET_NORM_INV
=
const
(
0xA6
)
SET_DISP
=
const
(
0xAE
)
SET_MEM_ADDR
=
const
(
0x20
)
SET_COL_ADDR
=
const
(
0x21
)
SET_PAGE_ADDR
=
const
(
0x22
)
SET_DISP_START_LINE
=
const
(
0x40
)
SET_SEG_REMAP
=
const
(
0xA0
)
SET_MUX_RATIO
=
const
(
0xA8
)
SET_COM_OUT_DIR
=
const
(
0xC0
)
SET_DISP_OFFSET
=
const
(
0xD3
)
SET_COM_PIN_CFG
=
const
(
0xDA
)
SET_DISP_CLK_DIV
=
const
(
0xD5
)
SET_PRECHARGE
=
const
(
0xD9
)
SET_VCOM_DESEL
=
const
(
0xDB
)
SET_CHARGE_PUMP
=
const
(
0x8D
)
# Subclassing FrameBuffer provides support for graphics primitives
# http://docs.micropython.org/en/latest/pyboard/library/framebuf.html
class
SSD1306
(
framebuf
FrameBuffer
)
:
def
__init__
(
self
width
height
external_vcc
)
:
self
width
=
width
self
height
=
height
self
external_vcc
=
external_vcc
self
pages
=
self
height
// 8
self
buffer
=
bytearray
(
self
pages *
self
width
)
super
(
)
__init__
(
self
buffer
self
width
self
height
framebuf
MONO_VLSB
)
self
init_display
(
)
def
init_display
(
self
)
:
for
cmd
in
(
SET_DISP
0x00
# off
# address setting
SET_MEM_ADDR
0x00
# horizontal
# resolution and layout
SET_DISP_START_LINE
0x00
SET_SEG_REMAP
0x01
# column addr 127 mapped to SEG0
SET_MUX_RATIO
self
height
SET_COM_OUT_DIR
0x08
# scan from COM[N] to COM0
SET_DISP_OFFSET
0x00
SET_COM_PIN_CFG
0x02
if
self
width
>
*
self
height
else
0x12
# timing and driving scheme
SET_DISP_CLK_DIV
0x80
SET_PRECHARGE
0x22
if
self
external_vcc
else
0xF1
SET_VCOM_DESEL
0x30
# 0.83*Vcc
# display
SET_CONTRAST
0xFF
# maximum
SET_ENTIRE_ON
# output follows RAM contents
SET_NORM_INV
# not inverted
# charge pump
SET_CHARGE_PUMP
0x10
if
self
external_vcc
else
0x14
SET_DISP
0x01
)
:
# on
self
write_cmd
(
cmd
)
self
fill
(
)
self
show
(
)
def
poweroff
(
self
)
:
self
write_cmd
(
SET_DISP
0x00
)
def
poweron
(
self
)
:
self
write_cmd
(
SET_DISP
0x01
)
def
contrast
(
self
contrast
)
:
self
write_cmd
(
SET_CONTRAST
)
self
write_cmd
(
contrast
)
def
invert
(
self
invert
)
:
self
write_cmd
(
SET_NORM_INV
(
invert
&
)
)
def
show
(
self
)
:
x0
=
x1
=
self
width
if
self
width
==
:
# displays with width of 64 pixels are shifted by 32
x0
+=
x1
+=
self
write_cmd
(
SET_COL_ADDR
)
self
write_cmd
(
x0
)
self
write_cmd
(
x1
)
self
write_cmd
(
SET_PAGE_ADDR
)
self
write_cmd
(
)
self
write_cmd
(
self
pages
)
self
write_data
(
self
buffer
)
class
SSD1306_I2C
(
SSD1306
)
:
def
__init__
(
self
width
height
i2c
addr
=
0x3C
external_vcc
=
False
)
:
self
i2c
=
i2c
self
addr
=
addr
self
temp
=
bytearray
(
)
self
write_list
=
[
b
"\x40"
None
]
# Co=0, D/C#=1
super
(
)
__init__
(
width
height
external_vcc
)
def
write_cmd
(
self
cmd
)
:
self
temp
[
]
=
0x80
# Co=1, D/C#=0
self
temp
[
]
=
cmd
self
i2c
writeto
(
self
addr
self
temp
)
def
write_data
(
self
buf
)
:
self
write_list
[
]
=
buf
self
i2c
writevto
(
self
addr
self
write_list
)
class
SSD1306_SPI
(
SSD1306
)
:
def
__init__
(
self
width
height
spi
dc
res
cs
external_vcc
=
False
)
:
self
rate
=
*
1024
*
1024
dc
init
(
dc
OUT
value
=
)
res
init
(
res
OUT
value
=
)
cs
init
(
cs
OUT
value
=
)
self
spi
=
spi
self
dc
=
dc
self
res
=
res
self
cs
=
cs
import
time
self
res
(
)
time
sleep_ms
(
)
self
res
(
)
time
sleep_ms
(
)
self
res
(
)
super
(
)
__init__
(
width
height
external_vcc
)
def
write_cmd
(
self
cmd
)
:
self
spi
init
(
baudrate
=
self
rate
polarity
=
phase
=
)
self
cs
(
)
self
dc
(
)
self
cs
(
)
self
spi
write
(
bytearray
(
[
cmd
]
)
)
self
In this project, we will build a Soil Moisture Meter using Capacitive Soil Moisture Sensor V2.0 and Raspberry Pi Pico. We will display the measured Soil Moisture value on a 0.96″ I2C OLED Display.
This capacitive soil moisture sensor is different from most resistive sensors on the market, avoiding the problem that resistive sensors are easily corroded and greatly extending their working life. The Capacitive Soil moisture sensor can be inserted into the soil to measure the relative soil moisture content, which is commonly used in soil moisture monitoring,
agricultural irrigation
& forestry protection.
Components Required
In this guide, I used
Elecrow Raspberry Pi Pico Starter Kit
to test different Modules. You can buy the kit and perform some other operations as well. From this kit, you can use the following components.
1. Raspberry Pi Pico Board – 1
2. SSD1306 OLED Display – 1
3. Capacitive Soil Moisture Sensor V2.0 – 1
4. Breadboard – 1
5. Jumper Wires – 10
6. Micro-USB Cable – 1
Capacitive Soil Moisture Sensor V2.0
This capacitive soil moisture sensor V2.0 measures soil moisture levels by capacitive sensing rather than resistive sensing like other sensors on the market. It is made of corrosion-resistant material which gives it excellent service life. Insert it into the soil around your plants and impress your friends with real-time soil moisture data!
This module includes an onboard voltage regulator which gives it an operating voltage range of 3.3 ~ 5.5V. It is perfect for low-voltage MCUs, both 3.3V, and 5V. The Capacitive Soil Moisture Sensor can work with Raspberry Pi Pico via ADC.
The Capacitive Soil Moisture Sensor V2.0 works better and have improved result compared to its version of
Capacitive Soil Moisture Sensor V1.2
SSD1306 OLED Display
This is a 0.96-inch blue OLED display module. The display module can be interfaced with any microcontroller using SPI/IIC protocols. It is having a resolution of 128×64. The package includes a display board, a display, and 4 pin male header pre-soldered to the board.
OLED (
Organic Light-Emitting Diode
) is a self-light-emitting technology composed of a thin, multi-layered organic film placed between an anode and cathode. In contrast to LCD technology, OLED does not require a backlight. OLED possesses high application potential for virtually all types of displays and is regarded as the ultimate technology for the next generation of flat-panel displays.
A detailed tutorial on
OLED Display & Raspberry Pi Pico
interfacing is explained in the previous article. You can go through the article in detail to learn more about the OLED Display.
Interfacing Capacitive Soil Moisture Sensor & Raspberry Pi Pico
Now let us interface the Capacitive Soil Moisture Sensor with Raspberry Pi Pico & 0.96″ OLED Display. The connection diagram is very simple.
The SSD1306 OLED Display is an I2C Module. Therefore connect its SDA & SCL Pin to GP0 & GP1 of Raspberry Pi Pico. Power the OLED Display via 5V & GND pin of Raspberry Pi Pico.
The Capacitive Soil Moisture Sensor is an Analog Sensor. Connect its Analog output pin to GP26 of Raspberry Pi Pico. Power the Capacitive Soil Moisture Sensor via the 3.3V & GND pin of Raspberry Pi Pico.
MicroPython Code/Program
The code is divided into 2 parts. The 1st one is
ssd1306.py
and the other is
main.py
. The OLED Display doesn’t work directly as it requires SSD1306 Module library.
ssd1306.py
Copy the following code and save it as
ssd1306.py
in Raspberry Pi Pico.
# MicroPython SSD1306 OLED driver, I2C and SPI interfaces
from
micropython
import
const
import
framebuf
# register definitions
SET_CONTRAST
=
const
(
0x81
)
SET_ENTIRE_ON
=
const
(
0xA4
)
SET_NORM_INV
=
const
(
0xA6
)
SET_DISP
=
const
(
0xAE
)
SET_MEM_ADDR
=
const
(
0x20
)
SET_COL_ADDR
=
const
(
0x21
)
SET_PAGE_ADDR
=
const
(
0x22
)
SET_DISP_START_LINE
=
const
(
0x40
)
SET_SEG_REMAP
=
const
(
0xA0
)
SET_MUX_RATIO
=
const
(
0xA8
)
SET_COM_OUT_DIR
=
const
(
0xC0
)
SET_DISP_OFFSET
=
const
(
0xD3
)
SET_COM_PIN_CFG
=
const
(
0xDA
)
SET_DISP_CLK_DIV
=
const
(
0xD5
)
SET_PRECHARGE
=
const
(
0xD9
)
SET_VCOM_DESEL
=
const
(
0xDB
)
SET_CHARGE_PUMP
=
const
(
0x8D
)
# Subclassing FrameBuffer provides support for graphics primitives
# http://docs.micropython.org/en/latest/pyboard/library/framebuf.html
class
SSD1306
(
framebuf
FrameBuffer
)
:
def
__init__
(
self
width
height
external_vcc
)
:
self
width
=
width
self
height
=
height
self
external_vcc
=
external_vcc
self
pages
=
self
height
// 8
self
buffer
=
bytearray
(
self
pages *
self
width
)
super
(
)
__init__
(
self
buffer
self
width
self
height
framebuf
MONO_VLSB
)
self
init_display
(
)
def
init_display
(
self
)
:
for
cmd
in
(
SET_DISP
0x00
# off
# address setting
SET_MEM_ADDR
0x00
# horizontal
# resolution and layout
SET_DISP_START_LINE
0x00
SET_SEG_REMAP
0x01
# column addr 127 mapped to SEG0
SET_MUX_RATIO
self
height
SET_COM_OUT_DIR
0x08
# scan from COM[N] to COM0
SET_DISP_OFFSET
0x00
SET_COM_PIN_CFG
0x02
if
self
width
>
*
self
height
else
0x12
# timing and driving scheme
SET_DISP_CLK_DIV
0x80
SET_PRECHARGE
0x22
if
self
external_vcc
else
0xF1
SET_VCOM_DESEL
0x30
# 0.83*Vcc
# display
SET_CONTRAST
0xFF
# maximum
SET_ENTIRE_ON
# output follows RAM contents
SET_NORM_INV
# not inverted
# charge pump
SET_CHARGE_PUMP
0x10
if
self
external_vcc
else
0x14
SET_DISP
0x01
)
:
# on
self
write_cmd
(
cmd
)
self
fill
(
)
self
show
(
)
def
poweroff
(
self
)
:
self
write_cmd
(
SET_DISP
0x00
)
def
poweron
(
self
)
:
self
write_cmd
(
SET_DISP
0x01
)
def
contrast
(
self
contrast
)
:
self
write_cmd
(
SET_CONTRAST
)
self
write_cmd
(
contrast
)
def
invert
(
self
invert
)
:
self
write_cmd
(
SET_NORM_INV
(
invert
&
)
)
def
show
(
self
)
:
x0
=
x1
=
self
width
if
self
width
==
:
# displays with width of 64 pixels are shifted by 32
x0
+=
x1
+=
self
write_cmd
(
SET_COL_ADDR
)
self
write_cmd
(
x0
)
self
write_cmd
(
x1
)
self
write_cmd
(
SET_PAGE_ADDR
)
self
write_cmd
(
)
self
write_cmd
(
self
pages
)
self
write_data
(
self
buffer
)
class
SSD1306_I2C
(
SSD1306
)
:
def
__init__
(
self
width
height
i2c
addr
=
0x3C
external_vcc
=
False
)
:
self
i2c
=
i2c
self
addr
=
addr
self
temp
=
bytearray
(
)
self
write_list
=
[
b
"\x40"
None
]
# Co=0, D/C#=1
super
(
)
__init__
(
width
height
external_vcc
)
def
write_cmd
(
self
cmd
)
:
self
temp
[
]
=
0x80
# Co=1, D/C#=0
self
temp
[
]
=
cmd
self
i2c
writeto
(
self
addr
self
temp
)
def
write_data
(
self
buf
)
:
self
write_list
[
]
=
buf
self
i2c
writevto
(
self
addr
self
write_list
)
class
SSD1306_SPI
(
SSD1306
)
:
def
__init__
(
self
width
height
spi
dc
res
cs
external_vcc
=
False
)
:
self
rate
=
*
1024
*
1024
dc
init
(
dc
OUT
value
=
)
res
init
(
res
OUT
value
=
)
cs
init
(
cs
OUT
value
=
)
self
spi
=
spi
self
dc
=
dc
self
res
=
res
self
cs
=
cs
import
time
self
res
(
)
time
sleep_ms
(
)
self
res
(
)
time
sleep_ms
(
)
self
res
(
)
super
(
)
__init__
(
width
height
external_vcc
)
def
write_cmd
(
self
cmd
)
:
self
spi
init
(
baudrate
=
self
rate
polarity
=
phase
=
)
self
cs
(
)
self
dc
(
)
self
cs
(
)
self
spi
write
(
bytearray
(
[
cmd
]
)
)
self
Technologies used
Hardware components
- Raspberry Pi
- SSD1306
- OLED
- Soil Moisture
Software & tools
- MicroPython
What you get
- Working project / hardware kit, tested before delivery
- Complete source code with explanation
- Project demo and guidance for your viva
- Project report, PPT and IEEE paper support (on request)
Delivery & Payment
Delivery takes a minimum of two weeks from the date your inquiry is confirmed.
Payment is in two parts:
• 50% advance to start the project
• Remaining 50% before delivery
Note:
• Documentation and PPT are not included by default
• If you need documentation/PPT, it can be arranged for extra time and cost
We'll confirm the exact timeline and cost with you after reviewing your requirements.