水やりを自動化して、ポトスを元気にする

#ポトスにお水をあげなくちゃ:seedling:
私の部屋には、毎日つかれた心をいやしてくれる「ポトス」がいます。
今年の5月に100均で購入し、可愛がっていたら、
ぐんぐん育ってくれて…

とにかく、かわいいんです！
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628696/17c2fc9a-38d0-74ee-b8fc-16b6a002aaf1.jpeg" width=600>

2、3日に1度、水やりをやっているのですが、
年に数回、地元へ帰省することがあり、
毎回7〜9日間ほど家をあけることがあります。

家を空けている期間は誰も水やりができないので、
このままでは、大切なポトスが苦しんでしまいます。

.

そんなわけで今回は、大切な観葉植物を毎日元気にするために、
RaspberryPiの工作を通して学んだ知識を活かして
水やりの自動化に挑戦していきました。

#完成イメージ
指定した時間に水やりをして、観葉植物の状態を撮影、
LINEに実行通知と画像を送信するプログラムを動かします。
<iframe width="560" height="315" src="https://www.youtube.com/embed/Q3NExUxZR1Y" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

#材料

- Raspberry Pi 3 B+
- [小型水中ポンプ DC5V](https://www.amazon.co.jp/gp/product/B07FFSK5GM/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1)
- [WEBカメラ](https://www.amazon.co.jp/%E3%83%AD%E3%82%B8%E3%82%AF%E3%83%BC%E3%83%AB-%E3%82%A6%E3%82%A7%E3%83%96%E3%82%AB%E3%83%A1%E3%83%A9-C270n-%E3%82%B9%E3%83%88%E3%83%AA%E3%83%BC%E3%83%9F%E3%83%B3%E3%82%B0-2%E5%B9%B4%E9%96%93%E3%83%A1%E3%83%BC%E3%82%AB%E3%83%BC%E4%BF%9D%E8%A8%BC/dp/B07QMKND9M/ref=sr_1_5?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=5WIYMRBLRIGB&keywords=web%E3%82%AB%E3%83%A1%E3%83%A9&qid=1639904068&sprefix=we%2Caps%2C2309&sr=8-5)
- チューブ（小型水中ポンプの吐き出し口の径に合うもの）
- 水を貯めるもの

#環境

- PC:MacBook Pro2017(macOS Big Sur_Ver11.6.1)
- エディタ:Atom（Ver1.58.0）
- VNC Viewer(Ver6.20.529)
- -raspbian
    - No LSB modules are available.
    - Distributor ID: Raspbian
    - Description:    Raspbian GNU/Linux 10 (buster)
    - Release:        10
    - Codename:       buster
- Python:3.7.3

Atomを用いてリモートでRaspberryPiへアクセスする方法を過去に紹介しています。
作業性が良いので、ぜひ参考にしていただけたらと思います。
↓ ↓ ↓
[RaspberryPi内のPythonファイルをAtomのリモート機能で編集したら最高だった](https://qiita.com/G-san/items/833c2b0e92e9c0b9dfa2)


#手順
ラズパイのOSインストール、環境設定等に関する説明は割愛します。

なので、環境構築ができている前提で進めていきます。


##ポンプ制御
ポンプはUSB電源に接続すると、モータが駆動する仕様になっています。
RaspberryPiのUSBポートは常時通電しているので、
繋げたままだと無限給水してしまいます。

USBポートの電源をON、OFF制御できるようにしましょう。

.

まずは、USBを制御するためのhub-ctrlを導入します。

```console:terminal
ターミナルに下記を入力

$ sudo apt-get install libusb-dev
$ wget http://www.gniibe.org/oitoite/ac-power-control-by-USB-hub/hub-ctrl.c
$ gcc -O2 hub-ctrl.c -o hub-ctrl-armhf-static -lusb -static
$ sudo cp hub-ctrl-armhf-static /usr/local/bin/hub-ctrl
```

```python:watering.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import time
import datetime
import os

# USB-ON
def USB_ON():
    print("USB-ON")
    os.system("sudo hub-ctrl -b 1 -d 2 -P 2 -p 1")
    return

# USB-OFF
def USB_OFF():
    print("USB-OFF")
    os.system("sudo hub-ctrl -b 1 -d 2 -P 2 -p 0")
    return

# 実行関数
def job():
    now_time = datetime.datetime.now()
    print("現在時刻 : ", now_time)

    # ON
    USB_ON()
    time.sleep(5)
   
    # OFF
    USB_OFF()
```

指定したUSBポートに対するON_OFF制御はできないみたいなので、
ON_OFFの切り替えは、全ポート行われます。

ちなみに、os.system("sudo hub-ctrl -b...の末尾の数字が、
1でON、0でOFFに切り替わります。

##Line通知＋定期実行
過去に投稿した記事を参考に、Lineへの通知処理を実行します。
Lineのアクセストークンが必要になるので、
その取得方法等は下記のリンクをご参照ください。
↓ ↓ ↓
[RaspberryPiを使って、インターホンを押すとLINEに通知が行く仕組みを1からつくってみた](https://qiita.com/G-san/items/a5977968ac1c708d0fe0)

また、下記の例だと20秒に一度の定期実行を行います。
定期実行はscheduleモジュールを使って実行できます。

```python:watering.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import time
import datetime
import os
import requests


# USB-ON
def USB_ON():
    print("USB-ON")
    os.system("sudo hub-ctrl -b 1 -d 2 -P 2 -p 1")
    return

# USB-OFF
def USB_OFF():
    print("USB-OFF")
    os.system("sudo hub-ctrl -b 1 -d 2 -P 2 -p 0")
    return

# Line通知
def Line_notify(message,sP_ID,s_ID):
    payload = {
    'message':message,
    'stickerPackageId': sP_ID,
    'stickerId': s_ID}
    headers = {'Authorization': 'Bearer ' + '発行したアクセストークンをここに書きます' }
    res = requests.post('https://notify-api.line.me/api/notify', data=payload, headers=headers)
    print(res)


# 実行関数
def job():
    now_time = datetime.datetime.now()
    print("現在時刻 : ", now_time)

    message = '\n\n水やりしたから、ヨシ！'
    sP_ID = 11538
    s_ID = 51626496

    # ON
    USB_ON()
    time.sleep(2)
    img = ShotPicture()
    Line_notify(message,sP_ID,s_ID)

    # OFF
    USB_OFF()
    os.remove(img)

# Test
schedule.every(20).seconds.do(job)

try:
    while True:
        schedule.run_pending()
        time.sleep(1)

except:
    USB_OFF()
    message = '\n\nなんかエラーが発生したっぽいけど、ヨシ！'
    sP_ID = 11538
    s_ID = 51626515
    Line_notify(message,sP_ID,s_ID)
```

実行すると、下記のようにLineへ通知が来ます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628696/55067e14-4719-84e6-cd75-485d4c4e76d4.png" width=600>

##撮影・画像送信
WEBカメラでポトスを撮影して、Lineに送信します。

WEBカメラで撮影する前に、OpenCVの環境を構築を実施。
この環境構築なのですが、上手くできていないとプログラムを実行した際に、
下記のようにエラーが出力されてしまいます。

私は、このエラー解決にもっとも時間がかかったので、
備忘のため、記事を残します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628696/338a8f41-aee3-e03e-f6ce-d242f19b661e.png" width=800>

最終的には、下記の記事を参考に、
記事の最下部まで試してやっと環境構築ができました。
↓ ↓ ↓
[【Raspberry Pi】Raspberry Pi Zero WにOpenCVの環境を構築する](https://rikoubou.hatenablog.com/entry/2019/05/21/151337)

撮影・画像送信を追加した水やりプログラムはこちら

```python:watering.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import time
import datetime
import os
import schedule
import requests
import cv2
from PIL import Image


# USB-ON
def USB_ON():
    print("USB-ON")
    os.system("sudo hub-ctrl -b 1 -d 2 -P 2 -p 1")
    return

# USB-OFF
def USB_OFF():
    print("USB-OFF")
    os.system("sudo hub-ctrl -b 1 -d 2 -P 2 -p 0")
    return

# Line通知
def Line_notify(message,sP_ID,s_ID,img):
    payload = {
    'message':message,
    'stickerPackageId': sP_ID,
    'stickerId': s_ID}
    files = {'imageFile':open(img, 'rb')}
    headers = {'Authorization': 'Bearer ' + '発行したアクセストークン' }
    res = requests.post('https://notify-api.line.me/api/notify', data=payload, headers=headers, files=files)
    print(res)

# カメラ撮影関数
def ShotPicture():
    Image_dir = "/home/pi/Desktop/"
    now = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
    file_name = now + '.jpg'
    cc = cv2.VideoCapture(0)
    ret, img = cc.read()
    cv2.imwrite(file_name, img)

    img = Image_dir + file_name
    cc.release()

    return(img)


# 実行関数
def job():
    now_time = datetime.datetime.now()
    print("現在時刻 : ", now_time)

    message = '\n\n水やりしたから、ヨシ！'
    sP_ID = 11538
    s_ID = 51626496

    # ON
    USB_ON()
    time.sleep(3)
    img = ShotPicture()
    Line_notify(message,sP_ID,s_ID,img)

    # OFF
    USB_OFF()
    os.remove(img)

# Test
schedule.every(20).seconds.do(job)
# Production
# schedule.every().day.at("07:00").do(job)

try:
    while True:
        schedule.run_pending()
        time.sleep(1)

except:
    USB_OFF()
    message = '\n\nなんかエラーが発生したっぽいけど、ヨシ！'
    sP_ID = None
    s_ID = None
    img = '/home/pi/Desktop/main.png'
    Line_notify(message,sP_ID,s_ID,img)

```
ShotPicture()で定義している部分で撮影の処理を行います。


このソースを実行させた結果がこちら。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628696/40f76adc-96d2-3a24-0d81-d11d6282fb35.png" width=600>
テスト動作で水やりをさせていませんが、ヨシですね！

.

ちなみに、エラーが発生するとこうなります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628696/e9ebd6e2-9fd3-f1a5-5625-2c791966770c.png" width=600>

except節で定義している、デスクトップ上の画像を選択して送信させています。
また、水やり中にエラーが発生し、無限給水をしてしまわないように、
USB給電をOFFにする処理を実行させるようにします。

これでヨシですね。（たぶん）

##自動実行
過去にスケジューリングをするならsystemdがいいと聞いたので、
自動実行をするために、shellスクリプトとserviceファイル作成、
権限付与などの処理を行います。

こちらも、過去に投稿した記事がありますので
詳しくはこちらからどうぞ
↓ ↓ ↓
[Raspberry Piでプログラムの自動起動をsystemdでやってみた](https://qiita.com/G-san/items/b0f9a340601cdb4a068f)

.

これで、自動水やりプログラムは完成です！

##たのしい工作

といっても、WEBカメラ、水中ポンプ、USBライトをRaspberryPiに差し込むだけ。

でおわる予定だったのですが、
USBライトはタッチセンサーのスイッチを押さないと点灯しない
仕様なので、ちょっとだけひと手間加わえます。

通電時に電源をONにしたいけど、どうしよう…

.

よし、考えるのはあとだ！！　　分解！！

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628696/1a6af538-2ad4-a345-3705-60be5ef5819a.jpeg" width=600>

電子部品に関することは詳しくわからないのですが、
おそらく、タッチセンサーの信号をオペアンプで増幅させて、
抵抗の大きさが異なる回路に切り替えているのかなと思います
（間違っていたらごめんなさい…）

なんとなく、ICの部分を短絡させればいけるかなと思い、検証してみます。

.

すると画像の部分を短絡させることによって、
電源ONのときにLEDが点灯することに成功！

その辺に落ちてた配線をはんだ付けするだけで終了です。

もし、配線がない場合は、
緑色の配線（乾電池からの電源供給）を拝借しましょう。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628696/4db058eb-3a1e-9b7f-612a-6308accdf13d.jpeg" width=600>

小さい基盤ようのはんだごてを持っていないので、
配線を焦がしてしまったことは見逃してください。

##完成品
あとは、組み立て、いい感じに配線したら完成です。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628696/a06cf7f5-0d91-7d3c-0e00-c4714e642e81.jpeg" width=600>


#参考記事

- [USB電源制御](https://pcvogel.sarakura.net/2017/11/06/31777)
- [RaspberryPiからスマホのLINEに画像を送信する方法](https://mayumega.site/raspi/raspi_line_pic/)
- [PythonでLINEにメッセージを送る](https://qiita.com/moriita/items/5b199ac6b14ceaa4f7c9)
- [【Python】scheduleを使ってモジュールを定期実行させよう](https://qiita.com/dgkmtu/items/3bd3794b44a0aa03bfe3)

#終わりに
まめコーヒーアドベントカレンダーの記事を書くネタを考える時期が、
たまたま帰省前だったので、こんな記事になってしましました。

この文章を書いている時に、コーヒーネタでもよかったなーと…

ポンプがあるなら、なんちゃってドリップマシンでもつくれたかもしれないですね。
来年のアドベントカレンダーのネタに取っておこうと思います。
（忘れているかもしれないけど）

.

最後まで見ていただきありがとうございました！！