Arduinoが転がっていたので自動水やり機に改造してやった
こんにちは、今年のGWは新型コロナウイルスの影響により様々なことが自粛となりました。かくいう私も初めてのコミケ参加を予定していたのですが、なくなってしまいました。 どこにも行けないので、Tinderで無理やりにでも遊ぼうかと思いましたが... まぁ流石にやりません...
やることもないとなると、部屋の掃除をするのはベタですね。 掃除をしていたらこいつが部屋から出てきました。
Arduino Duemilanoveです、なんて読むのかわかりません。 THE ArduinoのUNO R3の前身です。 回路はあまり詳しくないのですが、USBを認識するモジュールがFTDI FT232RLとATmega16U2という違いがあるくらいでしょうか? メインマイコンは328Pであり同じです。
一生ホコリをかぶるのも可愛そうなので、なにか動かしてやろうかと考えること1分、思いつきます。
「自動水やり機だ!!!」
「車輪の再発明!」
変なことを思いついた私を止められるものはいません、Amazonで土壌センサ+ポンプのセットを購入しました。
以下、準備したものです。
・マイコン (Arduino Duemilanove)
・土壌センサ (https://www.amazon.co.jp/gp/product/B07VKSTF78/ref=ppx_yo_dt_b_asin_title_o00_s01?ie=UTF8&psc=1)
・ポンプ+リレー(https://www.amazon.co.jp/gp/product/B07VKSTF78/ref=ppx_yo_dt_b_asin_title_o00_s01?ie=UTF8&psc=1)
・育てる植物(¥298のテーブルヤシにしました)
・固定するケース等
・トランジスタ(2SC1815)
・基板や配線
プログラムも以下のように適当に書きました。
// 自動水やり機
// made by psmofi
#include <MsTimer2.h> /*[ タイマーヘッダ ]*/
#include <EEPROM.h> /*[ 内蔵EEPROMヘッダ ]*/
/*[[ 定義 ]]*/
#define SOIL_INPUT 0 // 土壌センサ アナログ入力 A0ピン
#define PUMP_OUTPUT 7 // ポンプ デジタル出力 7ピン
#define SOIL_THRESHOLD 350 // 土壌センサしきい値
#define TIMER_INTERVAL 3600000 // 時間間隔(ms)
#define LEAST_INTERVAL_TIME 18 // 最小インターバル時間
#define EEPROM_ADDR 100 // EEPROMアドレス
/*[[ グローバル変数 ]]*/
volatile int soilVal; // 土壌センサ値
volatile bool watering = false; // 水やり可否(初期値:否)
unsigned char wateringCnt; // 水やり回数
volatile int progTime; // 経過時間(h)
/*[[ プロトタイプ宣言 ]]*/
void DoWatering(void); // 水やり開始関数
void StopWatering(void); // 水やり終了関数
void sensingSoil(void); // 土壌センサ(割り込み)
// setup関数
// 初回のみ実行
void setup() {
/*[ ピンの入出力を設定 ]*/
pinMode(PUMP_OUTPUT,OUTPUT); // ポンプピンを出力に設定
/*[ デフォルトは水やりはしない ]*/
StopWatering();
// デバッグ用シリアル出力設定
Serial.begin(9600);
// タイマーをTIMER_INTERVAL間隔でセットしてスタートする
MsTimer2::set(TIMER_INTERVAL, sensingSoil); // TIMER_INTERVALmsの期間
MsTimer2::start();
// 初回のセンサの値を入力する
soilVal = analogRead(SOIL_INPUT);
// 水やり回数をEEPROMから引き抜いてくる
wateringCnt = EEPROM.read(EEPROM_ADDR);
// 経過時間を0で設定
progTime = (int)0;
}
// loop関数
// 無限に実行
void loop() {
/*[ 土壌センサ値表示 ]*/
Serial.print("土壌センサ値:");
Serial.println(soilVal);
/*[ 水やり回数表示 ]*/
Serial.print("累計水やり回数:");
Serial.println(wateringCnt);
/*[ インターバル時間表示 ]*/
Serial.print("インターバル時間:");
Serial.println(wateringCnt);
delay(1000);
/*[ 水やり判定が可になっていれば、水やりする ]*/
if( watering == true ){
// 水やり
DoWatering();
// 5s Wait
delay(5000);
// 水やり終了
StopWatering();
// 水やり判定をfalseにする。
watering = false;
// 水やり回数をインクリメントし、EEPROMに書き込む
wateringCnt++;
EEPROM.write(EEPROM_ADDR,wateringCnt);
}
}
/*[ 水やり開始 ]*/
void DoWatering(void){
digitalWrite(PUMP_OUTPUT,HIGH);
}
/*[ 水やり終了 ]*/
void StopWatering(void){
digitalWrite(PUMP_OUTPUT,LOW);
}
/*[ 土壌センサ値の入力(割り込み) ]*/
void sensingSoil(void){
// センサの値を入力する
soilVal = analogRead(SOIL_INPUT);
// しきい値を超えていた場合、
if( soilVal < SOIL_THRESHOLD ){
// 経過時間がまだ残ってれば
if( progTime < (int)LEAST_INTERVAL_TIME ){
// 1時間経過
progTime++;
// 経過時間が0なら
}else{
// 水やりを可にする。
watering = true;
// インターバル時間を0にする
progTime = (int)0;
}
}
}
土壌センサ値が一定の乾きになり、18hrが経過したら5sほど水やりをするプログラムです。
内蔵のEEPROMに水やり回数を記録することで、何回水やりをやったのかがわかるようになっています。
適当に組み立ててみました。
なんとか完成?
ちなみに条件を満たしてポンプ動作をするとおそらくですがリレーのノイズでArduinoにリセットがかかり、何度かポンピングをしてしまいます。 別電源、フォトカプラを使ってGND分離しないと満足した動作はしないようです。
また、現在は条件を満たせばいつでも水やりをしてしまいますが、RTCを使えば条件を満たした朝7時に水やりをするなどが可能になります。 また余裕があったらやってみます。