Plant Watering Robot with a Raspberry Pi

Picture of the plant watering robot on a desk.

Building a useful robot doesn’t have to require complicated code or expensive equipment. With a Raspberry Pi and some cheap, basic hardware, you can keep your plants healthy and happy from anywhere in the world!

Follow this tutorial to learn how to set up an automatic plant watering system:

  1. Complete the physical assembly and wiring.
  2. Create and connect to the robot, and configure your robot’s components.
  3. Configure the ADC as a module from the registry.
  4. Write code utilizing the Viam Python SDK to control the plant watering robot.
Error

You can also follow a simplified version of this tutorial in this video: it eliminates the need for the ADC and the breadboard, instead using the digital pin of the moisture sensor to get “high” and “low” readings and to turn a relay on and off. You can start with this simple version and then add the ADC to make your machine more accurate!

The tutorial uses the following hardware, but you can adjust it as needed:

Before starting this tutorial, follow the Raspberry Pi Setup Guide to prepare your machine to run viam-server. Connect your Pi to its power supply to power it on. Make sure your Pi is flashed with a Viam-compatible operating system, and that you are able to SSH into it.

Set up your plant watering robot

Before programming the machine, you need to physically set up the plant watering robot by wiring the different components together. You will set up the robot to receive signals from the resistive soil moisture sensor and signal to the peristaltic pump when it is time to pump water from the water container to the plant container.

Full wiring diagram

Refer back to this diagram as you complete the steps to wire your hardware. Turn your Pi off while you are wiring the hardware.

The full wiring diagram for all the hardware for the Plant Watering Robot.

Wire your ADC

The analog-to-digital converter (ADC) converts the resistive soil moisture sensor’s analog readings to digital signals that can be processed by your machine, which expects digital signals to come to it through its GPIO pins.

Start by wiring your ADC to your machine.

You can find a Raspberry Pi pinout diagram at pinout.xyz. Reference the following pinout diagram for your MCP3008 analog-to-digital converter:

Pinout diagram for the ADC.

Insert the MCP3008 into your breadboard so that it bridges both sides of the divide. Now you can use the breadboard points next to the MCP3008 to connect pins on the MCP3008 to your Raspberry Pi and other peripherals using jumper wires. Begin by connecting MCP3008 pins to your Raspberry Pi:

MCP3008 ADC PinRaspberry Pi Pin
CLKSCLK
DOUTMISO
DINMOSI
CS/SHDN24GPIO8

Next, connect MCP3008 pins to the ground and power rails on the breadboard:

MCP3008 ADC PinBreadboard
VDDAny point on 5V power rail (red +)
VREFAny point on 5V power rail (red +)
AGNDAny point on GND rail (blue -)
DGNDAny point on GND rail (blue -)

Finally, connect your breadboard rails to 5V power and ground on the Raspberry Pi:

Breadboard railRaspberry Pi pin
Any point on 5V power rail (red +)Pin 4 (a 5 volt power pin)
Any point on GND rail (blue -)pin 34 (a ground pin)

Wire your resistive soil moisture sensor

Next, wire your resistive soil moisture sensor to your Pi and ADC.

Reference this diagram of the blue module part of the sensor:

Pinout diagram for the resistive soil moisture sensor.

Start by connecting the female jumper wires at the end of the sensor prongs to the blue module where the diagram shown above is labeled “Connect with Probe.” Be careful of the positive and negative sides, and make sure to match them correctly.

Then, wire the rest of the pins on the module to the breadboard as follows:

Moisture Sensor PinBreadboard
A0 (Analog Signal Output)CH0
VCCAny point on 5V power rail (red +)
GNDAny point on GND rail (blue -)

Put the soil moisture sensor inside of the container holding your plant.

Wire your pump

Now, wire and power your pump and relay module to complete your hardware setup:

  1. Use a splicing connector to connect your 5V pump motor’s positive wire to a jumper wire, and connect it to the NO pin on the relay module. NO stands for normally open, which will keep the circuit open unless the pin is triggered.
  2. Use a splicing connector to connect your 5V pump motor’s negative wire to a jumper wire, and connect it to pin 39 (ground) on the Raspberry Pi.
  3. Connect the COM (common) pin on the relay to pin 2 (5V) on the Pi.
  4. Connect the DC+ pin on the relay to pin 1 (3.3V) on the Pi.
  5. Connect the DC- pin on the relay to pin 14 (ground) on the Pi.
  6. Connect the IN pin on the relay to the pin 8 (GPIO 14) on the Pi.

Program your plant watering robot

Enable SPI on your machine

Now that you have wired your ADC and moisture sensor, make sure that the Serial Peripheral Interface (SPI) is enabled on your machine. This protocol allows your machine to communicate with the moisture sensor peripheral.

Turn your machine back on. SSH into your machine and run the following command:

sudo raspi-config

Once the raspi-config interface is open, navigate to Interface Options:

Raspi-config Tool interface with Interface Options selected.

Then, select SPI:

Raspi-config Tool interface with SPI selected.

Now, select Yes to enable SPI:

Raspi-config Tool interface with Yes selected for SPI enablement.

Finally, select Finish. Restart your machine using sudo reboot to make these changes take effect.

Configure the components of your robot in the Viam app

Add a new machine in the Viam app. On the machine’s page, follow the setup instructions to install viam-server on the computer you’re using for your project. Wait until your machine has successfully connected to the Viam app.

Then, navigate to the CONFIGURE tab of your new machine’s page in the app.

First, add your machine as a board component:

Click the + icon next to your machine part in the left-hand menu and select Component or service. Select the board type, then select the appropriate viam:raspberry-pi:pi model (for example, viam:raspberry-pi:pi4 for Raspberry Pi 4). Enter a name for your board and click Create. This tutorial uses the name local.

Creation of a board in the Viam app config builder.

{
  "components": [
    {
      "name": "local",
      "model": "pi",
      "api": "rdk:component:board",
      "attributes": {},
      "depends_on": []
    }
  ]
}

Configure the ADC as a module from the registry

Resources refer to the different components and services Viam provides for robots to use. Components refer to types of hardware, and each component’s built-in models support the most common models of this hardware. For example, the sensor component has an ultrasonic model built in for the ubiquitous ultrasonic sensor.

However, there are many different types of sensors used for sensing different things across the Internet of Things. Although the resistive soil moisture sensor is not currently one of Viam’s built-in models, you can add an analog-to-digital-converter (ADC) as a module and use it to get readings from the moisture sensor.

A module provides one or more modular resources, which add resource types (components and services) or models that are not built into Viam. A module can be added to your robot from the Viam Registry.

The Viam Registry allows hardware and software engineers to collaborate on their robotics projects by writing and sharing custom modules with each other. You can add a module from the Viam Registry directly from your robot’s CONFIGURE tab in the Viam app, using the + (Create) button.

To add the mcp300x-adc-sensor module to your robot, follow these steps:

  1. Go to your machine’s CONFIGURE tab. Click the + icon next to your machine part in the left-hand menu and select Component or service.

  2. Search for mcp300x and select sensor / mcp300x. Click Add module.

  3. Give your module a name of your choice. We used the name sensor.

  4. Click Create to add this module to your machine.

  5. Find your module’s card on the CONFIGURE page. Copy the following JSON object into the configuration field.

    {
      "channel_map": {
        "moisture": 0
      },
      "sensor_pin": 8
    }
    

    sensor_pin is the GPIO pin number of the machine’s pin you connected to the MCP300x chip. If you followed the wiring in this tutorial, this will be 8 which is pin 24, GPIO 8 (SPI Chip Select 0). Otherwise if you are using CS1, use 7.

Save your config by clicking Save in the top right corner of the page.

On the sensor configuration panel, click on the TEST area to confirm you can get readings from your sensor.

This module allows you to get multiple readings at the same time from different channels of the ADC sensor. If you wire and configure another sensor, such as a temperature sensor on channel 1, you can add the sensor to the "channel_map" and get a reading from it.

Now that you have set up your robot, you can put the suction tube of your pump into the water cup, and the output tube into the plant!

Install the Python SDK

Make sure any packages on your Pi are up to date, while connected to your Pi with SSH run:

sudo apt update
sudo apt upgrade

Then run the following command to create and activate the virtual environment: If you want to read more on virtual environments, check out the documentation.

python3 -m venv .venv
source .venv/bin/activate

Make sure you have pip installed for Python 3:

pip --version

If not, run the following command:

sudo apt install python3-pip

Run the following command to install the SDK:

pip3 install viam-sdk

Add Python control code

Follow these instructions to start working on your Python control code:

  1. Navigate to your machine’s page in the Viam app, and click on the CONNECT tab and the Code sample page.

  2. Select Python as the language.

  3. Follow the instructions shown under step 1 on that page to install the SDK.

  4. Then, under step 2 on that page, click the copy icon to copy the generated code sample, which establishes a connection with your robot when run.

    To show your machine’s API key in the sample code, toggle Include API key.

  5. Paste this code sample into a new file on your machine.

  6. Name the file plant-watering-robot.py, and save it.

Run the following commands on your machine to create and open the file:

source .venv/bin/activate
touch plant-watering-robot.py
nano plant-watering-robot.py

Now, you can add code into plant-watering-robot.py to write the logic that defines your plant watering system.

To start, add your system logic code into the main() function of the program. Use the Viam board and sensor API methods to read from the moisture sensor and control the pump’s voltage with PWM as a GPIO pin.

You can get your components from the robot like this:

# Note that this name, `sensor`, is defined when you add the mcp300x module
sensor = Sensor.from_robot(robot=robot, name='sensor')
# Note that this name, `local`, is defined when you add the board
local = Board.from_robot(machine, "local")

Then, add a control loop that runs continuously, similar to the following example:

while True:
    # this level depends on your specific setup, replace after testing

    is_not_moist = 600

    # Get the moisture sensor's readings
    readings = await sensor.get_readings()
    soil_moisture = readings.get('moisture')

    # Calculate the average moisture reading from the list of readings
    # to account for outliers
    avg_moisture = sum(soil_moisture) / len(soil_moisture)

    # If the average moisture reading indicates moisture, trigger pump
    # watering
    if (avg_moisture > is_not_moist):
        print('this plant is too thirsty! giving it more water')

        # Get the GPIO pin with PWM output (pin number 8) the water pump is
        # wired to on the board through the relay's IN wire
        pwm_pin = await local.gpio_pin_by_name(name="8")

        # Run the water pump
        # Set the duty cycle to .8, meaning that this pin will be in the
        # high state, powering the pump motor, for 80% of the duration of the
        # PWM interval period
        await pwm_pin.set_pwm(duty=0.8)

        # Wait for 15 seconds
        print('watering')
        time.sleep(15)

        # Stop the pump by setting the duty cycle to 0%
        await pwm_pin.set_pwm(duty=0.0)

        # Wait 60 seconds so that the water can soak into the soil a bit before
        # trying to water again
        print('waiting a little bit for the water to soak in')
        time.sleep(60)

Test motor

On your machine’s CONTROL page in the Viam app, expand the TEST card for your board component. You should see a panel that allows you to control individual GPIO pins.

Enter 8 as a GPIO number. Set a decimal value between 0 and 1, (for example 0.8), to activate the motor and begin pumping water. Set a value of 0 to turn the motor off and stop pumping water.

Test moisture sensor

On your machine’s CONTROL page in the Viam app, expand the TEST card for your sensor to see a live observed value from your moisture sensor. Test your sensor by putting it in air, water, and soils containing different amounts of moisture. Use these observed values to determine an appropriate is_not_moist value for your setup.

Save control code

Save plant-watering-robot.py with this logic added in, and then run it on your machine with the following command:

sudo python3 plant-watering-robot.py

Next steps

Now that you have created your automatic plant watering system with a resistive soil moisture sensor, you can easily use Viam to automate other aspects of your garden. For example, you can use a light sensor or a temperature sensor, and get readings from other channels of the MCP3008!

You could set up data capture and graph your sensor data, or create your own custom Typescript dashboard to display your sensor data.

If you build something based on this please share it in our Community Discord - we’d love to see it.