Arduinoと土壌センサを使って土の水分量の測定

 

こんなこと、やります。

  • Arduino(ESP32)と土壌センサを使って、土の水分量を測定
  • Ambientへログを送信、グラフ化する

Arduinoと土壌センサを使って土の水分量の測定
Arduinoと土壌センサを使って土の水分量の測定

つかうもの

Arduino

Ambientクラウドサービスへデータを送信するため、無線機能を搭載したESP32を使用しました。

Ambientや無線機能を使わないのでしたら、どのArduinoを使っていただいても構いません。Arduinoをお持ちでないようでしたらオススメ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つの種類があります。

  1. 抵抗型
  2. 静電容量型

抵抗型土壌センサ

❶の抵抗型は、2つの金属棒で土の抵抗を測って土壌の水分量を測定する方法です。水分量が増加すると電気抵抗が少なくなることを利用したセンサです。釘を使って自作することも可能です。

ただし、金属棒が土にさらされますから、腐食しやすいです。使っているうちに抵抗値も変化してしまデメリットがあります。

静電容量型土壌センサ

❷の静電容量型は、センサーに接触している水分量が変わると、センサー内部の静電容量が変化するのを利用して土壌水分量を測定します。静電容量型は、電極板をコーティングできるので腐食の恐れがほぼないといってよいでしょう。この記事でも❷の静電容量型を使用しました。

土壌センサの使い方

土壌センサの使い方を説明します。

静電容量型土壌センサ

「Capacitive Soil Moisture Sensor」の使い方を説明します。ネットを探しても公式のマニュアルを見つられなかったので、調べた限りの情報をまとめます。

土壌センサの使用範囲は図のとおりです。センサにラインが引いてありますが、これは警告線です。このラインより1cm〜2cm下の範囲までを、土壌へ埋めるようにしましょう。写真のようにセメダイン 超多用途 接着剤 スーパーX ブラックをつかって回路基板を防水対策すると便利でした。

土壌センサの使用範囲
土壌センサの使用範囲

仕様

項目内容
電源電圧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音センサの作り方に書きました。

AOUTとGND間に100kΩ
AOUTとGND間に100kΩ

準備

Arduinoと土壌センサの配線

土壌センサの電源は3.3Vまたは5Vのどちらでも構いません。GNDをArduinoと共通にして、センサのアナログ出力(AOUT)をArduinoのアナログ入力につなぎます。

センサのアナログ出力は0V〜3Vの範囲で変化します。

くれぐれも定電圧で!

以前、ESP8266で土壌センサを使ったときのことです。

土壌センサーを使ってベランダの野菜プランターの土壌水分量を測定
土壌センサーを使ってベランダの野菜プランターの土壌水分量を測定

朝、プランターに水やりをしてから、土壌の水分量の測定を開始し、Ambientでグラフ化しました。

時間と土壌水分量の推移グラフ
時間と土壌水分量の推移グラフ

なぜか水分量が上昇してしまいました。数式を何度も見ながら「間違ってないよなー」と確認。その後、電池交換した時、重大なミスに気づいてしまいました。

定電圧でなかったために水分量が正しく測れていない
定電圧でなかったために水分量が正しく測れていない

おわかり頂けますでしょうか?

電源の電圧降下が影響して、土壌センサーのアナログ出力に影響してしまったんです。土壌センサーは出力電圧が低くなると水分量が多くなってしまい、電池の消耗とともに右肩上がりのグラフになってしまったのです。

ですから、電源の定電圧化は必須です。どうしても乾電池を使いたい場合は、3.3VのレギュレーターなどのDC-DCコンバータを使って安定化電源にしましょう。

みなさんも、土壌センサをつかう際はくれぐれもご注意ください。

Arduinoと土壌センサで水分量の測定

Arduinoと土壌センサで水分量測定するプログラミングを行なっていきます。

次の内容でプログラミングしました。

  • アナログ入力でセンサの電圧値を読み取る
  • 土壌水分量を計算
  • 30秒置きにこれを繰り返し、WiFiでAmbientへログを送信

ちなみに、土壌センサは2つ使っています。また、DHT11を使って温度・湿度の測定も同時に行なっています。

DHT11の使い方は、Arduinoで温度湿度センサDHT11の使い方をご覧ください。

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();
}
コメントに書いたとおり、analogReadを連続でつかうとエラーが発生します。delayで少し待ってからanalogReadを行なってください。

測定結果

上記のプログラムを実行し、ベランダ菜園のフェルトプランタープラスチックプランターの土壌水分量を測定してみました。夕方に水やりを行い、次の日の夕方まで水やりをしない状態で観察します。

そして、こちらが測定したグラフです。

フェルトとプラスチックの土壌水分量の違い
フェルトとプラスチックの土壌水分量の違い

まず土壌水分量ですが、土壌センサにはバラツキがありました。また、土にセンサを挿す具合によって、だいぶ水分量が変化してしまいます。

よって、水分量のパーセンテージ同士を比較してもあまり意味がありません。

ですから、水分量の変化量を見ることにします。

水分量の変化量をみると、フェルトプランターでは一日でマイナス13%だったのに対し、プラスチックプランターではマイナス20%となりました。何度か測定しましたが、プラスチックプランターのほうが水の乾きが速い結果になりました。もちろん土の量の違いも水分量の変化に影響しているかもしれません。

発展

土壌センサを使った応用例をご紹介します。

M5StickC PLUSをつかう

M5Stackシリーズで土壌センサを使いたい方もいらっしゃると思います。

実は私も、最初はM5StickC PLUSを使っていたのです。

M5StickC PLUSにDHT11の自作HATと、GROVEで土壌センサを接続したようす
M5StickC PLUSにDHT11の自作HATと、GROVEで土壌センサを接続したようす

ですが、WiFi通信にした途端、G33のアナログ入力が動作しませんでした。G33はWiFi使用時でも使えるはずなのですが。

もしかしたら、delayをせずにanalogReadを連続で呼び出していたのがまずかったのかもしれません。

ESP32でも、連続でanalogReadを呼び出すと読み取りに失敗することがあります。M5StickC PLUSの実機で確かめたいのですが、訳あってM5StickC PLUSを失くしてしまい確認ができていません。みなさんが行う場合は、このへんを頭に入れておくとトラブル解決に役立つかもしれません。

M5StickC PLUSで気温、湿度、土壌水分量の測定
M5StickC PLUSで気温、湿度、土壌水分量の測定

応用例

試してはいませんが、Amazonでよく見かける商品をご紹介しします。

土壌センサとリレーやポンプがセットになった「自動水やり装置」です。実用的かどうかはさておき、なんだか楽しそうなので実験してみたくなります。

ちなみに、リレーの使い方はとてもカンタンです。使い方はラズパイとリレーモジュールをご参考になさってみてください。

PHを測定できるセンサも見つけてしまいました。畑の土壌管理や、水槽の水質管理に使えそうです。

記事に関するご質問などがあればTwitterへお返事ください。
この記事で紹介した商品
ESP32搭載ボード
ESP32の書籍
Arduinoで人気の周辺パーツ
関連記事