Raspberry Pi 3 Model B+で土壌水分センサー開発してみた

こんにちは。加藤です。
 
私は社内の植物を管理する「植物図鑑」という役割を担っています。そこで植物の水やりのタイミングが人によって違い、仕組み化できていないと感じていました。
 
というわけで、Raspberryと土壌水分センサーを用いて、土の乾燥具合で水やりのタイミングが分かる装置を制作しました。
 
今回はラズパイ初心者の方向けに、形として動くものを紹介させていただきます。

環境

今回は以下の環境・ハードウェアを使用しました。

言語
Python
OS
Raspberry Pi OS
PC
Raspberry Pi 3 Model B+
センサー
静電容量式土壌水分センサー基板
モジュール
静電容量式土壌湿度モジュール(PCF8591)
その他
LED発光ダイオード・抵抗・ブレッドボード・ジャンパワイヤー

機能概要

大まかに以下のような機能を実装しました。

土壌水分センサーで土の水分値を測るように命令/値を取得する
任意の時間に測定のバッチ処理が走る
乾燥状態および異常値の場合にLEDが点灯する

水分の閾値ですが、乾燥していると数値が小さく、湿潤だと大きい数値が返却されます。制作過程で3種類ほど土壌水分センサー基板・モジュールを試してみましたが、製品や土の状態によって若干数値が異なりました。
 
今回私が使用したPCF8591では、65前後で乾燥、100前後で湿潤という結果になりました。
 
実操作する際の閾値の決定は、乾燥・湿潤の状態をあらかじめ測定してから実装した方が良さそうです。

処理の流れ

実際の処理の流れは以下のようになっています。

① 定期バッチを実行
② 水分値取得の命令
③ 水分値をアナログ電圧値で送信
④ 水分値をデジタル信号で送信
⑤ LEDを光らせる命令

配線

配線はこのようになっています。複雑にはなりますが、ひとつひとつのPINの役割を理解しながら挿していくと理解が深まります。

ラズパイ PCF8591
5V(2番) VCC
GND(6番) GND
GPIO 2(3番) SCL
GPIO 3(5番) SDA
ラズパイ 土壌水分センサー基板
GND(14番) -(マイナス)
5V(4番) +(プラス)
PCF8591 土壌水分センサー基板
AIN2 AOUT
ラズパイ ブレッドボード
GPIO 27(13番) a-1
GND(30番) e-11
GPIO 17(11番) a-20
GND(34番) e-29

注意点ですが、配線作業はラズパイの電源を切ってから行いましょう。理由はラズパイはそこまで頑丈ではないので、場合によってはショートする恐れがあるためです。特に、今回使用したラズパイの2番・4番のGPIOピンは電気の入出力を行っている部分です。
 
また今回は5Vを使用しましたが、同じ理由から、まずは3.3Vの少ない電圧から始めることをオススメします。

コード

最後にコードの内容です。今回は以下の4つを記載しました。コードをそのまま貼り付けるだけで実装できます。
crontab…バッチ処理を記載

*/10 ****/user/bin/python3 /home/xxx/solid.py

DEFAULT.ini…水分の閾値を記載
[DEFAULT]
MIN = 0
MAX = 150

WET_MAX = 64
OPTIMAL_MIN = 65
OPTIMAL_MAX = 90
DRY_MIN = 91

PCF8591.py…土壌水分モジュールが実行する内容
import smbus

PCF8591_ADDRESS = 0x48

bus = smbus.SMBus(1)

def setup(address):
    global PCF8591_ADDRESS
    PCF8591_ADDRESS = address
    
def read(channel):
    
    if channel  3:
        return None
    
    bus.write_byte(PCF8591_ADDRESS, 0x42 | channel)
    
    #ダミー呼び出し
    bus.read_byte(PCF8591_ADDRESS)
    value = bus.read_byte(PCF8591_ADDRESS)
    
    return value

solid.py…水分値を判定しLED点灯/消灯の制御をする
import RPi.GPIO as GPIO
import PCF8591 as ADC
import configparser
import time

config_ini = configparser.ConfigParser()
config_ini.read('DEFAULT.ini')

ADC.setup(0x48)

GPIO.setmode(GPIO.BOARD)
GPIO.setup(11, GPIO.OUT)
GPIO.setup(13, GPIO.OUT)

value = ADC.read(0)

min_val = int(config_ini['DEFAULT']['MIN'])
max_val = int(config_ini['DEFAULT']['MAX'])

wet_max = int(config_ini['DEFAULT']['WET_MAX'])
opt_min = int(config_ini['DEFAULT']['OPTIMAL_MIN'])
opt_max = int(config_ini['DEFAULT']['OPTIMAL_MAX'])
dry_min = int(config_ini['DEFAULT']['DRY_MIN'])

try:
    if value  max_val:
        print("異常")
        print(ADC.read(0))
        GPIO.output(11, GPIO.HIGH)
        GPIO.output(13, GPIO.LOW)
        time.sleep(60)

    elif value <= wet_max:
        print("過湿")
        print(ADC.read(0))
        GPIO.output(11, GPIO.LOW)
        GPIO.output(13, GPIO.LOW)

    elif opt_min <= value <= opt_max:
        print("良好")
        print(ADC.read(0))
        GPIO.output(11, GPIO.LOW)
        GPIO.output(13, GPIO.LOW)

    else:
        print("乾燥")
        print(ADC.read(0))
        GPIO.output(11, GPIO.LOW)
        GPIO.output(13, GPIO.HIGH)
        time.sleep(60)

except KeyboardInterrupt:
    print("Exit")
    
finally:
    # キーボード操作で起動
    GPIO.output(11, GPIO.LOW)
    GPIO.output(13, GPIO.LOW)
    GPIO.cleanup()

反省点

実装している中で気が付いてしまったのですが、今回のようなIoT機器の実装では「Raspberry Pi 3 Model B+」ではオーバースペックでした。
 
「Raspberry Pi 3 Model B+」でも実装できますが、WEBサーバーを利用したり、データベースを用いてデータの保存をするような時に使用するものでした。
 
そのためこういったシンプルなIoT開発では、「RaspberryPi Pico」を使用することが多いそうです。ですが、将来的に水分値の平均をとってDBに保存しその値を元にした判定したり、LEDではなくLINEのAPIでの通知などできるといいなと考えていたので、結果オーライということにしたいと思います。

まとめ

いかがでしょうか。
 
ハードウェア用いた開発は初めてだったため、完成するまでには時間を要してしまいました。ですが、コンピュータ構成や電気の知識など大変勉強になりました。IN/OUTの概念はWEBアプリケーションも同じなので、ぜひ応用として作ってみてはいかがでしょうか。
 
 
 
 
《関連記事》

Raspberry Pi × Wiring Pi でクリスマスツリーを作ってみた【準備編】
技術
2015.12.7(Mon)

Raspberry Pi × Wiring Pi でクリスマスツリーを作ってみた【準備編】

#IoT

Raspberry Pi × Wiring Pi でクリスマスツリーを作ってみた【完成編】
技術
2015.12.8(Tue)

Raspberry Pi × Wiring Pi でクリスマスツリーを作ってみた【完成編】

#IoT

記事をシェア
MOST VIEWED ARTICLES