[Перевод] Raspberry Pi, Python и полив комнатных растений

У меня не складываются отношения с комнатными растениями. Дело в том, что я забываю их поливать. Зная это, я начал размышлять о том, что кто-то, наверняка, уже нашёл способ автоматизации полива. Как оказалось, способов таких существует очень много. А именно, речь идёт о решениях, основанных на Arduino или на Raspberry Pi. В этом материале я хочу рассказать о том, как создал систему, основанную на Raspberry Pi и Python, предназначенную для автоматизации полива растений.

ylyff31evrdtianmwk_5stnbgf4.jpeg

Компоненты и полезные ресурсы


Мне сразу хотелось бы отметить, что я вовсе не являюсь экспертом в электронике. Если меня попросят нарисовать электрическую схему, или подробно рассказать о том, как, работает какой-нибудь электронный компонент, я ничего толкового нарисовать или рассказать не смогу. На самом деле, я сделал этот проект, обладая лишь базовыми знаниями об электричестве и просто экспериментируя с компонентами. Прошу вас очень осторожно относиться к работе с электричеством. А, если вы чувствуете недостаток знаний в этой области, предлагаю хотя бы немного в этом разобраться.

Вот список компонентов, которые я использовал в своём проекте.


Я участвую в партнёрской программе Amazon, поэтому выше приведены соответствующие ссылки. Если вы, перейдя по ним, что-нибудь купите, я немного заработаю.

После того, как я раздобыл все необходимые мне компоненты, пришло время заняться некоторыми изысканиями. Ниже приведён список ресурсов, которые помогли мне правильно соединить электронные компоненты и понять основные моменты, касающиеся их функционирования:


Вот схема GPIO-портов Raspberry Pi.

e1e0bf981b31d01f59837b4885bc31ba.png


Схема GPIO-портов Raspberry Pi

Подключение реле к Raspberry Pi


Я начал с подключения реле к Raspberry Pi. Вот как это выглядит.

ec3cf5763b5451d4a4bf9b6da4fc4a95.jpg


Подключение реле к Raspberry Pi

Красный провод (Female-Female) идёт от пина платы реле JD_VCC к 5V-пину (контакт №2) Raspberry Pi. Оранжевый провод (Female-Female) ведёт от пина платы реле VCC к 3.3V-пину (контакт №1) Raspberry Pi.

4a617c868ef4a058c20f714a1c7b6fad.jpg


Пины JD_VCC и VCC платы реле

С помощью этих проводов мы подаём питание на плату реле. Для того чтобы получить возможность управлять отдельными реле, нужно соединить плату реле и Raspberry Pi ещё двумя проводами, которые подключаются к пинам GND и IN1 платы реле.

071ec994e83748306c3a9d35e8dc0791.jpg


Пины GND и IN1 платы реле

Чёрный провод (Female-Female) — это кабель заземления, который соединяет пин GND платы реле и контакт заземления на Raspberry Pi (я подключил его к контакту №34). Белый провод (Female-Female) ведёт от пина IN1 платы реле к контакту №12 Raspberry Pi. Именно этот белый провод позволяет нам программным способом управлять реле, включая и отключая отдельные реле, расположенные на плате.

226d5cd14bb1dd4ad3f31ae02bace405.jpg


Чёрный и белый провода, подключённые к Raspberry Pi

Если вы решите воспроизвести мой проект — вы можете организовать связь реле и Raspberry Pi, пользуясь любыми подходящими пинами. Но учитывайте, что если схема соединения компонентов вашего проекта будет отличаться от схемы соединения компонентов моего проекта — вам придётся внести соответствующие изменения в мой код.

Подключение блока питания к реле


После того, как я присоединил плату реле к Raspberry Pi, я подключил блок питания к одному из реле.

Не подключайте блок питания к розетке до тех пор, пока не завершите все операции по сбору компонентов системы. Помните о риске поражения электрическим током.

4b395ad58f4d7384efeb067ede209486.jpg


Подключение блока питания к одному из реле

Используемый мной блок питания на 12V поставляется с адаптером, к которому удобно подключать соединительные провода. Я подключил красный провод (Male-Male) к разъёму »+» адаптера, а коричневый кабель (Male-Male) — к разъёму »-» адаптера. Затем я подключил кабель с разъёмом «крокодил» (Female-Male) к коричневому проводу.

0fcfaff7f05b281f5cc23e73bf66fcc6.jpg


Адаптер, который поставляется с блоком питания

На плате реле имеется четыре отдельных реле. У каждого из них есть три контакта, к которым можно подключать кабели. В центре каждого реле находится разъём, к которому подключают положительный вывод внешнего источника питания. Слева находится разъём, к которому подключают положительный вход устройства, на которое нужно подавать питание.

c64ecddca0322384223dc85d0e397526.jpg


Подключение отдельного реле

Я подключил красный кабель от блока питания (положительный вывод) к центральному контакту реле. Затем я подключил оранжевый кабель (Male-Male) к левому разъёму реле и подключил к этому кабелю кабель с «крокодилом» (Female-Male).

3f77eea36c73477d3e50dbfcb4148c21.jpg


Красный и оранжевый кабели

ff39e36b9e57544b8167c24d5d2d773f.jpg


Блок питания и адаптер

98d38d875d52addfa9d57b245b61ce2c.jpg


Реле и Raspberry Pi

Подключение водяного насоса к реле


Теперь осталось лишь подключить разъёмы «крокодилы» к водяному насосу. Порядок их подключения определяет направление тока воды.

Так, мне нужно было, чтобы вода поступала бы в левый канал насоса и выходила бы из правого канала. Поэтому я подключил разъём «крокодил» чёрного провода к выводу насоса, около которого имеется красная точка, а другой «крокодил» — к другому выводу насоса. Если бы я подключил «крокодилы» в другом порядке — вода пошла бы в обратном направлении — из правого канала в левый.

059a2fbc0b0267b29ec9800fc13405f2.jpg


Подключение водяного насоса к реле

84b75596b0b1ad9d0277e58e2ddd06fa.jpg


Система полива в сборе: вода поступает в насос через левый канал, выходит из правого и идёт к растению

Код


Вот мы и добрались до того, в чём я по-настоящему хорош. Мы дошли до кода. Для того чтобы наладить программную работу с GPIO-портами Raspberry Pi, я использовал библиотеку gpiozero. Пользоваться ей легко, она скрывает от программиста массу низкоуровневых механизмов, с которыми обычно нужно разобраться тому, кто хочет работать с GPIO-пинами. Библиотека хорошо документирована.

Прежде чем заниматься написанием кода, к Raspberry Pi нужно подключить монитор, мышь и клавиатуру. Или нужно подключиться к Raspberry Pi по SSH.

После того, как вы войдёте в Raspberry Pi, перейдите к папке Desktop и создайте там папку run. В этой папке создайте папку classes. А в папке classes создайте файл Hardware.py. В нём должен быть следующий код:

from gpiozero import OutputDevice

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


В этом файле я всего лишь объявил новый класс Relay, который является наследником класса OutputDevice.

Далее, в папке classes я создал новый файл 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")


Цель этого класса заключается в отслеживании текущего времени и того момента, когда в прошлый раз выполнялся полив.

Итак, файлы Hardware.py и TimeKeeper.py находятся в папке classes. Теперь я, за пределами этой папки, создаю файл 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()


Тут можно поменять значения переменных WATERING_TIME и SECONDS_TO_WATER на те, которые кажутся вам подходящими. Первая переменная определяет то, в какое время нужно поливать растения. Вторая задаёт длительность полива.

Кроме того, я создал тут механизм рассылки уведомлений и напоминаний по электронной почте. Благодаря этому механизму владелец системы полива получает электронное письмо каждый раз, когда система включается и поливает растения. Кроме того, каждую пятницу он получает письмо с напоминанием о том, что ему нужно проверить запасы поливочной воды. В коде вызов соответствующих методов закомментирован, в результате программа может нормально работать и без настроек, касающихся электронной почты. Если вы хотите эти напоминания включить — надо сделать следующее:

  1. Надо ввести в строки FROM = TO = «YOUR_EMAIL@gmail.com» и password = «YOUR_PASSWORD» ваш адрес электронной почты Gmail и пароль.
  2. Нужно раскомментировать следующие строки:
    •  # 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. Нужно перейти сюда, войти в учётную запись Gmail и включить переключатель, имеющийся на данной странице. В противном случае при попытке отправить письмо с использованием Gmail вы получите сообщение об ошибке. 


Кроме того, тут важно отметить, что моя система напоминаний работает только с учётными записями Gmail.

Теперь, когда всё готово к работе, у вас должна получиться следующая структура файлов и папок:

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


Папку run можно, на самом деле, разместить где угодно. Я решил оставить её в папке Desktop.

Меня не прельщала перспектива подключаться к Raspberry Pi каждый раз, когда надо было запустить water_plant.py. Мне хотелось, чтобы этот скрипт запускался бы автоматически при включении Raspberry Pi. Это, например, позволило бы легко отключить систему, перенести её в другое место, включить, и уже ни о чём не беспокоиться. Для того чтобы реализовать этот привлекательный сценарий, нам понадобится команда crontab.

Откроем на Raspberry Pi окно терминала и введём следующую команду:

sudo crontab -e


В ответ на неё система должна вывести нечто, напоминающее то, что изображено на следующем рисунке.

ca03cdf45a0400ea64b5e163357e9079.png


Настройка задач cron

В этот файл нужно добавить следующую строчку:

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


Затем этот файл надо сохранить, воспользовавшись комбинацией клавиш Ctrl+X, введя Y и нажав Enter.

Вышеописанной строкой мы даём Raspberry Pi следующие инструкции: «Каждый раз, когда ты перезагружаешься, запускай файл water_plant.py, находящийся в папке run, котораях находится в папке Desktop». Если у вас папка run находится по другому пути — отредактируйте соответствующим образом эту команду.

Итоги


Посмотреть код проекта можно здесь. Если хотите — можете сразу клонировать себе репозиторий такой командой:

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


Вот и всё! Теперь вы знаете о том, как создать систему автоматизированного полива комнатных растений, основанную на Raspberry Pi. Она умеет поливать растения каждые 24 часа и может отправлять своему владельцу уведомления и напоминания по электронной почте.

Уважаемые читатели! Как бы вы подошли к разработке домашней автоматизированной системы полива растений?

iqfib45pgphfrxv--zfemt0qnmw.jpeg

© Habrahabr.ru