自動植物水やり・灌漑システム:回路設計、コード、プロジェクト報告書
自動植物水やりシステム ─ 完全ソースコード、回路図、プロジェクト報告書 ─ PDFダウンロード
はじめに
植物の水やりは日常業務の中で最も重要な栽培作業であり、同時に最も労力を要する作業です。猛暑・極寒、乾燥・多湿を問わず、植物に到達する水量を適切に制御することは極めて重要です。そこで、植物が必要な時に必要な分だけ水やりを行う自動植物水やりシステムの導入が効果的です。本プロジェクトの重要なポイントは「いつ、どれだけ水をやるか」です。人の手作業による水やりを減らすため、土壌水分レベルを継続的に監視し、水やりの要否と必要水量を判断するシステムを構築します。本システムは、電源、リレー、電磁弁、Arduino GSMシールド、土壌水分センサー、LCDといったサブシステムで構成されます。

本システムは、土壌水分センサーが特定時点で植物の水分レベルを検知し、それが植物ごとに設定された閾値を下回った場合、所定量の水を供給し、水分レベルが閾値に達するまで継続するよう設計・プログラミングされています。
システムは現在の状態を報告し、水やりのリマインダーやタンクへの給水通知を送信します。これらすべての通知はArduino GSMシールドで実現します。
関連プロジェクト:雨水・雪・水検知アラーム回路
プロジェクトの目的
高度な技術とエレクトロニクスの時代において、人の生活はよりスマートで、シンプルで、便利であるべきです。そのため、日常業務を軽減する自動化システムが数多く求められています。ここで提案する自動植物水やりシステムは、特に外出時に植物の水やりで困っている多くの人々に役立つものです。センサー技術とマイクロコントローラーを用いたスマートな切替装置で、何百万人もの人々を支援します。
最も基本的な形では、土壌水分センサーが特定時点で植物の水分レベルを検知し、閾値(植物ごとに事前設定)を下回った場合、水分レベルが閾値に達するまで所定量の水を供給します。システムには温湿度センサーも搭載され、周囲の環境を把握して水やりの判断に反映させます。電磁弁で水流を制御し、Arduinoが水分センサーの値を読み取って所定条件で電磁弁を駆動します。さらに、システム状態の報告、水やりリマインダーの送信、ユーザーからのSMS受信も、Arduino GSMシールドで実現します。
関連プロジェクト:水位表示回路図 ─ 2つのシンプルなプロジェクト

システムの背景
理科の教科書で学ぶ通り、植物は酸素を供給し環境を浄化する上で人類にとって不可欠です。自動植物水やりシステムは、日常品が先端技術と接続されるにつれ、家庭から産業レベルまで急速に普及しています。これらのシステムの主なメリットは効率性と使いやすさです。
植物水やりシステムにより、植物愛好家は外出中も自宅の植物を管理できます。効率的で信頼性の高い各種センサー技術を活用することで実現しています。
必要な自動化レベルに応じて、いくつかの種類の室内植物水やりシステムがあります。
- 植物水やりグローブとスパイク
- 室内点滴水やりシステム
- センサー技術
- 温湿度センサー
- 温度センサー
- 湿度センサー
- 土壌水分センサー
- バイメタルサーモスタット
- サーミスタ
- 測温抵抗体(RTD)
- 熱電対
- センサーIC、LM35
- デジタル温度センサー(ADT7301)
- DHT11とDHT22
- GSMモジュール
- GSMアーキテクチャ
- リレー
- トランジスタ
- 日立16×2 LCD
関連プロジェクト:ATMegaマイクロコントローラーとは? LEDプロジェクトの作り方
製品・コンポーネント仕様
| 要件ID | SRS-GSM-001 |
|---|---|
| タイトル | GSMモジュール |
| 説明 | システムにGSMモジュールを含む。受信者へアラートSMSを送信し、ユーザーからSMSを受信する。 |
| バージョン | Version 1.0 |
| 要件ID | SRS-Microcontroller-001 |
|---|---|
| タイトル | ATmega328p |
| 説明 | 通常Arduino Unoに搭載されるマイクロコントローラー。センサーからの読み取りを行い、システム全体を制御する。 |
| バージョン | Version 1.0 |
| 要件ID | SRS-Temperature and Humidity-001 |
|---|---|
| タイトル | DHT11 |
| 説明 | 温湿度センサーを含む。周囲の温度・湿度を取得し、マイクロコントローラーへ送信する。 |
| バージョン | Version 1.0 |
| 要件ID | SRS-Moisture-001 |
|---|---|
| タイトル | Grove土壌水分センサー |
| 説明 | 土壌水分センサーを含む。土壌の水分を読み取り、マイクロコントローラーへ送信する。 |
| バージョン | Version 1.0 |
| 要件ID | SRS-LCD-001 |
|---|---|
| タイトル | 日立16×2 LCD |
| 説明 | ユーザーインターフェース用LCDを含む。システム内の各種センサーが取得した読み取り値を表示する。 |
| バージョン | Version 1.0 |
関連記事:Arduinoプログラミング ─ Arduinoとは? プログラミング方法
Arduinoベース自動植物水やりシステム
自動植物水やりブロック図

自動植物水やり・灌漑システム 回路図
本システムには2つの機能コンポーネントがあります:水分センサーとモーター/ウォーターポンプ。基本形では、水分センサーが土壌水分レベルを検知し、モーター/ウォーターポンプが植物に水を供給します。

上図の回路図はシステム全体の動作を示しています。Arduino Unoでモーターを制御し、Hブリッジでサーボモーターの正転・逆転をコントロールします。水分センサーが土壌水分を測定しArduinoへ信号を送ると、水やり必要と判断された場合にサーボモーターを開き、所望の水分レベルに達するまで給水します。
上図のプロトタイプでは、水分センサーが水分レベルを検知してArduinoへ信号を送り、ArduinoがHブリッジ経由でウォーターポンプを駆動し、特定の植物に水やりを行います。これはArduino IDEソフトウェアで実装されています。
関連プロジェクト:IC 4017・555タイマーを用いた信号機制御電子プロジェクト
プロジェクト設計
このセクションでは、ソフトウェア設計とハードウェア設計の完了内容、システムに含まれる要素、完全な自動植物水やりシステムを構築するために各コンポーネントが選ばれた理由について説明します。選択されたコンポーネントを用いたシステムの基本概念モデルを以下の図に示します。
上図のブロック図で示される自動植物水やりシステムの機能は以下の通りです:
- GSMモジュールを含み、受信者へSMS送信、受信者からSMS受信を行う
- 土壌水分、温度、湿度センサーを使用する
- 電磁弁と電磁弁駆動回路を含み、電磁弁を通じた水流を制御する
- 水分センサーで特定植物の水分レベルを判定。マイクロコントローラーがループ処理でセンサー値を閾値と比較し、閾値以上ならGSMモジュールが受信者へSMS送信の準備をする
- 温湿度センサーで植物にとって暑すぎるか、湿度が高すぎるかを判定。ATmega328pチップ(ATmegaとは参照)が読み取り、全電磁弁のON/OFF判断に使用する
詳細なコンポーネント情報はPDFファイル(後述)に記載。
関連プロジェクト:Raspberry Piとは? Raspberry Piを使ったプロジェクト作成
ハードウェア設計
センサー回路図
以下の図はセンサー回路の回路図です。すべてのセンサーはArduinoのアナログピンA0〜A3に接続されています。ピンA0は温湿度センサー用、ピンA1〜A3は水分センサー用に予約されています。すべてのセンサーは共通の5V電源とGNDを共有します。
LCD回路図
以下の図はLCDの回路図です。デジタルピン8〜13をLCD用に予約しています(回路図参照)。ピン1とピン3は電源とGND、ピン2はコントラスト調整用で可変抵抗器に接続します。ArduinoのデジタルピンとLCDのデータピンを正しい順序で接続しないと、LCDにガベージ文字しか表示されないので注意してください。
電磁弁回路図
以下の図は電磁弁回路の回路図です。デジタルピン4〜7を電磁弁用に予約しています。回路はリレー、トランジスタ、抵抗、LED(CadStarに電磁弁シンボルがないためLEDで代用)で構成されます。リレーは5Vで動作し、5VがリレーのNO接点にも供給されます(LEDが5V動作で220Ω抵抗を介して接続されるため)。
関連プロジェクト:音声認識ベースホームオートメーションシステム
トランジスタのベースに電圧が印加されると、トランジスタがONしてリレーコイルが励磁され、NC接点に切り替わり、該当リレーのLEDが点灯します。ベース電圧が下がるとトランジスタがOFFし、リレーコイルが消磁されてNO接点に戻り、LEDが消灯します。
すべての回路図完成後、次のステップはユニバーサル基板(ベロボード)への実装です。事前にストリップボードレイアウト計画シートで回路設計を行うことが重要です。ベロボード設計の原則は以下の通りです:
- ストリップボードレイアウト計画シートの右上に、VsとGNDの電源ラインを最初にマークする
- ICのピン間のトラックをカットすることを忘れずに。図ではカット箇所をXでマークする
- 抵抗とアキシャルコンデンサはできるだけフラットに配置する。抵抗は通常4穴、コンデンサは8穴のギャップを要する
- 可能ならICのピン番号を振る。ベロボード裏面の銅箔トラックは水平方向に電流が流れる。上記回路図の各種ベロボード設計を以下に示す
ソフトウェア設計
ハードウェア完成後、ソフトウェアでテストを行います。このセクションでは、システム内で使用される各種自動化技術のソフトウェア設計実装を詳細に説明します。Arduinoに書き込まれたArduinoコードが含まれます。
最初に、電磁弁回路の動作と、マイクロコントローラー視点での電磁弁の挙動を確認しました。このための小さなフローチャートは、上図のソフトウェアフローセクションに示されています。
Arduino IDEを使用してソフトウェアをArduinoにアップロードしました。基本的な電磁弁回路用に、1秒ごとにLEDを点滅させるシンプルなプログラムを作成しました。デジタルピン4、5、6、7を初期定義し、プログラムと回路をテストしました。プログラム実行時、すべての基本初期化を行い、void setup()で出力ピンを定義し、void loop()で常時実行・1秒ごとにLED点滅を行います。
次に、各種センサーから読み取り値を取得しLCDに表示する小さなプログラムを作成・アップロードしました。これもフローチャートを作成(上図のソフトウェアフローセクション参照)。void loop()に入ると、センサーから読み取り、基本計算を行い、LCDに表示します。
関連基礎電子プロジェクト:LDR・BC547トランジスタを用いた自動街灯制御システム
次に、GSMモジュール用ソフトウェアをArduinoにアップロードし、GSMとマイクロコントローラーの通信を確立しました。最初にモデムテストを行い、基本初期化とGSM用ライブラリ、IMEI番号取得、モデムがArduinoとの通信開始時に正常動作するかを確認しました。次にネットワーク接続テストを行い、GSMを初期化してサポートされるネットワークを表示しました。
GSMモジュールのテスト完了・正常動作確認後、受信者との通信(SMS送信・受信)に進みます。そのためのシンプルなArduino配線プログラムを作成・アップロードしました。プログラムはGSMを初期化し、受信者へSMSを送信します。一方、GSMがエンドユーザーからSMSを受信する別のArduinoプログラムも作成しました。
最後に、すべてのソフトウェア設計を統合し、システム用最終動作ソフトウェアを構築しました。上図のソフトウェアフローセクションに示す様々なアルゴリズムアプローチを適用し、最終ソフトウェアが意図通りに動作するようにしました。上図は、読み取り、SMS送信、SMS受信、そして従来の動作を繰り返す最終ソフトウェアの動作を示しています。
注: すべてのソフトウェアコードは後述の付録に記載。
注意: すべてのソフトウェアコードは付録で確認できます。モデムテストとネットワーク接続テストの出力は、実際のレポートがハードウェア提出後に作成されたため、レポートに含まれていません。
関連プロジェクト:LabVIEWで基本的な電気・電子プロジェクトを作る方法
プロジェクト構築とソフトウェアテスト
すべてのハードウェア・ソフトウェア設計が完了したら、プロジェクト構築とテストの段階に入ります。このセクションでは、各種ハードウェア設計の実装・テスト方法、ソフトウェアコード内の隠れた問題のトラブルシューティングと解決、プロジェクト成功への道筋について詳述します。ステップバイステップのプロセスは、後述のPDFフルプロジェクト報告書(構築とテスト手順)に記載されています。
ソフトウェアテスト
ソフトウェアテストフェーズもプロジェクト開発の重要な側面です。ソフトウェアテストとは、プログラムやアプリケーションを実行し、ソフトウェアバグを発見する手順です。また、ソフトウェアプログラムやアプリケーションが技術要件を満たし、期待通りに動作し、同様の特性で実行可能かを検証・妥当性確認するプロセスとも言えます。ソフトウェアテストにはさまざまなアプローチを採用しました。ソフトウェア要件仕様書(SRS)を作成し、ソフトウェアシステムの期待動作を完全に記述しました。
関連プロジェクト:555タイマーを用いた拍手スイッチ回路電子プロジェクト
| 要件ID | SRS-Sensor-010 |
|---|---|
| タイトル | センサー |
| 説明 | システム内のセンサーが読み取りを行い、マイクロコントローラーへ送信する |
| バージョン | V 1.0 |
| 要件ID | SRS-Data-020 |
|---|---|
| タイトル | データ表示 |
| 説明 | ユーザーがシステムから読み取りを取得しようとしたとき、ディスプレイにデータ(例:温湿度値に続き水分読み取り値)を表示する |
| バージョン | V1.0 |
| 要件ID | SRS-Microcontroller-030 |
|---|---|
| タイトル | マイクロコントローラー |
| 説明 | システムのブレインとして、すべてを管理する |
| バージョン | V1.0 |
| 要件ID | SRS-Latch-040 |
|---|---|
| タイトル | ラッチ |
| 説明 | マイクロコントローラーのデジタルピンを拡張する |
| バージョン | V1.0 |
| 要件ID | SRS-GSM-050 |
|---|---|
| タイトル | GSM |
| 説明 | マイクロコントローラーの指示に従い、受信者へアラートSMSを送信する |
| バージョン | V1.0 |
SRSドキュメント作成後、ソフトウェア設計は静的テストフェーズ(ドキュメントレビュー)に移行しました。ここでは要件の検証を行います。検証方法は以下の4種類です:
- 検査(I):管理的・視覚的検証
- 分析(A):分析的根拠に基づく検証
- デモンストレーション(D):定量的測定なしで運用特性を検証
- テスト(T):定量的測定による定量的特性の検証。SRSドキュメントの各要件に対し、I、A、D、Tの略称で検証方法を定義
検証
| 要件ID | 要件タイトル | 方法 |
|---|---|---|
| REQ-010 | システムのセンサーが読み取りを取得することを検証 | I |
| REQ-020 | データが画面に表示されることを検証 | D |
| REQ-030 | システムのマイクロコントローラーが適切に管理・動作し、すべての要求に100%結果を返すことを検証 | D |
| REQ-040 | ラッチ回路が意図通り動作し、3入力を受けて8出力を出すことを検証 | A |
| REQ-050 | GSMによりSMSが送信・受信されることを検証 | D |
結果
すべてのテストが満足のいく結果で完了しました。特に文書化すべき特定の結果はありません。システムは水分センサーとDHT11(温湿度)センサーで動作し、現在の室温・湿度に応じた読み取りを行います。回路内の水分センサー読み取り値も、植物の現在の水分レベルに依存します。全体として、機能面からの結果は良好で、モチベーション維持に十分でした。
関連記事:Arduino PWMプログラミングとその機能
自動植物水やり・灌漑システム 最終完全ソフトウェアコード
注: プロジェクト関連のその他コード(電磁弁テスト用サンプルコード、システムセンサーテストコード、GSMモデムテストコード、GSMネットワーク接続コード、GSM SMS送信コード、GSM SMS受信コード等)はPDFファイルに掲載。
最終自動水やり植物プロジェクトコード
#include <dht.h>
#define dht_dpin A0
dht DHT;
//———————–
#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 10, 11, 12, 13);
//———————————-
int plantPotMoisture[3] = {A1, A2, A3};
//———————
#include <GSM.h>
#define PINNUMBER ""
GSM gsmAccess;
GSM_SMS sms;
char remoteNumber[] = "0899506304";
String moistureMessage = "Moisture is Low on sensor: ";
String SMS_Alert = "Sending SMS!";
String humidityMsg = "Humidity is High. Open All Solenoids";
String tempMsg = "Temperature is too HIGH!..Open ALl Solenoids ";
String messageBuffer = "";
char senderNumber[20];
String stringOne = "Opens1";
String stringTwo = "Opens2";
String stringThree = "Opens3";
String stringFour = "OpenAll";
//—————
#define solenoidData 5
#define solenoidClockster 4
#define solenoidLatch 6
//—————
const int master = 0;
const int slave1 = 1;
const int slave2 = 2;
const int slave3 = 3;
boolean takeReadings = true;
int serialSolenoidOutput = 0;
void setup() {
pinMode(solenoidData, OUTPUT);
pinMode(solenoidClockster, OUTPUT);
pinMode(solenoidLatch, OUTPUT);
digitalWrite(solenoidLatch, HIGH);
digitalWrite(solenoidLatch, LOW);
shiftOut(solenoidData, solenoidClockster, MSBFIRST, 0);
digitalWrite(solenoidLatch, HIGH);
//————————-
Serial.begin(9600);
lcd.begin(16, 2);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Wait Until");
lcd.setCursor(0, 1);
lcd.print("GSM Initialized!");
boolean notConnected = true;
while (notConnected) {
if (gsmAccess.begin(PINNUMBER) == GSM_READY)
notConnected = false;
else {
Serial.println("Not connected");
delay(1000);
}
}
}
void loop() {
if (takeReadings) {
moistureSensor();
TempAndHumidity();
if ((DHT.humidity > 50 || DHT.temperature > 25) && takeReadings) {
takeReadings = false;
if (DHT.humidity > 50) {
sendSMS(humidityMsg);
} else if (DHT.temperature > 25) {
sendSMS(tempMsg);
}
while (!takeReadings) recieveSMS();
}
if ((plantPotMoisture[0] > 30 || plantPotMoisture[1] > 30 || plantPotMoisture[2] > 30) && takeReadings) {
takeReadings = false;
if (plantPotMoisture[0] > 30) {
sendSMS(moistureMessage + "1");
} else if (plantPotMoisture[1] > 30) {
sendSMS(moistureMessage + "2");
} else {
sendSMS(moistureMessage + "3");
}
while (!takeReadings) recieveSMS();
}
}
}
void moistureSensor() {
for (int i = 0; i < 3; i++) {
lcd.clear();
plantPotMoisture[i] = analogRead(i);
plantPotMoisture[i] = map(plantPotMoisture[i], 550, 0, 0, 100);
Serial.print("Moisture" + String(i));
lcd.print("Moisture" + String(i));
Serial.print(plantPotMoisture[i]);
lcd.print(plantPotMoisture[i]);
Serial.println("%");
lcd.print("%");
delay(1000);
}
}
void TempAndHumidity() {
DHT.read11(dht_dpin);
lcd.setCursor(0, 0);
lcd.print("Humidity=");
Serial.print("Current humidity = ");
Serial.print(DHT.humidity);
lcd.print(DHT.humidity);
lcd.print("%");
Serial.print("%");
Serial.print("temperature = ");
Serial.print(DHT.temperature);
Serial.println("C");
lcd.setCursor(0, 1);
lcd.print("temp=");
lcd.print(DHT.temperature);
lcd.print("C ");
delay(1000);
lcd.clear();
}
void sendSMS(String messageToSend) {
Serial.print("Sending a message to mobile number: ");
Serial.println(remoteNumber);
Serial.println("SENDING");
lcd.print(SMS_Alert);
Serial.println();
Serial.println("Message:");
Serial.println(messageToSend);
sms.beginSMS(remoteNumber);
sms.print(messageToSend);
sms.endSMS();
Serial.println("\nCOMPLETE!\n");
lcd.clear();
lcd.print("Completed!!!");
}
void recieveSMS() {
char c;
if (sms.available()) {
lcd.clear();
lcd.print("Message received from:");
delay(800);
lcd.clear();
sms.remoteNumber(senderNumber, 20);
lcd.print(senderNumber);
while (c = sms.read()) {
Serial.println(c);
messageBuffer += c;
}
Serial.println(messageBuffer);
if (messageBuffer == stringOne) {
toggleSolenoid1();
takeReadings = true;
} else if (messageBuffer == stringTwo) {
toggleSolenoid2();
takeReadings = true;
} else if (messageBuffer == stringThree) {
toggleSolenoid3();
takeReadings = true;
} else if (messageBuffer == stringFour) {
toggleAll();
takeReadings = true;
} else {
takeReadings = true;
}
messageBuffer = "";
Serial.println("\nEND OF MESSAGE");
sms.flush();
Serial.println("MESSAGE DELETED");
}
delay(1000);
}
void toggleSolenoid1() {
solenoidWrite(master, HIGH);
delay(1000);
solenoidWrite(slave1, HIGH);
delay(1000);
solenoidWrite(slave1, LOW);
delay(1000);
solenoidWrite(master, LOW);
delay(1000);
}
void toggleSolenoid2() {
solenoidWrite(master, HIGH);
delay(1000);
solenoidWrite(slave2, HIGH);
delay(1000);
solenoidWrite(slave2, LOW);
delay(1000);
solenoidWrite(master, LOW);
delay(1000);
}
void toggleSolenoid3() {
solenoidWrite(master, HIGH);
delay(1000);
solenoidWrite(slave3, HIGH);
delay(1000);
solenoidWrite(slave3, LOW);
delay(1000);
solenoidWrite(master, LOW);
delay(1000);
}
void toggleAll() {
solenoidWrite(master, HIGH);
delay(1000);
solenoidWrite(slave1, HIGH);
delay(1000);
solenoidWrite(slave2, HIGH);
delay(1000);
solenoidWrite(slave3, HIGH);
delay(1000);
solenoidWrite(slave1, LOW);
delay(1000);
solenoidWrite(slave2, LOW);
delay(1000);
solenoidWrite(slave3, LOW);
delay(1000);
solenoidWrite(master, LOW);
delay(1000);
}
void solenoidWrite(int pin, bool state) {
if (pin >= 0 && pin < 8) {
if (state)
serialSolenoidOutput |= (1 << pin);
else
serialSolenoidOutput &= ~(1 << pin);
}
digitalWrite(solenoidLatch, LOW);
shiftOut(solenoidData, solenoidClockster, MSBFIRST, serialSolenoidOutput);
digitalWrite(solenoidLatch, HIGH);
}
自動植物水やりシステム 完全プロジェクト報告書(PDF)無料ダウンロード
- タイトル: Automated Plant Watering System
- 形式: PDF
- サイズ: 4.18MB
- ページ数: 77
- ダウンロード: こちら
関連記事:PCB設計の手順(ステップバイステップ・画像付き)
著者について
- 工学部 情報工学科 工学研究所 ブランチャードスタウン ダブリン15
産業技術
- SERENA:Arduino Mega 2560とTFT LCDタッチスクリーン搭載カスタムアラームシステム
- Arduinoで作る全自動植物水やりシステム - 湿度センサーとRTCで最適制御
- Arduino Nanoで構築するスマートホーム植物自動水やりシステム
- Arduino駆動のスマート自動灌水システム
- スマート都市型植物自動給水システム:センサー駆動の自動水やり
- オートマチックトランスミッション(AT)完全ガイド:種類・構造・仕組み
- 自動給油システム(ALS)完全ガイド:仕組み・種類・導入メリット
- 制御システム移行の成功戦略:シームレスな移行のためのエキスパートアプローチ
- 実績ある電気システムにおける一般的な故障モード
- 家庭の安全を守るために避けるべき電気コード違反トップ10
- PIRセンサー駆動自動ドア開閉システム:回路、動作、応用