工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Manufacturing Technology >> 製造プロセス

スマート灌漑コントローラー

コンポーネントと消耗品

>
Arduino Nano R3
× 1
IOエキスパンダー
× 1
IOエキスパンダーバンドル
× 1

アプリとオンラインサービス

>
Arduino IDE

このプロジェクトについて

Arduinoでスマート灌漑コントローラーを作成する

動的な水循環で庭をインテリジェントに灌漑します。雨が降っている場合、または最後の水やり以降に雨が降った場合は、庭への水やりをやめてください。光センサーを使用して日の出時刻を検出し、それに応じて水の開始時刻を自動的に調整します。寒すぎる場合は、庭に水をやるのをやめてください。

機能リスト

  • 外気温センサー
  • 外部雨センサー
  • 外光センサー
  • 毎週のスケジュール設定用の電池式リアルタイムクロック
  • 不揮発性ストレージ-電力損失のために散水を失うことはありません
  • 日の出の検出
  • スマートな散水は水道代を節約します
  • 適切な浸漬時間を確保するために、日の出前に水をまきます
  • 外が寒すぎるときは水やりをやめてください
  • 真菌の増殖を抑える
  • 簡単なスケジュール管理
<図>

スマート灌漑コントローラーを構築するために必要な部品

  • IOエキスパンダー
  • x21-I2Cに配線します。
  • 1-Wireジャンクション
  • 光コネクタ
  • スプリッター
  • ArduinoNano。
  • 4チャンネルDC5Vリレー。
  • TSL2561光センサー。
  • DS18B20防水温度センサー。
  • 光学式赤外線水位センサー。
  • DS3231 AT24C32IIC高精度リアルタイムクロック。
  • I2C SSD1306 OLED128x64ディスプレイ。
  • 200x120x75mmの透明な防水プラスチックエンクロージャ。
  • 100x68x50mmの透明な防水プラスチックエンクロージャ。
  • ip68pg7防水ナイロンケーブルグランド。
  • ip68pg11防水ナイロンケーブルグランド。
  • RJ11キーストーンネジ留め式端子ジャック。
  • 50フィート4C4PRJ11ワイヤー。
  • 6フィート4C4PRJ11ワイヤー。
  • 2.54mmヘッダーワイヤー。
  • x22ピンSPSTモーメンタリプッシュボタンマイクロスイッチ
  • 12VDC1Aウォールアダプター電源。

配線図

<図>

OLEDディスプレイ

<図>

メニューボタンを押してメニューを表示し、ボタンを押し続けるとすべてのメニューオプションが切り替わります。メニューは、30秒間操作がないと自動的に削除されます。選択ボタンを押して、目的のメニュー機能を実行します。

では、なぜIOエキスパンダーを使用するのですか?

  • 設計が簡単
  • 既製の部品
  • 書き込む1-Wireドライバーはありません
  • 書き込むDS3231RTCドライバーはありません
  • 書き込むEEPROMドライバーがありません
  • 書き込むOLEDディスプレイドライバーはありません
  • Arduinoコードスペースを取るための表示フォントはありません
  • 書き込む温度センサードライバーがありません
  • 書き込み用の光学式雨センサー乾燥機はありません
  • Arduinoのコードスペースを節約します。わずか12710バイト(39%)
  • コードを書くのにたった3日
  • 標準のRJ11電話ケーブルを使用して簡単に配線できます
  • センサーケーブルの長さの問題はありません
  • 同様の商用システムよりも構築が安価
  • 個々の要件に合わせて簡単に変更できます
  • 単一電源

システムを構築する

ArduinoNanoをIOExpanderに接続し、次のコードでプログラムします。 6ピンヘッダーはソフトウェアのシリアルデバッグポートであり、最終的なインストールでは必要ありません。

<図>

ONEWIRE_TO_I2C_ROM1およびONEWIRE-TO_I2C_ROM2で定義されたアドレスを、1-WireからI2Cアドレスに一致するように変更してください。

  / * IOエキスパンダースケッチの最適化
*
* Irrigation System v1.1
*
* /

#include
#include //ファイルの場所\ Program Files(x86)\ Arduino \ hardware \ tools \ avr \ avr \ include \ time.h
#include
#include
#include
#include "IOExpander.h"

#define FAHRENHEIT
#define INIT_BOARD "g5w1; g11w1; g11d0,75; g12w1; g12d0,75; rsf"
#define ONEWIRE_TO_I2C_ROM1 "i4scc"
#define ONEWIRE_TO_I2C_ROM2 "i6s8f" "t6s0300"
#define RTC_SENSOR "s4te"
#define I2C_EEPROM "s4tf"
#define I2C_OLED "s4t10"
#define I2C_LIGHT "s3t9; sc0"
# define OPTICAL_SENSOR "g5a"
#define BUTTON1 "g11d"
#define BUTTON2 "g12d"

#define WATER_TIME_BEFORE_SUNRISE 60
#define SUNRISE_LUX 100
# d efine RAIN_DETECT_LEVEL 4.0
#define DO_NOT_WATER_TEMP 4.4444 // 40F

#define MAX_ZONES 4

#define HOUR_IN_DAY 24L
#define MIN_IN_HOUR 60L
#define SEC_IN_MIN 60L
#define SEC_IN_HOUR(MIN_IN_HOUR * SEC_IN_MIN)
#define SEC_IN_DAY(HOUR_IN_DAY * SEC_IN_HOUR)
#define DAYS_IN_WEEK 7
#define SEC_IN_ />
#define SUN 0x01
#define MON 0x02
#define TUE 0x04
#define WED 0x08
#define THR 0x10
#define FRI 0x20
#define SAT 0x40
#define EVERYDAY(SUN | MON |火|水曜日| THR | FRI | SAT)

#define SUNRISE 0x80

#define MENU_OPTIONS 9
#define MENU_TIME 30

#define OFF 0
#define ON 1

#define STATE_ON_OFF 0x01

//#define SERIAL_DEBUG

#ifdef SERIAL_DEBUG
SoftwareSerial swSerial(8,7 );
#endif

char weekday [] [4] ={"SUN"、 "MON"、 "TUE"、 "WED"、 "THU"、 "FRI"、 " SAT "};

char menu [] [13] ={" Next "、
" Water "、
" Reset "、
" Clock Min + " 、
"Clock Min-"、
"Clock Hour +"、
"Clock Hour-"、
"Sunrise"、
"ON / OFF"};

enum {
MENU_NEXT、
MENU_WATER、
MENU_RESET、
MENU_CLOCK_MIN_PLUS、
MENU_CLOCK_MIN_MINUS、
MENU_CLOCK_HOUR_PLUS、
MENU_CLOCK_HOUR_MINUS、
MENU_SUNRISE、
MENU_ON_OFF
};

typedef struct {
char description [16];
uint8_t relay;
} ZONE;

typedef struct {
uint8_t zone;
uint8_t days;
int8_t hour;
int8_t min;
uint8_t duration;
}スケジュール;

typedef struct {
time_t sunrise_time;
time_t last_water_time;
uint8_t water_schedule;
uint8_t water_duration;
uint8_t rain [MAX_ZONES];
uint8_t state;
uint8_t crc;
} NVRAM;

enum {
ZONE1、
ZONE2、
ZONE3、
ZONE4
};

enum {
RELAY1 =1、
RELAY2、
RELAY3、
RELAY4
};

ZONE zone [] ={
{"Front Right"、RELAY1}、
{"Front Left"、RELAY2}、
{"Bushes"、RELAY3} 、
{"Left Side"、RELAY4}、
};

SCHEDULE schedule [] ={
{ZONE1、SUNRISE | EVERYDAY、-1、0、4}、
{ZONE2、EVERYDAY、6、15、5}、
{ZONE3、EVERYDAY、6、0、10}、
{ZONE4、EVERYDAY 、6、10、6}、
};

NVRAM nvram;
bool update_nvram =false;

uint8_t crc8(uint8_t * data、uint16_t長さ)
{
uint8_t crc =0;

while(length-){
crc =_crc8_ccitt_update(crc、* data ++);
}
return crc;
}

int led =13;
bool init_oled =true;
bool update_oled =true;
bool init_board =true;

#ifdef FAHRENHEIT
#define C2F(temp)CelsiusToFahrenheit(temp)
float CelsiusToFahrenheit(float celsius)
{
return((celsius * 9)/ 5)+ 32;
}
#else
#define C2F(temp)(temp)
#endif

void SerialPrint( const char * str、float decimal、char error)
{
Serial.print(str);
if(error)Serial.print(F( "NA"));
else Serial.print(decimal、1);
}

time_t NextScheduleT ime(time_t last_time、uint8_t * next_schedule)
{
time_t next_time =-1;
time_t clk_time;
uint8_t i;
tm clk;
uint8_t wday;

for(i =0; i if(schedule [i] .days&SUNRISE){
clk_time =nvram.sunrise_time;
clk_time + =schedule [i] .hour * SEC_IN_HOUR;
clk_time + =schedule [i] .min * SEC_IN_MIN;
localtime_r(&clk_time、&clk);
}
else {
localtime_r(&last_time、&clk);
clk。 tm_hour =schedule [i] .hour;
clk.tm_min =schedule [i] .min;
clk.tm_sec =0;
clk_time =mktime(&clk);
}
wday =clk.tm_wday;
while(clk_time <=last_time ||!(schedule [i] .days&(1 < {
clk_time + =SEC_IN_DAY;
if(++ wday> SATURDAY)wday =SUNDAY;
if(wday ==clk.tm_wday)break; // 1週間のみチェック
}
if(clk_time next_time =clk_time;
* next_schedule =i;
}
}
return next_time;
}

void StartScheduleTime(time_t start_time、uint8_t start_schedule)
{
uint8_t i;

nvram。 last_water_time =start_time;
nvram.water_schedule =start_schedule;
nvram.water_duration =schedule [start_schedule] .duration + 1;
update_nvram =true;
//雨が降ったかどうかを確認
i =schedule [start_schedule] .zone;
if(i 0){
if(nvram.rain [i]> nvram.water_duration)nvram .water_duration =0;
else nvram.water_duration- =nvram.rain [i];
nvram.rain [i] =0;
}
}

void WaterScheduleTime(void)
{
uint8_t i;

nvram.water_duration--;
update_nvram =true;
i =スケジュール[ nvram.water_schedule] .zone;
if(i Serial.print ( "r");
Serial.print(zone [i] .relay);
if(nvram.water_duration> 0)Serial.println( "o");
elseSerial。 println( "f");
SerialReadUntilDone();
}
}

void setup(){
Serial.begin(115200);
#ifdef SERIAL_DEBUG
swSerial.begin(115200);
#endif
pinMode(led、OUTPUT);
// delay(1000);
wdt_enable (WDTO_8S);
}

void loop(){
static tm rtc;
tm clk、sunrise_clk;
time_t rtc_time;
time_t clk_time;
static time_t next_time;
static uint8_t last_sec;
static uint8_t last_min;
bool error_rtc;
bool error_light;
bool error_temp;
static long lux =0;
static float temp、rain;
static uint8_t sunrise_counter =MIN_IN_HOUR;
static bool check_sunrise =false;
uint8_t i;
static bool read_nvram =true;
static time_t water_time;
static uint8_t water_schedule;
uint8_t sz;
uin t8_t wday;
long n;
bool button1、button2;
static int8_t menu_select =-1;
static time_t menu_time =0;

シリアル。 println();
if(SerialReadUntilDone()){
if(init_board){
SerialCmdDone(INIT_BOARD);
init_board =false;
}

if(init_oled){
if(SerialCmdNoError(ONEWIRE_TO_I2C_ROM1)){
SerialCmdDone(I2C_OLED "; si; sc; sd");
init_oled =false;
}
}

if(SerialCmdDone(RTC_SENSOR)){
error_rtc =!SerialReadTime(&rtc);
if(!error_rtc){
clk =rtc; // mktime()はstructtmを変更できます
rtc_time =mktime(&clk);
localtime_r(&rtc_time、&rtc); // wdayを取得します。
}

if(read_nvram){
if(SerialCmdNoError(I2C_EEPROM)){
SerialReadEEPROM((uint8_t *)&nvram、0、sizeof (nvram));
if(nvram.crc!=crc8((uint8_t *)&nvram、sizeof(nvram)-sizeof(uint8_t))){
//swSerial.println("CRC8失敗! ");
// nvramを初期化します
memset(&nvram、0、sizeof(nvram));
clk =rtc;
clk.tm_hour =6;
clk .tm_min =0;
clk.tm_sec =0;
nvram.sunrise_time =mktime(&clk);
if(nvram.sunrise_time update_nvram =true;
}
//最後の水時間を1週間以上確認します
if(rtc_time --nvram.last_water_time> SEC_IN_WEEK)nvram.last_water_time =rtc_time --SEC_IN_WEEK;
//日の出時刻を確認します
if(rtc_time> nvram.sunrise_time){
localtime_r(&nvram.sunrise_time、&sunrise_clk);
clk =rtc;
clk.tm_hour =sunrise_clk.tm_hour;
clk.tm_min =sunrise_clk.tm_min;
clk.tm_sec =sunrise_clk.tm_sec;
nvram.sunrise_time =mktime(&clk);
if(nvram.sunrise_time }
if(nvram.water_duration) {
nvram.water_duration ++;
water_time =nvram.last_water_time;
}
else {
clk_time =(nvram.last_water_time)? nvram.last_water_time:rtc_time;
water_time =NextScheduleTime(clk_time、&water_schedule);
}
read_nvram =false;
}
}
}

//毎分1回だけ処理します
if(rtc.tm_min!=last_min)
{
// 1-Wire温度測定を要求します。後で読んでください。
error_temp =!SerialCmdNoError(ONEWIRE_TEMPERATURE);
if(!error_temp)SerialCmdDone( "tt");

error_light =!SerialCmdNoError(ONEWIRE_TO_I2C_ROM2 "; oo0" );
if(!error_light){
SerialCmdDone(I2C_LIGHT); //オーバードライブを使用しない
SerialCmd( "sr");
SerialReadInt(&lux);
SerialReadUntilDone();
}

if(SerialCmd (OPTICAL_SENSOR)){
SerialReadFloat(&rain);
SerialReadUntilDone();
}

error_temp =!SerialCmdNoError(ONEWIRE_TEMPERATURE);
if(! error_temp){
SerialCmd( "tr");
SerialReadFloat(&temp);
SerialReadUntilDone();
}

//日の出ですか?
if(lux if(sunrise_counter> 0)sunrise_counter--;
else check_sunrise =true;
}
else {
if (sunrise_counter sunrise_counter ++;
if(check_sunrise &&sunrise_counter ==MIN_IN_HOUR){
nvram.sunrise_time =rtc_time +(SEC_IN_DAY --SEC_IN_HOUR);

update_nvram =true;
}
}
}

//雨が降っていますか?
if(rain <=RAIN_DETECT_LEVEL){
for(i =0; i if(nvram.rain [i] <-1)nvram.rain [i] ++;
}
update_nvram =true;
}

//スケジュールを確認
if(menu_select ==-1 &&!nvram.water_duration){
while(water_time +(schedule [water_schedule] .duration * SEC_IN_MIN) water_time =NextScheduleTime(water_time、&water_schedule);
}
if(water_time <=rtc_time){
StartScheduleTime(water_time、water_schedule);
if(temp <=DO_NOT_WATER_TEMP | | nvram.state&STATE_ON_OFF ==OFF)
nvram.water_duration =0;
}
}

//水をやる必要がありますか?
if(nvram.water_duration){
WaterScheduleTime();
if(!nvram.water_duration)
water_time =NextScheduleTime(water_time、&water_schedule);
}

last_min =rtc.tm_min;
update_oled =true;
}

//ボタンをチェック
button1 =SerialReadButton(BUTTON1);
if(button1){
if(menu_select ==-1)menu_select =0;
else {
if(++ menu_select> =MENU_OPTIONS)
menu_select =0;
}
menu_time =rtc_time;
update_oled =true;
}
if( menu_select> =0){
button2 =SerialReadButton(BUTTON2);
if(button2){
clk_time =rtc_time;
switch(menu_select){
case MENU_NEXT:
case MENU_RESET:
if(nvram.water_duration){
nvram.water_duration =1;
WaterScheduleTime();
}
water_time =NextScheduleTime(( menu_select ==MENU_NEXT)? water_time:rtc_time、&water_schedule);
break;
case MENU_WATER:
StartScheduleTime(water_time、water_schedule);
WaterScheduleTime();
break;
case MENU_CLOCK_MIN_PLUS:
clk_time + =SEC_IN_MIN;
break;
case MENU_CLOCK_MIN_MINUS:
clk_time- =SEC_IN_MIN;
break;
case MENU_CLOCK_HOUR_PLUS:
clk_time + =SEC_IN_HOUR;
break;
case MENU_CLOCK_HOUR_MINUS:
clk_time- =SEC_IN_HOUR;
break;
case MENU_ON_OFF:
nvram.state ^ =STATE_ON_OFF;
update_nvram =true;
break;
}
if(clk_time!=rtc_time){
if(SerialCmdDone(RTC_SENSOR)){
localtime_r( &clk_time、&clk);
SerialWriteTime(&clk);
rtc_time =clk_time;
}
}
menu_time =rtc_time;
update_oled =true;
}
}
if(menu_select> =0 &&rtc_time --menu_time> MENU_TIME){
menu_select =-1;
update_oled =true;
}

if(update_oled){
if(SerialCmdNoError (ONEWIRE_TO_I2C_ROM1)){
Serial.print( "st10; so1; sc; sf0; sa0; sd0,0、\" ");
if(nvram.water_duration)Serial.print(nvram.water_duration );
else {
if((nvram.state&STATE_ON_OFF)==OFF)Serial.print( "OFF");
else if(rain <=RAIN_DETECT_LEVEL)Serial.print( "Rain");
else if(temp <=DO_NOT_WATER_TEMP)Serial.print( "Cold");
else Serial.print( "v1.1");
}
Serial.print( "\"; sf2; sa1; sd75,0、\ "");
if(menu_select ==7){//日の出
clk_time =nvram.sunrise_time;
localtime_r(&clk_time、&clk);
}
else clk =rtc;
Serial.print(clk.tm_hour-((clk.tm_hour> 12)?12:0));
Serial.print( " : ");
if(clk.tm_min <10)Serial.print(" 0 ");
Serial.print(clk.tm_min);
Serial.println(" \ "" );
SerialReadUntilDone();

Serial.print( "sf1; sa0; sd79,8、\" ");
Serial.print((clk.tm_hour> 12 )? "PM": "AM");
Serial.print( "\"; sf0; sa1; sd127,1、\ "");
Serial.print(weekday [clk.tm_wday] );
Serial.print( "\"; sd127,13、\ "");
Serial.print(clk.tm_mon + 1);
Serial.print( "/");
Serial.print(clk.tm_mday);
Serial.println( "\" ");
SerialReadUntilDone();

Serial.print(" sf0; sa0; sd1,36、\ "");
i =schedule [water_schedule] .zone;
if(i localtime_r(&water_time、&clk);
if(water_time --rtc_time> SE C_IN_DAY){
Serial.print( "\"; sa1; sd126,36、\ "");
Serial.print(clk.tm_mon + 1);
Serial.print( " / ");
Serial.print(clk.tm_mday);
Serial.print(" ");
Serial.print(clk.tm_hour-((clk.tm_hour> 12)? 12:0));
Serial.print( ":");
if(clk.tm_min <10)Serial.print( "0");
Serial.print(clk。 tm_min);
Serial.print( "");
}
else {
Serial.print( "\"; sf1; sa1; sd111,30、\ "");
Serial.print(clk.tm_hour-((clk.tm_hour> 12)?12:0));
Serial.print( ":");
if(clk.tm_min <10)Serial.print( "0");
Serial.print(clk.tm_min);
Serial.print( "\"; sf0; sd126,36、\ "");
}
Serial.print((clk.tm_hour> 12)? "PM": "AM");
if(nvram.water_duration)Serial.print( "\"; so2; sc0、 29,128,19 ");
Serial.println();
SerialReadUntilDone();

if(menu_select ==-1){
//Serial.print( "\"; sa0; sd0,52、\ "");
//Serial.print( rain);
SerialPrint( "\"; so1; sa2; sd63,52、\ ""、C2F(temp)、error_temp);
if(!error_temp)Serial.print( "\"、 248、\ ""
#ifdef FAHRENHEIT
"F"
#else
"C"
#endif
);
シリアル。 print( "/");
Serial.print(lux);
}
else {
Serial.print( "\"; so0; sc0,51,128,14; sf0; sa2; sd63,52、\ "");
if(menu_select ==MENU_ON_OFF){
Serial.print((nvram.state&STATE_ON_OFF)? "OFF": "ON");
}
else Serial.print(menu [menu_select]);
}
Serial.println( "\"; sd ");
SerialReadUntilDone();
update_oled =false;
}
else init_oled =true;
}

if(update_nvram){
if(SerialCmdNoError(I2C_EEPROM)){
nvram.crc =crc8((uint8_t *)&nvram、sizeof(nvram)-sizeof(uint8_t));
//swSerial.println(nvram.crc 、HEX);
SerialWriteEEPROM((uint8_t *)&nvram、0、sizeof(nvram));
update_nvram =false;
}
}

delay(50);
}
else {
digitalWrite(led、HIGH);
delay(500);
digitalWrite(led、LOW);
delay(500);
init_board =true;
init_oled =true;
}
wdt_reset();
}

注: USBポートを使用してArduinoNanoをプログラムする場合は、IO Expanderから切断する必要があります。これは、同じ単一のシリアルポートも使用しているためです。代わりに、デバッグする場合は、ICSPポートを使用してATmega328Pをプログラムします。ソフトウェアデバッグポートを有効にするには、SERIAL_DEBUG定義のコメントを解除します。

スプリッタは、最初に光赤外線センサーデータラインを1-Wireリモートセンサーラインから分離するように構成する必要があります。 R2のゼロオーム0603抵抗器にはんだ付けします。

<図>

PG7およびPG11の右側にある、小さいエンクロージャーに7/16 "の穴を開け、大きいエンクロージャーに11/16"の穴を開けます。ドレメルツールを使用して、グランドがぴったり合うまで穴を少し拡大します。 PG7は、リモートセンサーとPG11を12VDC、24VAC、マニホールドワイヤー、およびRJ11リモートセンサーワイヤーに供給します。

<図>

SPSTモーメンタリプッシュボタンマイクロスイッチを配線し、RJ11ネジ留め式端子に接続します。熱収縮チューブを使用して接点を絶縁します。

<図>

すべてのワイヤーを接続し、すべての部品を組み立て/フィードして大きなエンクロージャーに入れます。リモートセンサー用の50フィートのRJ11ワイヤーは、PG11グランドを切断せずにぴったりとはまるはずです。

<図>

光学赤外線水センサー用に小さなエンクロージャーの上面に9/16 "の穴を開けます。ドレメルツールを使用して、センサーが収まるまで穴を少し拡大します。小さなリモートセンサーエンクロージャーはぴったりとはまりますが、中身がRJ11ワイヤーをできるだけ短くすると、すべてを小さなエンクロージャーに詰め込むのに役立ちます。組み立てたら、ナットをねじ込む前に、グランドナットウォッシャーにマリングルーを追加することをお勧めします。より良いシールを作成します。

<図>

リモートセンサーエンクロージャーを屋外に設置し、光学赤外線水センサーと光センサーを障害物なしで空に向けて、家の東側に持ち上げて取り付けます。

<図>

大きなエンクロージャーの上部中央下部に1/4 "の穴を開け、ボタンを取り付けます。ボタンが収まるまで、ドレメルツールを使用して穴を少し拡大します。

<図>

システムをテストし、すべてが正しく動作していることを確認します。リレーとセンサーをテストするには、ArduinoをIO Expanderから切断し、コンピューターに直接接続して手動で制御します。すべてが動作していることを確認したら、両面テープとパッキングフォームを使用してすべての部品をエンクロージャに組み立て、ボードを固定し、スマート灌漑コントローラーの利点と節約を享受します。

動作中のビデオ

2019年9月12日更新

システムが数日間電源を失った場合の起動の問題を修正したv1.1をリリースしました。

2019年10月2日更新

1-WireをI2C、DS3231、次にSSD1306 OLED画面に接続すると、下の丸で囲んだ画像に示すように、SDAラインとSCLラインに合計3つの異なるプルアップがあります。これにより、効果的に4.7k / 3 =1.56kのプルアップが発生し、強すぎて画面がランダムに破損する可能性があります。

<図>

DS3231は他のラインで使用されている抵抗パックを使用しているため、他のプルアップ抵抗を取り外します。

  • 1-I2CR3およびR4に配線します。
  • SSD1306 OLEDR6およびR7。

コード

  • スマート灌漑コントローラー
スマート灌漑コントローラー C / C ++
Arduinoを使用して、庭や庭にインテリジェントに水をまきます。
 / * IOエキスパンダースケッチの最適化** Irrigation System v1.1 * * /#include  #include  //ファイルの場所\ Programファイル(x86)\ Arduino \ hardware \ tools \ avr \ avr \ include \ time.h#include  #include  #include  #include "IOExpander。 h "#define FAHRENHEIT#define INIT_BOARD" g5w1; g11w1; g11d0,75; g12w1; g12d0,75; rsf "#define ONEWIRE_TO_I2C_ROM1" i4scc "#define ONEWIRE_TO_I2C_ROM2" i6s8f "#define define I2C_EEPROM "s4tf" #define I2C_OLED "s4t10" #define I2C_LIGHT "s3t9; sc0" #define OPTICAL_SENSOR "g5a" #define BUTTON1 "g11d" #define BUTTON2 "g12d" #define WATER_TIME_BEFORE_SU定義DO_NOT_WATER_TEMP4.4444 // 40F#define MAX_ZONES 4#define HOUR_IN_DAY 24L#define MIN_IN_HOUR 60L#define SEC_IN_MIN 60L#define SEC_IN_HOUR(MIN_IN_HOUR * SEC_IN_MIN)#define SEC_IN_DAY(HOUR_IN_DAY * SEC_IN_HOUR)#define DAYS_IN_WEEK TUE 0x04#define WED 0x08#define THR 0x10#define FRI 0x20#define SAT 0x40#define EVERYDAY(SUN | MON |火|水曜日| THR | FRI | SAT)#define SUNRISE 0x80#define MENU_OPTIONS 9#define MENU_TIME 30#define OFF 0#define ON 1#define STATE_ON_OFF 0x01 //#define SERIAL_DEBUG#ifdef SERIAL_DEBUGSoftwareSerial swSerial(8,7);#endifchar weekday [] [4] ={"SUN"、 "MON"、 "TUE"、 "WED"、 "THU"、 "FRI"、 "SAT"}; char menu [] [13] ={"Next"、 "Water"、 "Reset" 、 "Clock Min +"、 "Clock Min-"、 "Clock Hour +"、 "Clock Hour-"、 "Sunrise"、 "ON / OFF"}; enum {MENU_NEXT、MENU_WATER、MENU_RESET、MENU_CLOCK_MIN_PLUS、MENU_CLOCK_MIN_MINUS、MENU_CLOCK_HOUR_PLUS、 MENU_CLOCK_HOUR_MINUS、MENU_SUNRISE、MENU_ON_OFF}; typedef struct {char description [16]; uint8_tリレー;} ZONE; typedef struct {uint8_tゾーン; uint8_t日; int8_t時間; int8_t min; uint8_t duration;} SCHEDULE; typedef struct {time_t sunrise_time; time_t last_water_time; uint8_t water_schedule; uint8_t water_duration; uint8_t rain [MAX_ZONES]; uint8_t状態; uint8_t crc;} NVRAM; enum {ZONE1、ZONE2、ZONE3、ZONE4}; enum {RELAY1 =1、RELAY2、RELAY3、RELAY4}; ZONE zone [] ={{"Front Right"、RELAY1}、{"Front Left" 、RELAY2}、{"ブッシュ"、RELAY3}、{"左側"、RELAY4}、};スケジュールスケジュール[] ={{ゾーン1、サンライズ| EVERYDAY、-1、0、4}、{ZONE2、EVERYDAY、6、15、5}、{ZONE3、EVERYDAY、6、0、10}、{ZONE4、EVERYDAY、6、10、6}、}; NVRAM nvram; bool update_nvram =false; uint8_t crc8(uint8_t * data、uint16_t length){uint8_t crc =0; while(length-){crc =_crc8_ccitt_update(crc、* data ++); } return crc;} int led =13; bool init_oled =true; bool update_oled =true; bool init_board =true; #ifdef FAHRENHEIT#define C2F(temp)CelsiusToFahrenheit(temp)float CelsiusToFahrenheit(float celsius){return((celsius 9)/ 5)+ 32;}#else#define C2F(temp)(temp)#endifvoid SerialPrint(const char * str、float decimal、char error){Serial.print(str); if(エラー)Serial.print(F( "NA")); else Serial.print(decimal、1);} time_t NextScheduleTime(time_t last_time、uint8_t * next_schedule){time_t next_time =-1; time_t clk_time; uint8_t i; tm clk; uint8_t wday; for(i =0; i  SATURDAY)wday =SUNDAY; if(wday ==clk.tm_wday)break; // 1週間だけチェックします} if(clk_time  0){if(nvram.rain [i]> nvram.water_duration)nvram.water_duration =0;それ以外の場合、nvram.water_duration- =nvram.rain [i]; nvram.rain [i] =0; }} void WaterScheduleTime(void){uint8_t i; nvram.water_duration--; update_nvram =true; i =schedule [nvram.water_schedule] .zone; if(i  0)Serial.println( "o"); else Serial.println( "f"); SerialReadUntilDone(); }} void setup(){Serial.begin(115200); #ifdef SERIAL_DEBUG swSerial.begin(115200); #endif pinMode(led、OUTPUT); // delay(1000); wdt_enable(WDTO_8S);} void loop(){static tm rtc; tm clk、sunrise_clk; time_t rtc_time; time_t clk_time; static time_t next_time; static uint8_t last_sec; static uint8_t last_min; bool error_rtc; bool error_light; bool error_temp; static long lux =0;静的フロート温度、雨; static uint8_t sunrise_counter =MIN_IN_HOUR; static bool check_sunrise =false; uint8_t i; static bool read_nvram =true; static time_t water_time; static uint8_t water_schedule; uint8_t sz; uint8_t wday;長いn; bool button1、button2; static int8_t menu_select =-1; static time_t menu_time =0; Serial.println(); if(SerialReadUntilDone()){if(init_board){SerialCmdDone(INIT_BOARD); init_board =false; } if(init_oled){if(SerialCmdNoError(ONEWIRE_TO_I2C_ROM1)){SerialCmdDone(I2C_OLED "; si; sc; sd"); init_oled =false; }} if(SerialCmdDone(RTC_SENSOR)){error_rtc =!SerialReadTime(&rtc); if(!error_rtc){clk =rtc; // mktime()はstruct tm rtc_time =mktime(&clk);を変更できますlocaltime_r(&rtc_time、&rtc); // wdayを取得します。 } if(read_nvram){if(SerialCmdNoError(I2C_EEPROM)){SerialReadEEPROM((uint8_t *)&nvram、0、sizeof(nvram)); if(nvram.crc!=crc8((uint8_t *)&nvram、sizeof(nvram)-sizeof(uint8_t))){// swSerial.println( "CRC8 Failure!"); // nvram memset(&nvram、0、sizeof(nvram));を初期化しますclk =rtc; clk.tm_hour =6; clk.tm_min =0; clk.tm_sec =0; nvram.sunrise_time =mktime(&clk); if(nvram.sunrise_time  SEC_IN_WEEK)nvram.last_water_time =rtc_time --SEC_IN_WEEK; //日の出時刻を確認if(rtc_time> nvram.sunrise_time){localtime_r(&nvram.sunrise_time、&sunrise_clk); clk =rtc; clk.tm_hour =sunrise_clk.tm_hour; clk.tm_min =sunrise_clk.tm_min; clk.tm_sec =sunrise_clk.tm_sec; nvram.sunrise_time =mktime(&clk); if(nvram.sunrise_time  0)sunrise_counter--;それ以外の場合、check_sunrise =true; } else {if(sunrise_counter  =MENU_OPTIONS)menu_select =0; } menu_time =rtc_time; update_oled =true; } if(menu_select> =0){button2 =SerialReadButton(BUTTON2); if(button2){clk_time =rtc_time; switch(menu_select){case MENU_NEXT:case MENU_RESET:if(nvram.water_duration){nvram.water_duration =1; WaterScheduleTime(); } water_time =NextScheduleTime((menu_select ==MENU_NEXT)?water_time:rtc_time、&water_schedule);壊す;ケースMENU_WATER:StartScheduleTime(water_time、water_schedule); WaterScheduleTime();壊す;ケースMENU_CLOCK_MIN_PLUS:clk_time + =SEC_IN_MIN;壊す;ケースMENU_CLOCK_MIN_MINUS:clk_time- =SEC_IN_MIN;壊す;ケースMENU_CLOCK_HOUR_PLUS:clk_time + =SEC_IN_HOUR;壊す;ケースMENU_CLOCK_HOUR_MINUS:clk_time- =SEC_IN_HOUR;壊す;ケースMENU_ON_OFF:nvram.state ^ =STATE_ON_OFF; update_nvram =true;壊す; } if(clk_time!=rtc_time){if(SerialCmdDone(RTC_SENSOR)){localtime_r(&clk_time、&clk); SerialWriteTime(&clk); rtc_time =clk_time; }} menu_time =rtc_time; update_oled =true; }} if(menu_select> =0 &&rtc_time --menu_time> MENU_TIME){menu_select =-1; update_oled =true; } if(update_oled){if(SerialCmdNoError(ONEWIRE_TO_I2C_ROM1)){Serial.print( "st10; so1; sc; sf0; sa0; sd0,0、\" "); if(nvram.water_duration)Serial.print(nvram。 water_duration); else {if((nvram.state&STATE_ON_OFF)==OFF)Serial.print( "OFF"); else if(rain <=RAIN_DETECT_LEVEL)Serial.print( "Rain"); else if(temp <=DO_NOT_WATER_TEMP)Serial.print( "Cold"); else Serial.print( "v1.1");} Serial.print( "\"; sf2; sa1; sd75,0、\ ""); if(menu_select ==7){//サンライズclk_time =nvram.sunrise_time; localtime_r(&clk_time、&clk);} else clk =rtc; Serial.print(clk.tm_hour-((clk.tm_hour> 12)?12:0));シリアル。 print( ":"); if(clk.tm_min <10)Serial.print( "0"); Serial.print(clk.tm_min); Serial.println( "\" "); SerialReadUntilDone(); Serial.print( "sf1; sa0; sd79,8、\" "); Serial.print((clk.tm_hour> 12)?" PM ":" AM "); Serial.print(" \ "; sf0; sa1; sd127,1、\ ""); Serial.print(weekday [clk.tm_wday]); Serial.print( "\"; sd127,13、\ ""); Serial.print(clk.tm_mon + 1); Serial.print( "/"); Serial.print(clk.tm_mday); Serial.println( "\" "); SerialReadUntilDone(); Serial.print( "sf0; sa0; sd1,36、\" "); i =schedule [water_schedule] .zone; if(i  SEC_IN_DAY){Serial.print( "\"; sa1; sd126,36、\ ""); Serial.print(clk.tm_mon + 1); Serial.print( "/"); Serial.print(clk.tm_mday); Serial.print( ""); Serial.print(clk.tm_hour-((clk.tm_hour> 12)?12:0)); Serial.print( ":"); if (clk.tm_min <10)Serial.print( "0"); Serial.print(clk.tm_min); Serial.print( "");} else {Serial.print( "\"; sf1; sa1; sd111、 30、\ ""); Serial.print(clk.tm_hour-((clk.tm_hour> 12)?12:0)); Serial.print( ":"); if(clk.tm_min <10)Serial.print ( "0"); Serial.print(clk.tm_min); Serial.print( "\"; sf0; sd126,36、\ "");} Serial.print((clk.tm_hour> 12)? "PM" : "AM"); if(nvram.water_duration)Serial.print( "\"; so2; sc0,29,128,19 "); Serial.println(); SerialReadUntilDone(); if(menu_select ==-1){// Serial.print( "\"; sa0; sd0,52、\ ""); //Serial.print(rain); SerialPrint( "\"; so1; sa2; sd63,52、\ ""、C2F(temp)、error_temp); if(!error_temp)Serial.print( "\"、248、\ "" #ifdef FAHRENHEIT "F" #else "C" #endif); Serial.print( "/"); Serial.print(lux); } else {Serial.print( "\"; so0; sc0,51,128,14; sf0; sa2; sd63,52、\ ""); if(menu_select ==MENU_ON_OFF){Serial.print((nvram.state&STATE_ON_OFF)? "OFF": "ON"); } else Serial.print(menu [menu_select]); } Serial.println( "\"; sd "); SerialReadUntilDone(); update_oled =false;} else init_oled =true;} if(update_nvram){if(SerialCmdNoError(I2C_EEPROM)){nvram.crc =crc8((uint8_t * )&nvram, sizeof(nvram)-sizeof(uint8_t)); //swSerial.println(nvram.crc, HEX); SerialWriteEEPROM((uint8_t*)&nvram, 0, sizeof(nvram)); update_nvram =false; } } delay (50); } else { digitalWrite(led, HIGH); delay(500); digitalWrite(led, LOW); delay(500); init_board =true; init_oled =true; } wdt_reset();}

回路図

Intelligently water your yard or garden

製造プロセス

  1. オープンソースのスマート農業システムの設計
  2. スマートセンサーボードがエッジAI開発をスピードアップ
  3. SensorflareとRaspberryPiを備えた433MHzスマートホームコントローラー
  4. ラズベリーパイ温度センサー
  5. セルラーIoT:スマートゴミ箱
  6. スマートバーテンダー
  7. 感情センサー/ EEG
  8. 水分センサーを備えたWin10IOT灌漑コントローラー
  9. スマートテキスタイル用の超高感度で弾力性のあるセンサー
  10. スマートコンタクトレンズ用超薄型センサー
  11. スマート メカトロニクスが Sensata Technologies のセンサー製造を支援