Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Manufacturing Technology >> Productieproces

Arduino-gestuurde slimme irrigatiecontroller – Automatisch besproeien met weer- enlichtsensoren

Onderdelen en benodigdheden

Arduino Nano R3 × 1
IO Expander × 1
IO Expander Bundle × 1

Apps en online diensten

  • Arduino IDE

Over dit project

Maak een slimme irrigatiecontroller met Arduino

Besproei je tuin intelligente met dynamische besproeiingscycli. Stop met besproeien als het regent of heeft geregend sinds de laatste besproeiing. Gebruik de lichtsensor om zonsopgang te detecteren en de starttijden automatisch aan te passen. Stop besproeien als het te koud is buiten.

Functielijst

  • Buitentemperatuursensor
  • Regenbuitensensor
  • Lichtbuitensensor
  • Batterij-gebufferde real-time klok voor wekelijkse planning
  • Niet-vlatiel opslag – nooit een besproeiing verliezen door stroomuitval
  • Zonsopgangdetectie
  • Slimme besproeiing bespaart op de waterrekening
  • Besproei vóór zonsopgang voor optimale infiltratietijd
  • Stop besproeien bij te lage buitentemperatuur
  • Verminder schimmelgroei
  • Eenvoudige planningcontrole
Arduino-gestuurde slimme irrigatiecontroller – Automatisch besproeien met weer- enlichtsensoren

Benodigde onderdelen voor de slimme irrigatiecontroller

  • IO Expander
  • 2× 1-Wire naar I2C converter
  • 1-Wire Junction
  • Optische connector
  • Splitter
  • Arduino Nano
  • 4-kanaals 5V DC relais
  • TSL2561 lichtsensor
  • DS18B20 waterdichte temperatuursensor
  • Optische infrarode waterstandsensor
  • DS3231 AT24C32 IIC precisie real-time klok
  • I2C SSD1306 OLED 128x64 display
  • 200x120x75mm transparante waterdichte plastic behuizing
  • 100x68x50mm transparante waterdichte plastic behuizing
  • IP68 PG7 waterdichte nylon kabelklem
  • IP68 PG11 waterdichte nylon kabelklem
  • RJ11 keystone schroefklem
  • 50ft 4C4P RJ11 draad
  • 6ft 4C4P RJ11 draad
  • 2.54mm header draad
  • 2× 2-pins SPST momentane drukknop microschakelaar
  • 12VDC 1A wandadapter voeding

Bedradingsschema

Arduino-gestuurde slimme irrigatiecontroller – Automatisch besproeien met weer- enlichtsensoren

OLED-display

Arduino-gestuurde slimme irrigatiecontroller – Automatisch besproeien met weer- enlichtsensoren

Druk op de Menuknop om het menu weer te geven en druk herhaaldelijk om door alle opties te cyclen. Het menu verdwijnt automatisch na 30 seconden inactiviteit. Druk op de Selectieknop om de gewenste menufunctie uit te voeren.

Waarom de IO Expander gebruiken?

  • Simpeler ontwerp
  • Kant-en-klare onderdelen
  • Geen 1-Wire driver nodig
  • Geen DS3231 RTC driver nodig
  • Geen EEPROM driver nodig
  • Geen OLED-display driver nodig
  • Geen display-lettertypes die Arduino-geheugen innemen
  • Geen temperatuursensor driver nodig
  • Geen optische regensensor driver nodig
  • Bespaart code-ruimte op Arduino; slechts 12710 bytes (39%)
  • Alleen drie dagen om de code te schrijven
  • Eenvoudig te bedraden met standaard RJ11-telefoonkabel
  • Geen sensor-kabellengteproblemen
  • Goedkoper bouwen dan vergelijkbare commerciële systemen
  • Eenvoudig aan te passen aan individuele eisen
  • Enkele voeding

Bouw het systeem

Sluit de Arduino Nano aan op de IO Expander en programmeer het met de onderstaande code. De 6-pins header is de software-seriële debugpoort en is niet nodig in de definitieve installatie.

Arduino-gestuurde slimme irrigatiecontroller – Automatisch besproeien met weer- enlichtsensoren

Zorg ervoor dat je de ONEWIRE_TO_I2C_ROM1 en ONEWIRE_TO_I2C_ROM2 gedefinieerde adressen wijzigt zodat ze overeenkomen met je 1-Wire naar I2C-adressen.

Code

/* IO Expander sketch geoptimaliseerd
 * Irrigatie Systeem v1.1
 */
#include <math.h>
#include <time.h>
#include <util/crc16.h>
#include <avr/wdt.h>
#include <SoftwareSerial.h>
#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 ONEWIRE_TEMPERATURE "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
#define RAIN_DETECT_LEVEL 4.0
#define DO_NOT_WATER_TEMP 4.4444 // 40°F

#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_WEEK (SEC_IN_DAY * DAYS_IN_WEEK)

#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 | TUE | WED | 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] = {"ZON","MAA","DIN","WOE","DON","VRI","ZAT"};

char menu[][13] = {"Volgende",
 "Besproei",
 "Reset",
 "Klok Min +",
 "Klok Min -",
 "Klok Uur +",
 "Klok Uur -",
 "Zonsopgang",
 "AAN/UIT"};

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;
} 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 state;
 uint8_t crc;
} NVRAM;

enum {
 ZONE1,
 ZONE2,
 ZONE3,
 ZONE4
};

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

ZONE zone[] = {
 {"Voor Rechts", RELAY1},
 {"Voor Links", RELAY2},
 {"Struiken", RELAY3},
 {"Linkerkant", 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 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)
#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 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 < sizeof(schedule) / sizeof(SCHEDULE); 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 << wday))) {
     clk_time += SEC_IN_DAY;
     if (++wday > 6) wday = 0;
     if (wday == clk.tm_wday) break; // Alleen één week controleren
   }
   if (clk_time < next_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;
 // Check of het geregend heeft
 i = schedule[start_schedule].zone;
 if (i < MAX_ZONES && nvram.rain[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 = schedule[nvram.water_schedule].zone;
 if (i < MAX_ZONES) {
   Serial.print("r");
   Serial.print(zone[i].relay);
   if (nvram.water_duration > 0) Serial.println("o");
   else Serial.println("f");
   SerialReadUntilDone();
 }
}

void setup() {
 Serial.begin(115200);
#ifdef SERIAL_DEBUG
 swSerial.begin(115200);
#endif
 pinMode(led, OUTPUT);
 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;
 uint8_t wday;
 long 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;
       rtc_time = mktime(&clk);
       localtime_r(&rtc_time, &rtc);
     }

     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))) {
           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 < rtc_time) nvram.sunrise_time += SEC_IN_DAY;
           update_nvram = true;
         }
         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 < rtc_time) nvram.sunrise_time += SEC_IN_DAY;
         }
         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;
       }
     }
   }

   // Verwerken één keer per minuut
   if (rtc.tm_min != last_min) {
     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();
     }

     // Is het zonsopgang?
     if (lux < SUNRISE_LUX) {
       if (sunrise_counter > 0) sunrise_counter--;
       else check_sunrise = true;
     } else {
       if (sunrise_counter < MIN_IN_HOUR) {
         sunrise_counter++;
         if (check_sunrise && sunrise_counter == MIN_IN_HOUR) {
           nvram.sunrise_time = rtc_time + (SEC_IN_DAY - SEC_IN_HOUR);
           check_sunrise = false;
           update_nvram = true;
         }
       }
     }

     // Regent het?
     if (rain <= RAIN_DETECT_LEVEL) {
       for (i = 0; i < MAX_ZONES; i++) {
         if (nvram.rain[i] < 255) nvram.rain[i]++;
       }
       update_nvram = true;
     }

     // Controleer schema
     if (menu_select == -1 && !nvram.water_duration) {
       while (water_time + (schedule[water_schedule].duration * SEC_IN_MIN) < rtc_time) {
         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;
       }
     }

     // Moeten we besproeien?
     if (nvram.water_duration) {
       WaterScheduleTime();
       if (!nvram.water_duration)
         water_time = NextScheduleTime(water_time, &water_schedule);
     }

     last_min = rtc.tm_min;
     update_oled = true;
   }

   // Controleer knoppen
   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("UIT");
         else if (rain <= RAIN_DETECT_LEVEL) Serial.print("Regen");
         else if (temp <= DO_NOT_WATER_TEMP) Serial.print("Koud");
         else Serial.print("v1.1");
       }
       Serial.print("\";sf2;sa1;sd75,0,\"");
       if (menu_select == 7) { // Zonsopgang
         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 < MAX_ZONES) Serial.print(zone[i].description);
       localtime_r(&water_time, &clk);
       if (water_time - rtc_time > 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) {
         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) ? "UIT" : "AAN");
         } 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));
       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();
}

Let op: Als je de USB-poort gebruikt om de Arduino Nano te programmeren, moet je deze loskoppelen van de IO Expander omdat deze dezelfde seriële poort gebruikt. Voor debugging gebruik de ICSP-poort om de ATmega328P te programmeren. Om de software debug-poort in te schakelen, haal de commentaar bij SERIAL_DEBUG weg.

De splitter moet eerst geconfigureerd worden om de datalijn van de optische infraroodsensor te isoleren van de 1-Wire remote sensorlijn. Soldeer een 0-Ohm 0603-weerstand op R2.

Arduino-gestuurde slimme irrigatiecontroller – Automatisch besproeien met weer- enlichtsensoren

Boor een 7/16" gat in de kleine behuizing en een 11/16" gat in de grote behuizing aan de rechterkant voor de PG7 en PG11. Gebruik een Dremel om de gaten iets te vergroten tot de klemmen strak zitten. De PG7 voedt de remote sensoren en de PG11 de 12VDC, 24VAC, manifold draden en de RJ11 remote sensor draad.

Arduino-gestuurde slimme irrigatiecontroller – Automatisch besproeien met weer- enlichtsensoren

Bedraad de SPST momentane drukknop microschakelaars en sluit ze aan op de RJ11 schroefklem. Gebruik krimpkous om de contacten te isoleren.

Arduino-gestuurde slimme irrigatiecontroller – Automatisch besproeien met weer- enlichtsensoren

Sluit alle draden aan en monteur/voer alle onderdelen in de grote behuizing. Je 50ft RJ11 draad voor de remote sensoren zou net door de PG11 klem moeten passen zonder knippen.

Arduino-gestuurde slimme irrigatiecontroller – Automatisch besproeien met weer- enlichtsensoren

Boor een 9/16" gat in de bovenzijde van de kleine behuizing voor de optische infrarode watersensor. Gebruik een Dremel om het gat iets te vergroten tot de sensor past. De kleine remote sensor behuizing is een strakke pasvorm, maar als de inhoud in de aanbevolen oriëntatie wordt gelegd, zou het net moeten passen. Het zo kort mogelijk maken van de RJ11 draden helpt om alles in de kleinere behuizing te stoppen. Eenmaal gemonteerd wordt aangeraden om wat marij cola in de klemmoer wasser te doen voordat de moer wordt vastgedraaid, voor een betere afdichting.

Arduino-gestuurde slimme irrigatiecontroller – Automatisch besproeien met weer- enlichtsensoren

Installeer de remote sensor behuizing buiten en monteer het verhoogd aan de oostkant van je huis met de optische infrarode watersensor en lichtsensor naar de hemel gericht zonder obstakels.

Arduino-gestuurde slimme irrigatiecontroller – Automatisch besproeien met weer- enlichtsensoren

Boor 1/4" gaten in de top, midden en bodem van de grote behuizing en monteer de knoppen. Gebruik een Dremel om de gaten iets te vergroten tot de knoppen passen.

Arduino-gestuurde slimme irrigatiecontroller – Automatisch besproeien met weer- enlichtsensoren

Test het systeem en zorg dat alles correct werkt. Om de relais en sensoren te testen, koppel de Arduino los van de IO Expander en sluit het direct aan op je computer om handmatig te controleren. Nadat je gecontroleerd hebt dat alles werkt, monteur alle onderdelen in de behuizing met dubbelzijdig tape en verpakkingschuim om je printplaten te bevestigen, en geniet van de voordelen en besparingen van je Slimme Irrigatiecontroller.

Video in werking

Update 12-9-2019

Versie 1.1 uitgebracht die een opstartprobleem oplost als het systeem meerdere dagen zonder stroom is geweest.

Update 2-10-2019

Bij het aansluiten van de 1-Wire naar I2C op de DS3231 en vervolgens op het SSD1306 OLED-scherm, heb je in totaal drie verschillende pull-up weerstanden op de SDA en SCL lijnen (zoals in de afbeelding omcirkeld). Dit resulteert effectief in een 4,7k / 3 = 1,56k pull-up die te sterk kan zijn en willekeurige schermcorrupties veroorzaakt.

Arduino-gestuurde slimme irrigatiecontroller – Automatisch besproeien met weer- enlichtsensoren

Omdat de DS3231 een weerstandspakket gebruikt dat ook door andere lijnen wordt gebruikt, verwijder de andere pull-up weerstanden:

  • 1-Wire naar I2C R3 en R4
  • SSD1306 OLED R6 en R7

Schema

Besproei je tuin of gazon intelligente

Arduino-gestuurde slimme irrigatiecontroller – Automatisch besproeien met weer- enlichtsensoren

Productieproces

  1. Een 433 MHz Slimme Huiscounter Bouwen met Sensorflare en Raspberry Pi
  2. Een Raspberry Pi thuistemperatuurmonitor bouwen met MCP9808, InfluxDB & Grafana
  3. Slimme Vuilnisbak: Een Cellulaire IoT-oplossing voor Geautomatiseerd Afvalbeheer
  4. Slimme Barman: Bouw Je Eigen Raspberry Pi-Cocktailstation
  5. Emotiesensor & EEG: Goedkope Hardware voor Real-time Emotiedetectie
  6. Slimme Irrigatiecontroller met Windows 10 IoT, Raspberry Pi en XBee Vocht-sensoren
  7. Sensorproductie Revolutie: Sensata Gebruikt Slimme Mechatronica
  8. Open-source smart farming systemen bouwen: Boeren versterken met betaalbare, interoperabele IoT
  9. ECM3532: Eta Compute’s eerste geïntegreerde, ultra-laagstroom AI-sensorboard versnelt edge-ontwikkeling
  10. Revolutionaire ultra-gevoelige, duurzame rek-sensor voor slimme textiel
  11. Revolutionaire ultra-dunne sensor verbetert slimme contactlensfunctionaliteit