Arduinoと土壌水分センサーで植物の自動水やり装置を作る!キャリブレーションと水のやりすぎ防止まで解説
「旅行や出張で数日家を空けると、観葉植物がしおれてしまう…」「水やりを忘れて枯らしてしまった」──そんな経験、ありますよね。
この記事では、Arduinoと静電容量式の土壌水分センサー、小型の水中ポンプを組み合わせて、土が乾いたら自動で水をあげる装置を作ります。難易度はArduino初〜中級者向け。LチカやanalogRead()を一度でも触ったことがあれば大丈夫です😊
ただ「乾いたらポンプON」だけだと、実はうまく動きません。この記事では、つまずきやすいキャリブレーションと水のやりすぎ防止(ヒステリシスと安全装置)まで一緒に見ていきましょう!
用意するもの

| 部品 | 役割・メモ |
|---|---|
| Arduino UNO(互換機でもOK) | 全体の制御 |
| 静電容量式土壌水分センサー(Capacitive Soil Moisture Sensor v1.2 など) | 土の湿り具合をアナログ値で出力 |
| 1チャンネル リレーモジュール | ポンプの電源をON/OFFする |
| 小型水中ポンプ(DC 3〜5V程度)+チューブ | タンクから鉢へ水を送る |
| ポンプ用の電源(電池ボックスなど) | ポンプはArduinoとは別の電源から給電する |
| 水タンク(ペットボトルなど)・ジャンパーワイヤ |
⚠️ 抵抗式(2本の金属電極がむき出しのタイプ)のセンサーは、長期間の設置には不向きです。電極に電流が流れ続けるため、土の中で腐食が進みやすいからです。常に挿しっぱなしにする自動水やりでは、電極が表に出ていない静電容量式を選びましょう。
配線
- センサー:VCC → 5V、GND → GND、AOUT → A0
- リレーモジュール:VCC → 5V、GND → GND、IN → D7
- ポンプ:ポンプ用電源の+ → リレーの COM、リレーの NO → ポンプの+、ポンプの− → ポンプ用電源の−
ここが重要です👇
- ポンプをArduinoの5Vピンから直接動かさない。モーターの起動電流でArduinoがリセットされる原因になります
- センサーは基板の白線(上限ライン)より上を土に埋めない。電子部品が濡れると壊れます
- 水と電気を扱うので、Arduino本体やリレーは鉢から離し、水がかからない場所に置きましょう
ステップ1:センサーをキャリブレーションする
静電容量式センサーは、乾いているほど値が大きく、湿っているほど値が小さくなります。イメージとしては「数字が大きい=カラカラ」です。
ところが、この値はセンサーの個体差や電源電圧で大きく変わります。ある個体では空気中で500台なのに、別の個体では600台、ということも珍しくありません。なので、まずは自分のセンサーで「カラカラの値」と「びしょびしょの値」を測ります。
// 土壌水分センサーのキャリブレーション用スケッチ
const int SENSOR_PIN = A0;
void setup() {
Serial.begin(9600);
}
void loop() {
// 10回読んで平均し、ノイズを減らす
long sum = 0;
for (int i = 0; i < 10; i++) {
sum += analogRead(SENSOR_PIN);
delay(10);
}
int raw = sum / 10;
Serial.print("raw=");
Serial.println(raw);
delay(500);
}
ポイントをまとめるとこんな感じです。
- 10回読んで平均を取り、値のブレを抑えている
- シリアルモニタ(9600bps)を開き、①センサーを空気中に置いたときの値と②白線の手前までコップの水に挿したときの値をメモする
- ①が「DRY_RAW」、②が「WET_RAW」になります
表示例(値は個体によって異なります):
raw=521
raw=519
raw=520
(水に挿すと)
raw=262
raw=259
この記事では、以降 DRY_RAW = 520、WET_RAW = 260 として話を進めます。実際には自分で測った値に置き換えてください。
ステップ2:「しきい値1つ」がダメな理由をPythonで確かめる
いきなりポンプをつなぐ前に、制御の考え方をPythonで試しておきましょう。水とポンプを使う実験は失敗すると後片付けが大変なので、ロジックだけ先にPCで確認しておくと安心です。
素直に考えると「湿度40%未満ならポンプON、40%以上ならOFF」ですよね。でもセンサー値には少しノイズが乗るので、40%付近をウロウロすると…? これ、実行せずに答えられますか?
# 自動水やりの「しきい値」と「ヒステリシス」をPythonで先に確かめる
DRY_RAW = 520 # 空気中(カラカラ)のときの値
WET_RAW = 260 # 水に挿したときの値
def to_percent(raw):
"""センサーの生の値を 0〜100% の湿度に変換する"""
# Arduino の map() と同じく小数点以下は切り捨て
percent = int((DRY_RAW - raw) * 100 / (DRY_RAW - WET_RAW))
return max(0, min(100, percent))
# 土が乾いていく〜水やりまでを想定したセンサー値(少しノイズが乗っている)
readings = [408, 412, 415, 419, 414, 418, 413, 420, 424, 428, 431, 395, 360, 330]
def simulate(on_below, off_above):
pump = False
log = []
for raw in readings:
p = to_percent(raw)
if not pump and p < on_below:
pump = True
elif pump and p >= off_above:
pump = False
log.append((raw, p, "ON" if pump else "--"))
return log
for name, on_below, off_above in [("しきい値1つ(40%)", 40, 40),
("ヒステリシスあり(35%でON / 60%でOFF)", 35, 60)]:
log = simulate(on_below, off_above)
switches = sum(1 for a, b in zip(log, log[1:]) if a[2] != b[2])
print(f"■ {name}")
print(" " + " ".join(f"{p:>3}%" for _, p, _ in log))
print(" " + " ".join(f"{s:>4}" for _, _, s in log))
print(f" ポンプの切り替え回数: {switches}回\n")

実行すると、上の実行結果のようになります。
しきい値が1つだと、40%付近のわずかなブレでポンプがON/OFFを6回も繰り返しています。これでは水がチョロチョロ出たり止まったりして、リレーやポンプにも負担がかかります。
そこで使うのがヒステリシスです。つまり「ONにする値」と「OFFにする値」をわざとずらす方法です。35%を下回ったら水やり開始、60%以上になるまで止めない、とすると、切り替えは開始と終了の2回だけになりました🚀 エアコンのサーモスタットも同じ考え方で動いています。
ちなみに、変換式は Arduino の map() と同じく小数点以下を切り捨てにしているので、Arduinoで表示される%とそろいます。
ステップ3:自動水やりスケッチ
いよいよ本番のスケッチです。ヒステリシスに加えて、水のやりすぎを防ぐ工夫を2つ入れています。
// 静電容量式土壌水分センサー+ポンプで自動水やり
const int SENSOR_PIN = A0;
const int PUMP_PIN = 7; // リレーモジュールの IN につなぐ
const int DRY_RAW = 520; // キャリブレーションで測った「空気中」の値に書き換える
const int WET_RAW = 260; // キャリブレーションで測った「水中」の値に書き換える
const int ON_BELOW = 35; // これを下回ったら水やり開始(%)
const int OFF_ABOVE = 60; // これ以上になったら水やり終了(%)
const unsigned long PUMP_MS = 3000; // 1回の給水時間(3秒)
const unsigned long SOAK_MS = 60000; // 水が土にしみ込むのを待つ時間(60秒)
const int MAX_PULSES = 5; // 1回の水やりで給水する回数の上限
// LOW で ON になるリレーモジュールなら RELAY_ON を LOW に変える
const int RELAY_ON = HIGH;
const int RELAY_OFF = (RELAY_ON == HIGH) ? LOW : HIGH;
bool watering = false; // 水やり中かどうか
int pulses = 0; // 今回の水やりで給水した回数
bool locked = false; // 安全装置が作動したか
int readPercent() {
long sum = 0;
for (int i = 0; i < 10; i++) {
sum += analogRead(SENSOR_PIN);
delay(10);
}
int raw = sum / 10;
// 乾いているほど値が大きいので、DRY→0%、WET→100% に変換
int percent = map(raw, DRY_RAW, WET_RAW, 0, 100);
return constrain(percent, 0, 100);
}
void setup() {
digitalWrite(PUMP_PIN, RELAY_OFF); // 起動直後にポンプが回らないよう先にOFFを書く
pinMode(PUMP_PIN, OUTPUT);
Serial.begin(9600);
}
void loop() {
if (locked) {
Serial.println("LOCKED: check water tank and sensor");
delay(10000);
return;
}
int percent = readPercent();
Serial.print("moisture=");
Serial.print(percent);
Serial.println("%");
// ヒステリシス:35%未満で開始、60%以上で終了
if (!watering && percent < ON_BELOW) {
watering = true;
pulses = 0;
} else if (watering && percent >= OFF_ABOVE) {
watering = false;
Serial.println("watering done");
}
if (watering) {
if (pulses >= MAX_PULSES) {
// 何度給水しても湿らない=タンクが空かセンサーが抜けている
locked = true;
return;
}
digitalWrite(PUMP_PIN, RELAY_ON);
delay(PUMP_MS);
digitalWrite(PUMP_PIN, RELAY_OFF);
pulses++;
Serial.print("pump pulse ");
Serial.println(pulses);
delay(SOAK_MS); // しみ込むまで待ってから測り直す
} else {
delay(5000);
}
}
ここが重要です👇
- 少しずつ給水して、しみ込むのを待つ:水をあげてもすぐにはセンサーの値が上がりません。60%になるまでポンプを回し続けると、値が上がる前に鉢から水があふれます。そこで「3秒給水 → 60秒待って測り直す」を繰り返しています
- 給水回数の上限(安全装置):タンクが空になったり、センサーが鉢から抜けたりすると、いくら給水しても値が上がりません。5回給水しても60%に届かなければロックして止まるので、部屋が水浸しになるのを防げます
- リレーの向きに注意:リレーモジュールには、INがHIGHでONになるタイプとLOWでONになるタイプがあります。電源を入れた瞬間にポンプが回るなら、
RELAY_ONをLOWに変えてください setup()でpinMode()より先にOFFを書いておくと、起動直後にポンプが一瞬動くのを防ぎやすくなります
シリアルモニタの表示例:
moisture=41%
moisture=38%
moisture=34%
pump pulse 1
moisture=47%
pump pulse 2
moisture=62%
watering done
moisture=61%
うまく動かないときのチェックポイント
- %がいつも0%や100%に張り付く:DRY_RAW / WET_RAW が自分のセンサーの値と合っていません。ステップ1をやり直しましょう
- 値が安定しない:センサーの周りに隙間があると値が暴れます。挿したあと周りの土を軽く押さえて密着させてください
- ポンプが回るとArduinoがリセットされる:ポンプの電源をArduinoと分けているか確認しましょう
- しきい値の決め方:植物によって好む湿り具合は違います。まずは数日シリアルモニタで値を観察し、「そろそろ水をあげたい」と感じたときの%をON_BELOWの目安にするのがおすすめです
まとめ
- 自動水やりには、腐食に強い静電容量式の土壌水分センサーを使う
- センサー値は個体差が大きいので、空気中と水中の値でキャリブレーションしてから%に変換する
- しきい値1つだとON/OFFを繰り返すので、ヒステリシス(35%でON/60%でOFF)を使う
- 「少しずつ給水→しみ込むのを待つ」と「給水回数の上限」で、水のやりすぎと水浸しを防ぐ
「むずかしそう」に見える自動水やりも、分解してみるとセンサーを読む → %に変換 → ポンプをON/OFFの3ステップです。ざっくりとした流れがつかめたら、ぜひ手元の鉢植えで試してみてください😊
こちらも読まれています
📡 Arduinoをもっと深く学ぼう!
Arduino・ラズパイ・ロボットプログラミングを体系的に学びたい方へ。おすすめのUdemyコースや電子部品もまとめています。
Arduinoロボット入門のおすすめコース・部品を見る →📚 関連商品・おすすめ書籍
※本記事にはアフィリエイトリンクが含まれます。





