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アプリケーションも同じなので、ぜひ応用として作ってみてはいかがでしょうか。
《関連記事》

