これまで、土壌抵抗に基づいて水遣りを行うロジックを考えてきました。
ここで、手動水遣りボタンを作ります。
これは土壌抵抗に寄らず、水を給水するためのものです。
ここでは、割り込みモードを使います。
これまで、タクトスイッチの状態を見て動作させるには digitalRead、analogReadを使ってきました。これによって、スイッチが押されたことを観測しています。
しかし、delayに入っているときなど、**Readのコマンドがないときには読むことができません。
ここでArduinoにはattachInterruptという割り込み関数が用意されています。
これをつかってタクトスイッチが押されたら、給水を行います。
Arduino UNO R3の場合は割り込み番号0でpin2、割り込み番号1でpin3の組み合わせでこのピンの入力を随時受け付ける機能があります。
このattachInterruptはこの二つのpinしか利用することはできません。
========================================
void setup (){
pinMode(2, INPUT); //割り込みピン(タクトスイッチ)
attachInterrupt(0, manual_supply, HIGH);
}
========================================
void setupの中でこの割り込みピンを宣言します。
ここでは2pinをINPUTとして使用することと、attachInterrupt関数で、このpin2を意味する”0”、呼び出す関数、pinの状態、を指定します。
この場合は、0 = pin2を監視して、HIGHになったとき、manual_supplyという関数を呼び出します。
========================================
void setup (){}
void loop (){}
void manual_supply() {
Tsw = 1;//タクトスイッチON
}
========================================
次に、void loopの外にこの呼び出す関数を定義します。
ここではTswというタクトスイッチの状態を示す定数を "1"に変更する指定をしました。
========================================
void loop (){
if (Tsw == 1) {
analogWrite(POMP, power); //ポンプON
delay(mizu);
Serial.println("water supply" );
analogWrite(POMP, 0);
Tsw = 0;
}
========================================
void loopの中に、このTswによっての動作を記述します。
ポンプをONにし、水遣り時間を経過の値ポンプをOFFにします。
また、Tswを 0 にリセットします。
ここで、間違いやすいことが "==" はifなどの中で、条件一致を示し、"=" は、この定数を書き換えることを意味します。
ifの中で = を使ってしまうと、ここで書き替えが起こってしまって思い道理に動かないので注意です。
このようにして、まだ一部完全ではないですが、一通りの自動水遣り装置が出来上がりました。
これまでは時間経過をdelayのみで記述しましたが、タクトスイッチの監視をする必要があるため
========================================
int cycle = 200; //水遣りチェック周期
========================================
を定義し、
========================================
int CHECK = 30 * 1000; //水やりカウント倍率
========================================
によって、
cycle * CHECK = 土壌状態更新周期
となるように設計しました。
こうすることで、スイッチが押されたときはすぐに水遣りを実施し、一方、土壌センサの読み値が変化したときは土壌状態更新周期が来たときに更新を実施します。
========================================
if (check > CHECK / 10) { //給水スキップ倍率10倍
========================================
thresholdを超えたときは加速的に水遣りをします。
======================プログラム全文ここから============
float regist = 600; //土壌抵抗
int power = 255; //ポンプpwm
int threshold = 800; //水遣り敷居値 (実装800、テスト700)
int GREEN = A1;
int YELLOW = A2;
int RED = A3;
int POMP = 5;
int LED = 150;
int cycle = 200; //水遣りチェック周期
int check = 0; //水遣り実行周期繰り返しカウント
int CHECK = 30 * 1000; //水やりカウント倍率
//cycle * CHECK = 土壌状態更新周期
int aveNum = 10;//平均化のサンプリング数
int aveCycle = 300; //平均化サンプリング周期(ms)
int retry = 0; //水遣りRetryカウント
int retryMax = 3; //水遣り繰り返しMax
int ReWait = 12000; //水遣り繰り返しのwait(実装12*1000、テスト3000)
int mizu = 3000; //水遣り動作時間
int Tsw = 0; //タクトスイッチ
int manual_s = 0;
void setup() {
Serial.begin(9600); //シリアルモニタを使う(カッコ内は通信速度)
pinMode(A0, INPUT); //土壌抵抗Read
pinMode(5, OUTPUT); //電圧を印可する宣言
pinMode(A1, OUTPUT); //GREEN
pinMode(A2, OUTPUT); //YELLOW
pinMode(A3, OUTPUT); //RED
pinMode(2, INPUT); //割り込みピン(タクトスイッチ)
attachInterrupt(0, manual_supply, HIGH);
// attachInterrupt(1, manual_supply, HIGH) 割り込みNo.1 = Pin2(Leonardo)
//attachInterrupt(0, manual_supply, HIGH) 割り込みNo.0 = Pin2(Uno)
}
void loop() {
float REGIST = 0; //平均計算のための中間の数値を格納
int i; //繰り返しのためのカウンター
for (i = 0 ; i < aveNum; i++) {
regist = analogRead(A0);
REGIST = REGIST + regist; //読み値を足し合わせ合計していく
// Serial.println(regist);
// Serial.print(",");
// Serial.println(REGIST);
delay(aveCycle);
}
regist = REGIST / aveNum; //合計から平均を算出しregistとして出力
Serial.print("A0 = regist = ");
Serial.println(regist);
Serial.print("threshold = ");
Serial.println(threshold);
Serial.print("cycle = ");
Serial.println(cycle);
Serial.print("Retry = ");
Serial.println(retry);
Serial.print("POMP = ");
Serial.println(power);
Serial.print("Tsw =" );
Serial.println(Tsw);
Serial.print("check =");
Serial.println(check);
if (check > CHECK) {
check = 0;
}
else if (Tsw == 1) {
analogWrite(POMP, power); //ポンプON
delay(mizu);
Serial.println("water supply" );
analogWrite(POMP, 0);
Tsw = 0;
check = 0;
}
else if (regist > 1021) //センサーエラー
{ analogWrite(RED, LED);
delay(100);
analogWrite(POMP, 0);
analogWrite(GREEN, 0);
analogWrite(YELLOW, 0);
analogWrite(RED, 0);
delay(100);
}
else if (retry > 2) //Rety 3回で土壌水分が上がらないとき
{ analogWrite(RED, LED);
delay(100);
analogWrite(POMP, 0);
analogWrite(GREEN, 0);
analogWrite(YELLOW, 0);
analogWrite(RED, 0);
delay(100);
Serial.println("Water supply ERROR !!");
if (regist <= threshold) { //小なりイコール
retry = 0;
}
else {}
}
else if (regist > threshold) { //給水
if (check > CHECK / 10) { //給水スキップ倍率
analogWrite(GREEN, 0);
analogWrite(YELLOW, 0);
analogWrite(RED, LED);
analogWrite(POMP, power); //ポンプON
delay(mizu);
Serial.println("water supply" );
analogWrite(POMP, 0);
Tsw = 0;
retry = retry + 1;
delay(ReWait);
}
else {
analogWrite(GREEN, 0);
analogWrite(YELLOW, 0);
analogWrite(RED, LED);
Serial.println("red" );
check++;
}
}
else if (regist > threshold - 200)
{
analogWrite(GREEN, 0);
analogWrite(YELLOW, LED);
analogWrite(RED, 0);
delay(cycle);//更新間隔の設定
retry = 0;
check++;
}
else if (regist > 100) {
analogWrite(GREEN, LED);
analogWrite(YELLOW, 0);
analogWrite(RED, 0);
delay(cycle);//更新間隔の設定
retry = 0;
check++;
}
else {
analogWrite(RED, LED);
delay(100);
analogWrite(POMP, 0);
analogWrite(GREEN, 0);
analogWrite(YELLOW, 0);
analogWrite(RED, 0);
delay(100);
}
}
void manual_supply() {
Tsw = 1;//タクトスイッチON
}
======================プログラム全文ここまで============
**一部使われていない定数やコードがあるかもしれません。