今回は、土壌水分計の出力の記録について説明します。ここではアナログ式、つまり出力が電圧で返ってくるタイプのものを扱います。土壌水分計の定番といえば、METER(旧Decagon Devices)のEC-5があります(http://www.ai-nex.co.jp/ECH2Oprobe-soil.html )。温度も同時に測れる5TM(現在、販売中止と書いてあります)などはSDIによるデジタル式なので、ここで紹介する方法では扱うことができません。
実は、似たような土壌水分センサーはいろいろあり、Amazonで検索すると数百円~千円程度で多くのセンサーヘッドが見つかります。例えば、以下の土壌水分センサーは3つで880円。
このセンサーの詳細はわかりませんが、入力(印加)は3.3~5.5Vとのことです。電圧レギュレータ内蔵とのことなので、実際には3.3V以下で動いているのでしょう。今回はこれら2つを扱ってみますが、いずれも扱い方は基本的に同じです。
EC-5
扱い方に特段難しいことはありませんが、連続して印加しないように、とマニュアルには注意書きがあります。どの程度の時間を連続と考えるのかよくわかりませんが、省電力の観点からも、記録をとる寸前に印加するのがよいと思います。励起(印加)電圧は2.5~3.6Vで、出力は約 0.22~0.8V、計測時間は10msとのことです。また、計測間隔を10秒以上とるように、との注意書きもあります。ただ、少なくとも短期間、毎秒計測しても特段の問題が起こったようには見えませんでした。ターミナルは写真のようにピンジャックあるいはバラ線となっています。私はピンジャックで届いても、切ってバラにして接続しています。ロットによってスリーブの色が異なるようで、
赤:Analog out(出力)、素線:Ground、白:Excitation(印加)
あるいは
オレンジ:Analog out(出力)、素線:Ground、茶:Excitation(印加)
にいずれかになります。
Arduino UNOのアナログ計測は第4回で説明した通り、5Vレンジの10bitなので(この5V、という範囲は実はREFピンを使って変えられます)、分解は約0.005Vで、EC-5の出力幅0.6V(=0.8-0.22V)を120段階にしか分解できないことになります。これが不十分なら、第8回で説明したようなADCモジュールを使います。
問題は印加のほうになります。Arduino UNOやArduino Nanoには3.3V出力ピンがありますが、このピンからは連続的に印加されるので、(マニュアルを真面目にうけとるなら)EC-5の印加には向きません。デジタルピンを使って印加すればON/OFFできるわけですが、これらのArduinoは5V系モデルなので、ONにするたびに5Vで印加されてしまいます。この問題を避けるためには、以下の3つの方法が考えられます。
① Arduino Pro Mini 3.3V 8MHzモデルのように、3.3V系のマイコンボードを使ってデジタルピンから印加する
② Arduino UNOなど5V系マイコンボードの3.3V出力ピンを使うが、第10回で紹介したマルチプレクサーモジュールを使って限られた時間のみ通電する
③ Arduino UNOなど5V系マイコンボードの5Vデジタルピンを使うが、電圧レギュレータを使って3.3Vに落としてから印加する
それぞれの接続例とスケッチを示します。せっかくですので、3つのEC-5を接続することを想定します。ここでは、「測定間隔を最低10秒とせよ」というのをガン無視して、2秒間隔(delay(2000);とある通り)としています。個人的経験としてこれで壊れたことはありませんが、各自の責任で行ってください。
① Arduino Pro Mini 3.3V 8MHzモデルのように、3.3V系のマイコンボードを使ってデジタルピンから印加する
下の図のように接続しますが、ここはUSB-シリアル変換モジュール(図中の赤い基板)のVcc出力が3.3Vに落とされていることが前提です(PCのUSB端子からの印加は5Vです)。もしこの端子から5V出ている場合には、Arduino Pro Mini側のVccではなくRAWにつないで下さい。Arduino Pro Miniのボード上で3.3Vに落とされてから入力されます(詳しくは第12回参照)。印加開始して(digitalWriteでHIGHにして)から100msec待ち、電圧を読んだ後にdigitalWrite -> LOWで印加を停止しています。
#define CHANNELNUM 3 // Number of EC-5 connected to Arduino
const int apin[CHANNELNUM]={0, 1, 2}; // Analog pins to read the EC-5 outputs
const int dpin[CHANNELNUM]={2, 3, 4}; // Digital pins to energise EC-5
void setup(void)
{
int cnt1;
/* ----- Setting up serial communication with PC ------ */
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
for(cnt1=0;cnt1<CHANNELNUM;cnt1++)
{
pinMode(dpin[cnt1], OUTPUT);
}
}
void loop(void)
{
int cnt1; //general-purpose counter index
float ec5_reading[CHANNELNUM];
for(cnt1=0;cnt1<CHANNELNUM;cnt1++)
{
digitalWrite(dpin[cnt1], HIGH);
delay(100);
ec5_reading[cnt1]=analogRead(apin[cnt1])*3300.0/1023;
digitalWrite(dpin[cnt1], LOW);
}
/* ----- Show the data on PC ----- */
for(cnt1=0;cnt1<CHANNELNUM;cnt1++)
{
Serial.print("Ch");Serial.print(cnt1);Serial.print(": ");Serial.print(ec5_reading[cnt1]);Serial.println(" mV");
}
Serial.println("");
delay(2000);
}
最近、写真を見せていなかったので、久々に雰囲気を見せます。自宅にEC-5が1つしかなかったので、ここでは1つしかつないでいません。また、私が持っているUSB-シリアル変換モジュールやArduino Pro Miniは、上のFritzing図と比べると6線の端子が逆転(鏡面対称)になっていました。よくシルクを見て接続してください。
結果はこんな感じです。Ch0しかつなげていないので、Ch1・Ch2は不定値を示しています。244.38mVとありますが、センサー受感部を握ると、600mVくらいになります。
② Arduino UNOなど5V系マイコンボードの3.3V出力ピンを使うが、第10回で紹介したマルチプレクサーモジュール(図中の赤い基板)を使って限られた時間のみ通電する。
簡単におさらいすると、s0~s3の4つのピンをつかって4bit(16通り)の信号を送ると、c0~c15のどれかとsigが双方向でつながるというスイッチング装置です。いずれのEC-5にも印加しない時間帯は、何もつないでいないC3とsigをつなぐようにスケッチを書きました。3.3V印加しているとはいえ、マイコン自体は5V系なので、電圧を変換するときは×3.3V/1023ではなく×5V/1023することに注意。
#define CHANNELNUM 3 // Number of EC-5 connected to Arduino
const int s0 = 3; // Used to control the multiplexer
const int s1 = 4; // Used to control the multiplexer
const int s2 = 5; // Used to control the multiplexer
const int s3 = 6; // Used to control the multiplexer
const int apin[CHANNELNUM]={0, 1, 2}; // Analog pins to read the EC-5 outputs
void setup(void)
{
/* ----- Setting up serial communication with PC ------ */
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
/* ----- Preparation of multiplexer signal ----- */
pinMode(s0, OUTPUT);
pinMode(s1, OUTPUT);
pinMode(s2, OUTPUT);
pinMode(s3, OUTPUT);
}
void loop(void)
{
int cnt1; //general-purpose counter index
float ec5_reading[CHANNELNUM];
for(cnt1=0;cnt1<CHANNELNUM;cnt1++)
{
connectMux(cnt1);
delay(100);
ec5_reading[cnt1]=analogRead(apin[cnt1])*5000.0/1023;
}
connectMux(cnt1+1);
/* ----- Show the data on PC ----- */
for(cnt1=0;cnt1<CHANNELNUM;cnt1++)
{
Serial.print("Ch");Serial.print(cnt1);Serial.print(": ");Serial.print(ec5_reading[cnt1]);Serial.println(" mV");
}
Serial.println("");
delay(2000);
}
/* Function to connect to a particular channel by multiplexer (mux) */
int connectMux(int channel)
{
int controlPin[] = {s0, s1, s2, s3};
int muxChannel[16][4]={
{0,0,0,0}, //channel 0
{1,0,0,0}, //channel 1
{0,1,0,0}, //channel 2
{1,1,0,0}, //channel 3
{0,0,1,0}, //channel 4
{1,0,1,0}, //channel 5
{0,1,1,0}, //channel 6
{1,1,1,0}, //channel 7
{0,0,0,1}, //channel 8
{1,0,0,1}, //channel 9
{0,1,0,1}, //channel 10
{1,1,0,1}, //channel 11
{0,0,1,1}, //channel 12
{1,0,1,1}, //channel 13
{0,1,1,1}, //channel 14
{1,1,1,1} //channel 15
};
//loop through the 4 sig
for(int i = 0; i < 4; i ++){
digitalWrite(controlPin[i], muxChannel[channel][i]);
}
}
③ Arduino UNOなど5V系マイコンボードの5Vデジタルピンを使うが、電圧レギュレータを使って3.3Vに落としてから印加する。
ここで、電圧レギュレータというものについて説明します。(三端子)レギュレータは、下の写真のように端子が3つあり、真ん中がコモン(GND)で、入力側(左)に電圧を与えると、出力側(右)から一定の(入力値から下げられた)電圧が得られるものです。この写真は48M05Fで、5V出力タイプなので、入力には5Vよりいくらか大きい直流電圧を与えなければなりません。ただし、実際には入力・出力両方の端子に容量の異なるコンデンサーを接続するなどの手間が必要です。
これをすでにしてあるモジュールが安価に手に入るので、そちらを使うほうが簡単です。下の写真は3.3Vへ電圧降下を行うモジュールで、AMS1117というレギュレータが実装されています。Amazonで、HiLetGoさんが10個600円くらいで売っています。通電するとLEDが点灯するというサービス(?)付きです。
これを使えば・・・
スケッチ自体は①のケースとほとんど同じです。×3300.0/1023を×5000.0/1023に直した他、デジタルピンを番号を1つずらしただけです(特にずらした意味はありません)。
#define CHANNELNUM 3 // Number of EC-5 connected to Arduino
const int apin[CHANNELNUM]={0, 1, 2}; // Analog pins to read the EC-5 outputs
const int dpin[CHANNELNUM]={3, 4, 5}; // Digital pins to energise EC-5
void setup(void)
{
int cnt1; //general-purpose counter index
/* ----- Setting up serial communication with PC ------ */
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
for(cnt1=0;cnt1<CHANNELNUM;cnt1++)
{
pinMode(dpin[cnt1], OUTPUT);
}
}
void loop(void)
{
int cnt1; //general-purpose counter index
float ec5_reading[CHANNELNUM];
for(cnt1=0;cnt1<CHANNELNUM;cnt1++)
{
digitalWrite(dpin[cnt1], HIGH);
delay(500);
ec5_reading[cnt1]=analogRead(apin[cnt1])*5000.0/1023;
digitalWrite(dpin[cnt1], LOW);
}
/* ----- Show the data on PC ----- */
for(cnt1=0;cnt1<CHANNELNUM;cnt1++)
{
Serial.print("Ch");Serial.print(cnt1);Serial.print(": ");Serial.print(ec5_reading[cnt1]);Serial.println(" mV");
}
Serial.println("");
delay(2000);
}
3個880円の土壌水分計
センサーに「Capacitive Soil Moisture Sensor(静電容量式土壌水分センサー)」なるジェネリックな名前しかついていないので、あえてこう呼ばせてもらいます。印加電圧はEC-5とほぼ同じなので、先の①~③接続図でEC-5をこのセンサーに単に置き換えればそのまま使えます。
私が買ったものは先の写真のようにL型のピンヘッダ―がついてきました(白いコネクタ)。これにメスのジャンパーワイヤーをつなげばもちろんそのまま使えますが、防水にしたいので、はんだごてを使ってピンヘッダ―は取り除きました。そこに2芯のシールドケーブルをはんだ付けし、大径の熱収縮チューブで完全にシールしたのが下の図です。これで、不格好ながら、EC-5みたいな感じになりました。EC-5は16,000円ですが、これはケーブル2mと熱収縮チューブを含めて1000円しません。同じ性能があるかはわかりませんが・・・
両センサーの比較
ここで、両センサーの応答を見てみます。長期的な比較をする時間がなかったので、10分くらいでできる簡単な比較だけです。Arduino Pro Mini 3.3V 8MHzに両センサーを1つずつ接続し、持ち運びやすいようにバッテリー駆動とし、結果がすぐ見えるようにLCD(第18回参照。ただし、ここでは20文字×4行ではなく16文字×2行を使っているので、I2Cアドレスなどに変更があります)表示としました。先の①~③の方法のうち、ここでは③を使いました(LCDは5Vで印加しないと明るさが足りないので)。第18回をとばしていて、まだLCDのライブラリをインストールしていない人は、それが必要なことに留意してください。
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F,20,4);
const int s0 = 3; // Used to control the multiplexer
const int s1 = 4; // Used to control the multiplexer
const int s2 = 5; // Used to control the multiplexer
const int s3 = 6; // Used to control the multiplexer
void setup(void)
{
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
/* ----- Preparation of multiplexer signal ----- */
pinMode(s0, OUTPUT);
pinMode(s1, OUTPUT);
pinMode(s2, OUTPUT);
pinMode(s3, OUTPUT);
/* ----- Initialisation of LCD ----- */
lcd.init();
lcd.backlight();
}
void loop(void)
{
float ec5_reading;
float sms_reading;
connectMux(0);
delay(100);
ec5_reading=analogRead(A0)*5000.0/1023;
connectMux(1);
delay(100);
sms_reading=analogRead(A1)*5000.0/1023;
connectMux(2);
lcd.clear();
lcd.setCursor(0, 0);lcd.print(ec5_reading);
lcd.setCursor(0, 1);lcd.print(sms_reading);
lcd.setCursor(4, 0);lcd.print(" mV");
lcd.setCursor(4, 1);lcd.print(" mV");
delay(2000);
}
/* Function to connect to a particular channel by multiplexer (mux) */
int connectMux(int channel)
{
int controlPin[] = {s0, s1, s2, s3};
int muxChannel[16][4]={
{0,0,0,0}, //channel 0
{1,0,0,0}, //channel 1
{0,1,0,0}, //channel 2
{1,1,0,0}, //channel 3
{0,0,1,0}, //channel 4
{1,0,1,0}, //channel 5
{0,1,1,0}, //channel 6
{1,1,1,0}, //channel 7
{0,0,0,1}, //channel 8
{1,0,0,1}, //channel 9
{0,1,0,1}, //channel 10
{1,1,0,1}, //channel 11
{0,0,1,1}, //channel 12
{1,0,1,1}, //channel 13
{0,1,1,1}, //channel 14
{1,1,1,1} //channel 15
};
//loop through the 4 sig
for(int i = 0; i < 4; i ++){
digitalWrite(controlPin[i], muxChannel[channel][i]);
}
}
空気中、水中に置いたり、我が家の軒先でペチュニアの鉢にさしてみました。
結果は、
EC-5
3個880円の土壌水分計
空気中
263mV
2834mV
乾いた鉢
449mV
2512mV
水をあげたばかりの鉢
630mV
1661mV
水中
909mV
1510mV
水を鉢の土に均一にあげられたわけではないので、これを見て線形性云々の議論はできませんが、安いセンサーも、出力レンジが広そうで、これだけ見れば悪くはなさそうです。少なくとも、地盤中のある位置が浸潤したかどうかを判断するくらいには使えそうです。
最後に
ここで扱った土壌水分計はアナログ出力なので、扱いは簡単ですが、一方で気をつけないといけないこともあります。まず、印加電圧が安定していなければなりません。他にいろいろ周辺機器をArduinoにつなぎ、電力供給が足りないことによって電圧降下などが起きないようしてください。また、供給の問題かADC(アナログ-デジタル変換)の問題かわかりませんが、長期計測をしていると、全てのセンサーの値が一様にシフトすることなどあります。地盤の含水率がいたるところで急に上がった!と解釈するかもしれませんが、電圧がどこかで(入力か出力か)でシフトした可能性もあります。ですので、長期計測を行う際は、少なくとも1つ、ダミーとしてセンサーを余分に接続し、地盤に挿さずにロガーボックス中などに浮かせておくことをお勧めします。そうすれば、本当の地盤状態の変化と、電圧系のシフト(ドリフト)を区別することができます。