Arduinoと土壌湿度センサを使って土の水分量の測定
こんなこと、やります。
- Arduino(ESP32)と土壌湿度センサを使って、土の水分量を測定
- Ambientへログを送信、グラフ化する
つかうもの
はじめに使うものをご紹介いたします。
Arduino
Ambientクラウドサービスへデータを送信するため、無線機能を搭載したESP32を使用しました。私は普段、WayintopさんのESP32を使用しています。
Ambientや無線機能を使わないのでしたら、どのようなArduinoを使っていただいても構いません。もしArduinoをお持ちでないようでしたら、下記記事をご参考になさってみてください。
土壌湿度センサ
こちらの静電容量型の土壌湿度センサを使用します。
Amazonでよく見かけるこちらの製品は「Capacitive Soil Moisture Sensor」というものです。
土壌湿度センサは防水加工されていません。防水加工を施して、ケーブルを延長した土壌湿度センサをメルカリで販売してます。よろしければこちらもご検討ください。
野外に便利
電源コードが取れない場合、モバイルバッテリーのような安定化電源が必要です。
その他の電子部品
ブレッドボードやジャンプワイヤをお持ちでない方は揃えておいてください。
また、DHT11で温度と湿度も同時に測定しました。
開発環境
項目 | バージョン |
---|---|
統合開発環境 | VS Code x Platform IO |
パソコン | macOS Big Sur 11.0.1 |
Macを使用しましたが、WindowsやLinuxでも構いません。また統合開発環境も、Arduino IDEで大丈夫です。
土壌湿度センサの選び方
ところで、土壌湿度センサには次の2つの種類があります。
- 抵抗型
- 静電容量型
抵抗型土壌湿度センサ
❶の抵抗型は、2つの金属棒で土の抵抗を測って土壌の水分量を測定する方法です。水分量が増加すると電気抵抗が少なくなることを利用したセンサです。釘を使って自作することも可能です。
ただし、金属棒が土にさらされますから、腐食しやすいです。使っているうちに抵抗値も変化してしまうデメリットがあります。
▼ DfROBOTの抵抗型土壌湿度センサーを防水加工しました。
静電容量型土壌湿度センサ
❷の静電容量型は、センサに接触している水分量が変わると、センサ内部の静電容量が変化するのを利用して土壌水分量を測定します。静電容量型は、電極板をコーティングできるので腐食の恐れがほぼないといってよいでしょう。この記事でも❷の静電容量型を使用しました。
土壌湿度センサの使い方
土壌湿度センサの使い方を説明します。
静電容量型土壌湿度センサ
「Capacitive Soil Moisture Sensor」の使い方を説明します。ネットを探しても公式のマニュアルを見つられなかったので、調べた限りの情報をまとめます。
土壌湿度センサの使用範囲は図のとおりです。センサにラインが引いてありますが、これは警告線です。このラインより1cm〜2cm下の範囲までを、土壌へ埋めるようにしましょう。
仕様
項目 | 内容 |
---|---|
電源電圧 | 3.3〜5.5V |
出力電圧範囲 | 0〜3V |
消費電流 | 5mA |
センサのアナログ出力電圧は、センサによって少しばらつきがあるようです。複数台使う場合は、補正かけるなどの工夫が必要かもしれません。
水分量の計算方法
土壌湿度センサを使って水分量を測定するには準備が必要です。それは、空気中と水中においてのアナログ出力を知る必要があります。空気中で値を水分量0%とし、水中での値を水分量100%とします。土壌湿度センサにはラインが引いてありますので、それより少し手前までを水につけて測定します。
つぎに、空気中の値を AirValueとし、水中の値をWaterValue とします。水分量 Moisture(%)は次の式で表すことができます。
$$ Moisture = 100 - 100 \times \frac{(Aout - WaterValue)}{(AirValue - WaterValue)}$$
ここでAoutは、センサのアナログ出力値であります。
静電容量型土壌湿度センサの回路図
少しマニアックな話になりますが、静電容量型土壌湿度センサの内部回路が分かりましたのでご紹介しておきます。
発振回路
まず、タイマICの555を使って矩形波を発生させています。矩形波は1次のRCローパスフィルタに通されます。すると、矩形波はローパスフィルタによって高周波成分が削られていき三角波へ近づきます。そして、交流信号(電圧)を直流信号(電圧)に変えるため、AC-DCコンバータを通します。
ローパスフィルタ
ここで、ローパスフィルタのコンデンサCを土壌湿度センサのプローブにすると、静電容量の変化に応じてカットオフ周波数が変化します。つまりフィルタのかかり具合が変わり、出力のアナログ電圧が変化するわけです。
AC-DCコンバータ
AC-DCコンバータは、Peak Detectorとも呼ばるもので、いわゆる半波整流回路になってます。実は、アナログ出力とは、1uのコンデンサに溜まった電荷を測っているにすぎないのです。1MΩの抵抗は、1uのコンデンサに溜まった電荷を逃がす役割をします。センサの反応が悪いと感じた場合には、この抵抗を100kΩ程度に変えると改善します。ここらへんの話は【ラズパイ】ECMで音センサつくってみたに書きました。
準備
Arduinoと土壌湿度センサを使って水分量を測定する前の準備です。
土壌湿度センサとArduino(ESP32)の配線
土壌湿度センサの電源は3.3Vまたは5Vのどちらでも構いませんが、ここでは3.3Vに繋いでおきました。GNDをArduinoと共通にして、センサのアナログ出力(AOUT)をArduinoやESP32のアナログ入力につなぎます。ADコンバータが使えるピンでしたらどこでも構いませんので、下記の配線図はご参考までに。
土壌湿度センサのアナログ出力は0V〜3Vの範囲で変化します。
土壌湿度センサの測定
先に説明した通り、土壌湿度センサは湿度に応じてアナログ電圧が出力されます。こちらのプログラムで事前に空気中の実測値と水に浸した時の実測値を測っておきましょう。
#include <Arduino.h>
#define SENSOR_PIN A0 // Arduino Uno
// #define SENSOR_PIN 27 // ESP32
void setup(void) {
Serial.begin(115200);
pinMode(SENSOR_PIN, INPUT);
delay(3000);
}
void loop(void) {
int val = analogRead(SENSOR_PIN);
Serial.println(val);
delay(1000);
}
Arduinoと土壌湿度センサで水分量の測定
こちらはArduino Unoと土壌湿度センサを使って水分量を測定する簡易的なプログラムです。センサが空気中の時に0、センサが水中の時を100を示すようになっています。ADC_MAX と ADC_MIN は各自で測定して書き換えてください。
#include <Arduino.h>
#define SENSOR_PIN A0 // Arduino Uno
// #define SENSOR_PIN 27// ESP32
const int ADC_MAX = 352; // 空気中の実測値
const int ADC_MIN = 159; // 水に浸した実測値
void setup(void) {
Serial.begin(115200);
pinMode(SENSOR_PIN, INPUT);
delay(3000);
}
void loop(void) {
int val = analogRead(SENSOR_PIN);
if (ADC_MAX < val) {
val = ADC_MAX;
}
else if (ADC_MIN > val) {
val = ADC_MIN;
}
int moisture = 100 - map(val, ADC_MIN, ADC_MAX, 0, 100);
Serial.println(moisture);
delay(1000);
}
先ほどもお伝えしたとおり、センサが空気中の時に0、センサが水中の時を100を示すプログラムです。ですから正確な意味での湿度が測定できるわけではないことをご了承ください。
これらを発展させれば、水やりポンプと組み合わせて、一定の水分量を下回ったら自動で水やりを行える装置を作ることも可能です。以前に企業様から依頼されて、8ch分の自動水やり機を製作したりしました。こちらの端末では、ボタンを使ってセンサの誤差を校正できたり、水やりを行う水分量を変えたりすることができます。
上の写真のポンプはこちらの製品です。
USB電源でも動作するので手軽で良いのですが、水を引き上げる力はそれほど強くありません。本格的に水やりを行いたい場合は、下記の電磁弁を使った方法をオススメします。
【発展】ESP32(ESP8266)と土壌湿度センサでデータロガー
ここからはWiFi機能を使ってデータロガーを作った事例をご紹介いたします。
次の内容でプログラミングしました。
- 温度・湿度の測定
- 土壌湿度センサで土壌水分量の測定
- 30秒置きにこれを繰り返し、WiFiでAmbientへログを送信
土壌湿度センサは2つ使いました。また、DHT11を使って温度・湿度の測定も同時に行なっています。
DHT11の使い方は、Arduinoで温度湿度センサDHT11の使い方をご覧ください。
AmbientはIoTデータをグラフ化してくれる無料のクラウドサービスです。Ambientの使い方は、【ラズパイ】Ambientへセンサデータを送信してグラフ化をご覧ください。
ソースコード
#include "DHT.h"
#include "Ambient.h"
#define DHT11_PIN 32
#define ADC1_PIN 34
#define ADC2_PIN 35
const int ADC1_MAX = 2230; // 空気中の実測値
const int ADC1_MIN = 990; // 水に浸した実測値
const int ADC2_MAX = 2160; // 空気中の実測値
const int ADC2_MIN = 960; // 水に浸した実測値
const char* ssid = "WiFiのSSID";
const char* password = "WiFiのパスワード";
const int channelId = AmbientのチャンネルID;
const char* writeKey = "Ambientのライトキー";
const boolean displayMode = true;
WiFiClient client;
Ambient ambient;
DHT dht(DHT11_PIN, DHT11);
void setup() {
Serial.begin(115200);
pinMode(ADC1_PIN, INPUT);
pinMode(ADC2_PIN, INPUT);
dht.begin();
Serial.println("WiFi connecting....");
WiFi.begin(ssid, password); // Wi-Fiの初期化
while (WiFi.status() != WL_CONNECTED) { // Wi-Fiアクセスポイントへの接続待ち
delay(500);
}
Serial.println("WiFi connected!!!");
ambient.begin(channelId, writeKey, &client);
}
int counter = 0;
void loop() {
/** DHT11 処理 **/
float h = dht.readHumidity();
float t = dht.readTemperature();
if (isnan(h) || isnan(t)) {
Serial.println("DHT11 failed...");
}
/** 土壌湿度センサ 処理 **/
int adc1 = analogRead(ADC1_PIN);
delay(500); // 少し待たないとanalogReadに失敗する
int adc2 = analogRead(ADC2_PIN);
Serial.printf("adc1: %d, adc2: %d\n", adc1, adc2);
if (ADC1_MAX < adc1) {
adc1 = ADC1_MAX;
}
else if (ADC1_MIN > adc1) {
adc1 = ADC1_MIN;
}
if (ADC2_MAX < adc2) {
adc2 = ADC2_MAX;
}
else if (ADC2_MIN > adc2) {
adc2 = ADC2_MIN;
}
int m1 = 100 - map(adc1, ADC1_MIN, ADC1_MAX, 0, 100);
int m2 = 100 - map(adc2, ADC2_MIN, ADC2_MAX, 0, 100);
Serial.printf("Humid: %.0f, Temp: %.1f%, Moist1: %d, Moist2: %d\n", h, t, m1, m2);
if (counter % 6 == 0) {
sendAmbient(h, t, m1, m2);
}
counter++;
delay(4500);
}
void sendAmbient(float humid, float temp, int moist1, int moist2) {
ambient.set(1, temp);
ambient.set(2, humid);
ambient.set(3, moist1);
ambient.set(4, moist2);
ambient.send();
}
測定結果
上記のプログラムを実行し、ベランダ菜園のフェルトプランターとプラスチックプランターの土壌水分量を測定してみました。夕方に水やりを行い、次の日の夕方まで水やりをしない状態で観察します。
そして、こちらが測定したグラフです。
まず土壌水分量ですが、土壌湿度センサにはバラツキがありました。また、土にセンサを挿す具合によって、だいぶ水分量が変化してしまいます。
よって、水分量のパーセンテージ同士を比較してもあまり意味がありません。
ですから、水分量の変化量を見ることにします。
水分量の変化量をみると、フェルトプランターでは一日でマイナス13%だったのに対し、プラスチックプランターではマイナス20%となりました。何度か測定しましたが、プラスチックプランターのほうが水の乾きが速い結果になりました。もちろん土の量の違いも水分量の変化に影響しているかもしれません。
くれぐれも定電圧で!
以前、ESP8266で土壌湿度センサを使ったときのことです。
土壌湿度センサを使ってベランダの野菜プランターの土壌水分量を測定
朝、プランターに水やりをしてから、土壌の水分量の測定を開始し、Ambientでグラフ化しました。
なぜか水分量が上昇してしまいました。数式を何度も見ながら「間違ってないよなー」と確認。その後、電池交換した時、重大なミスに気づいてしまいました。
おわかり頂けますでしょうか?
電源の電圧降下が影響して、土壌湿度センサのアナログ出力に影響してしまったんです。土壌湿度センサは出力電圧が低くなると水分量が多くなってしまい、電池の消耗とともに右肩上がりのグラフになってしまったのです。
ですから、電源の定電圧化は必須です。どうしても乾電池を使いたい場合は、3.3VのレギュレーターなどのDC-DCコンバータを使って安定化電源にしましょう。
みなさんも、土壌湿度センサをつかう際はくれぐれもご注意ください。
M5StickC PLUSで土壌湿度センサを使ってみた
M5Stackシリーズで土壌湿度センサを使いたい方もいらっしゃると思います。
実は私も、最初はM5StickC PLUSを使っていたのです。
M5StickC PLUSにDHT11の自作HATと、GROVEで土壌湿度センサを接続したようす
ですが、WiFi通信にした途端、G33のアナログ入力が動作しませんでした。G33はWiFi使用時でも使えるはずなのですが。
もしかしたら、delayをせずにanalogReadを連続で呼び出していたのがまずかったのかもしれません。
ESP32でも、連続でanalogReadを呼び出すと読み取りに失敗することがあります。M5StickC PLUSの実機で確かめたいのですが、訳あってM5StickC PLUSを失くしてしまい確認ができていません。みなさんが行う場合は、このへんを頭に入れておくとトラブル解決に役立つかもしれません。
応用例
試してはいませんが、Amazonでよく見かける商品をご紹介いたします。
土壌湿度センサとリレーやポンプがセットになった「自動水やり装置」です。実用的かどうかはさておき、なんだか楽しそうなので実験してみたくなります。
ちなみに、リレーの使い方はとても簡単です。使い方はラズパイとリレーモジュールをご参考になさってみてください。
PHを測定できるセンサも見つけてしまいました。畑の土壌管理や、水槽の水質管理に使えそうです。
【防水加工済み】土壌湿度センサ販売中!
菜園ですぐにお使いただけるように、センサの防水加工を施して、数メートルのケーブルとジャンプワイヤを付けたものをメルカリで少数販売してます!ブレッドボードにそのままさして、Arduino開発できるので便利です!
また、植物の根を痛めないようにセンサの先端を丸く加工しました。