Raspberry Pi, Python and watering indoor plants

I have no relationship with indoor plants. The fact is that I forget to water them. Knowing this, I began to reflect on the fact that someone, for sure, had already found a way to automate irrigation. As it turned out, there are a lot of ways. Namely, we are talking about solutions based on Arduino or Raspberry Pi. In this article I want to talk about how I created a system based on Raspberry Pi and Python, designed to automate watering plants.



Components and Useful Resources


I would immediately like to note that I am not at all an expert in electronics. If they ask me to draw an electrical diagram, or to tell in detail about how any electronic component works, I can’t draw anything sensible or tell. In fact, I did this project with only basic knowledge of electricity and just experimenting with components. I ask you to be very careful about working with electricity. And, if you feel a lack of knowledge in this area, I suggest at least a little understanding of this.

Here is a list of components that I used in my project.


I participate in the Amazon affiliate program, so the links above are provided. If you go through them and buy something, I will earn a little.

After I got all the components I need, it's time to do some research. The following is a list of resources that helped me correctly connect electronic components and understand the main points regarding their functioning:


Here's a diagram of the Raspberry Pi's GPIO ports.


Raspberry Pi GPIO Port Diagram

Connect a relay to the Raspberry Pi


I started by connecting a relay to the Raspberry Pi. Here is how it looks.


Connecting the relay to the Raspberry Pi The

red wire (Female-Female) goes from the pin of the JD_VCC relay board to the 5V pin (pin No. 2) of the Raspberry Pi. An orange wire (Female-Female) leads from the pin of the VCC relay board to the 3.3V pin (pin No. 1) of the Raspberry Pi.


Pins JD_VCC and VCC of the relay board

Using these wires, we supply power to the relay board. In order to be able to control individual relays, you need to connect the relay board and the Raspberry Pi with two more wires that connect to the GND and IN1 pins of the relay board.


The GND pins and IN1 of the relay board The

Female (Female) Female wire is the ground cable that connects the GND pin of the relay board and the ground terminal on the Raspberry Pi (I connected it to pin No. 34). A white wire (Female-Female) leads from pin IN1 of the relay board to pin No. 12 of the Raspberry Pi. It is this white wire that allows us to programmatically control the relay, turning on and off the individual relays located on the board.


Black and white wires connected to the Raspberry Pi

If you decide to reproduce my project, you can arrange the relay and Raspberry Pi to communicate using any suitable pins. But keep in mind that if the connection diagram of the components of your project is different from the connection diagram of the components of my project, you will have to make the appropriate changes to my code.

Connecting the power supply to the relay


After I connected the relay board to the Raspberry Pi, I connected the power supply to one of the relays.

Do not plug the power supply into a power outlet until you have completed all of the system component collection operations. Be aware of the risk of electric shock.


Connecting the power supply to one of the relays The

12V power supply used by me comes with an adapter to which it is convenient to connect the connecting wires. I connected the red wire (Male-Male) to the adapter “+” connector, and the brown cable (Male-Male) to the adapter “-” connector. Then I connected the cable with the “Crocodile” (Female-Male) connector to the brown wire.


Adapter that comes with the power supply

The relay board has four separate relays. Each of them has three pins to which cables can be connected. In the center of each relay is a connector to which the positive output of an external power source is connected. On the left is the connector to which the positive input of the device to which power is to be connected is connected.


Connecting a separate relay

I connected a red cable from the power supply (positive terminal) to the central contact of the relay. Then I connected the orange cable (Male-Male) to the left connector of the relay and connected the cable with the “crocodile” (Female-Male) to this cable.


Red and orange cables


Power supply and adapter


Relay and Raspberry Pi

Connecting a water pump to a relay


Now it remains only to connect the connectors “crocodiles” to the water pump. The order of their connection determines the direction of the water flow.

So, I needed water to enter the left channel of the pump and exit the right channel. Therefore, I connected the “crocodile” connector of the black wire to the pump terminal, near which there is a red dot, and the other “crocodile” to the other pump terminal. If I connected the “crocodiles” in a different order - the water would go in the opposite direction - from the right channel to the left.


Connecting a water pump to a relay


Complete irrigation system: water enters the pump through the left channel, leaves the right and goes to the plant

The code


So we got to what I'm really good at. We got to the code. In order to get software working with the GPIO ports of the Raspberry Pi, I used the gpiozero library . It is easy to use, it hides a lot of low-level mechanisms from the programmer, which you usually need to understand for someone who wants to work with GPIO pins. The library is well documented.

Before writing code, you need to connect a monitor, mouse, and keyboard to your Raspberry Pi. Or you need to connect to the Raspberry Pi via SSH .

After you enter Raspberry Pi, go to the folder Desktopand create a folder there run. Create a folder in this folder classes. And in the folder, classescreate a file Hardware.py. It should have the following code:

from gpiozero import OutputDevice

class Relay(OutputDevice):
    def __init__(self, pin, active_high):
        super(Relay, self).__init__(pin, active_high)

In this file, I just declared a new class Relay, which is the descendant of the OutputDevice class .

Next, in the folder, classesI created a new file TimeKeeper.py:

import datetime

class TimeKeeper:
    def __init__(self, current_time):
        self.current_time = current_time
        self.time_last_watered = None
    
    def set_current_time(self, updated_time):
        self.current_time = updated_time

    def set_time_last_watered(self, updated_time):
        self.time_last_watered = updated_time

    @staticmethod
    def get_current_time():
        now = datetime.datetime.now()
        return now.strftime("%I:%M:%S %p")

The purpose of this class is to track the current time and the moment when the last time watering was carried out.

So, the files Hardware.pyand TimeKeeper.pyare in the folder classes. Now, outside of this folder, I create a file water_plant.py:

from classes import Hardware
from classes import TimeKeeper as TK
import schedule
import smtplib
import time
import ssl

# WATERING_TIME must be in "00:00:00 PM" format
WATERING_TIME = '11:59:50 AM'
SECONDS_TO_WATER = 10
RELAY = Hardware.Relay(12, False)
EMAIL_MESSAGES = {
    'last_watered': {
        'subject': 'Raspberry Pi: Plant Watering Time',
        'message': 'Your plant was last watered at'
    },
    'check_water_level': {
        'subject': 'Raspberry Pi: Check Water Level',
        'message': 'Check your water level!',
    }
}

def send_email(time_last_watered, subject, message):
    port = 465
    smtp_server = "smtp.gmail.com"
    FROM = TO = "YOUR_EMAIL@gmail.com"
    password = "YOUR_PASSWORD"

    complete_message = ''
    if time_last_watered == False:
        complete_message = "Subject: {}\n\n{}".format(subject, message)
    else:
        complete_message = "Subject: {}\n\n{} {}".format(subject, message, time_last_watered)
    
    context = ssl.create_default_context()
    with smtplib.SMTP_SSL(smtp_server, port, context=context) as server:
        server.login(FROM, password)
        server.sendmail(FROM, TO, complete_message)

def send_last_watered_email(time_last_watered):
    message = EMAIL_MESSAGES['last_watered']['message']
    subject = EMAIL_MESSAGES['last_watered']['subject']
    send_email(time_last_watered, subject, message)

def send_check_water_level_email():
    message = EMAIL_MESSAGES['check_water_level']['message']
    subject = EMAIL_MESSAGES['check_water_level']['subject']
    send_email(False, subject, message)

def water_plant(relay, seconds):
    relay.on()
    print("Plant is being watered!")
    time.sleep(seconds)
    print("Watering is finished!")
    relay.off()

def main():
    time_keeper = TK.TimeKeeper(TK.TimeKeeper.get_current_time())
    if(time_keeper.current_time == WATERING_TIME):
        water_plant(RELAY, SECONDS_TO_WATER)
        time_keeper.set_time_last_watered(TK.TimeKeeper.get_current_time())
        print("\nPlant was last watered at {}".format(time_keeper.time_last_watered))
        # send_last_watered_email(time_keeper.time_last_watered)

# schedule.every().friday.at("12:00").do(send_check_water_level_email)

while True:
    # schedule.run_pending()
    time.sleep(1)
    main()

Here you can change the values ​​of variables WATERING_TIMEand SECONDS_TO_WATERthose that seem suitable for you. The first variable determines what time to water the plants. The second sets the duration of watering.

In addition, I created here a mechanism for sending notifications and reminders by e-mail. Thanks to this mechanism, the owner of the irrigation system receives an email every time the system is turned on and water the plants. In addition, every Friday he receives a letter reminding him that he needs to check the supplies of irrigation water. In the code, the call of the corresponding methods is commented out, as a result, the program can work normally without settings relating to e-mail. If you want to enable these reminders, do the following:

  1. You must enter in the line FROM = TO = «YOUR_EMAIL@gmail.com»and password = «YOUR_PASSWORD»your Gmail email address and password.
  2. Uncomment the following lines:

    •  # send_last_watered_email (time_keeper.time_last_watered)
    • # schedule.every (). friday.at ("12:00"). do (send_check_water_level_email)
    • # schedule.run_pending ()
  3. You need to go here , log in to your Gmail account and turn on the switch on this page. Otherwise, when you try to send an email using Gmail, you will receive an error message. 

In addition, it’s important to note that my reminder system only works with Gmail accounts.

Now that everything is ready for work, you should get the following structure of files and folders:

run
├── classes
│ ├── Hardware.py
│ └── TimeKeeper.py
└── water_plant.py

A folder runcan actually be placed anywhere. I decided to leave it in the folder Desktop.

I was not attracted by the prospect of connecting to the Raspberry Pi every time I had to start it water_plant.py. I would like this script to run automatically when Raspberry Pi is turned on. This, for example, would make it easy to turn off the system, move it to another place, turn it on, and not have to worry about anything. In order to implement this attractive scenario, we need a team crontab.

Open the terminal window on the Raspberry Pi and enter the following command:

sudo crontab -e

In response to it, the system should output something resembling that shown in the following figure.


Configuring cron tasks

Add the following line to this file:

@reboot python3 /home/pi/Desktop/run/water_plant.py

Then this file must be saved using the key combination Ctrl+Xby entering Yand pressing Enter.

In the above line, we give the Raspberry Pi the following instructions: "Every time you reboot, run the file water_plant.pylocated in the folder runthat is in the folder Desktop." If your folder runis located in a different way, edit this command accordingly.

Summary


View the project code here . If you want, you can immediately clone your repository with this command:

git clone https://github.com/AlanConstantino/rpi-plant-project.git

That's all! Now you know how to create an automated irrigation system for indoor plants based on the Raspberry Pi. She knows how to water plants every 24 hours and can send her owner email notifications and reminders.

Dear readers! How would you go about developing a home automated plant watering system?


All Articles