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

Slimme irrigatiecontroller

Componenten en benodigdheden

Arduino Nano R3
× 1
IO-uitbreiding
× 1
IO-uitbreidingsbundel
× 1

Apps en online services

Arduino IDE

Over dit project

Maak een slimme irrigatiecontroller met Arduino

Irrigeer uw tuin intelligent met dynamische watercycli. Stop met het besproeien van uw tuin als het regent of heeft geregend sinds uw laatste watergift. Gebruik de lichtsensor om de zonsopgangstijd te detecteren en de starttijden van het water automatisch dienovereenkomstig aan te passen. Stop met het besproeien van je tuin als het te koud is.

Functielijst

  • Buitentemperatuursensor
  • Regensensor buiten
  • Buitenlichtsensor
  • Realtime klok met batterijvoeding voor wekelijkse planning
  • Niet-vluchtige opslag - verlies nooit een bewatering door stroomuitval
  • Zonsopgangdetectie
  • Slim water geven bespaart op uw waterrekening
  • Water voor zonsopgang om de juiste weektijd mogelijk te maken
  • Stop met water geven als het buiten te koud is
  • Verminder schimmelgroei
  • Eenvoudig schemabeheer

Onderdelen die nodig zijn om de Smart Irrigation Controller te bouwen

  • IO-uitbreiding
  • x2 1-draads naar I2C.
  • 1-draads verbinding
  • Optische connector
  • Splitser
  • Arduino Nano.
  • 4-kanaals DC 5V-relais.
  • TSL2561 lichtsensor.
  • DS18B20 waterdichte temperatuursensor.
  • Optische infrarood waterniveausensor.
  • DS3231 AT24C32 IIC precisie realtime klok.
  • I2C SSD1306 OLED 128x64-scherm.
  • 200x120x75mm doorzichtige waterdichte plastic behuizing.
  • 100x68x50mm doorzichtige waterdichte plastic behuizing.
  • ip68 pg7 waterdichte nylon kabelwartel.
  • ip68 pg11 waterdichte nylon kabelwartel.
  • RJ11 Keystone-schroefaansluiting.
  • 50ft 4C4P RJ11-draad.
  • 1,8 m 4C4P RJ11-draad.
  • 2,54 mm kopdraad.
  • x2 2-pins SPST kortstondige drukknop microschakelaar
  • 12VDC 1A wandadaptervoeding.

Bedradingsschema

OLED-scherm

Druk op de Menu-knop om het menu weer te geven en blijf op de knop drukken om door alle menu-opties te bladeren. Het menu wordt automatisch verwijderd na 30 seconden inactiviteit. Druk op de knop Selecteren om de gewenste menufunctie uit te voeren.

Dus waarom de IO Expander gebruiken?

  • Eenvoudiger te ontwerpen
  • Verkrijgbare onderdelen
  • Geen 1-Wire driver om te schrijven
  • Geen DS3231 RTC-stuurprogramma om te schrijven
  • Geen EEPROM-stuurprogramma om te schrijven
  • Geen OLED-beeldschermstuurprogramma om te schrijven
  • Geen weergavelettertypen om Arduino-coderuimte in te nemen
  • Geen stuurprogramma voor temperatuursensor om te schrijven
  • Geen optische regensensor om te schrijven
  • Bespaart coderuimte op Arduino; slechts 12710 bytes (39%)
  • Slechts drie dagen om de code te schrijven
  • Eenvoudig aan te sluiten met standaard RJ11-telefoonkabel
  • Geen problemen met de lengte van de sensorkabel
  • Goedkoper om te bouwen dan vergelijkbare commerciële systemen
  • Gemakkelijk wijzigingen aan te brengen om aan individuele vereisten aan te passen
  • Enkele voeding

Bouw het systeem

Sluit de Arduino Nano aan op de IO Expander en programmeer deze met de volgende code. De 6-pins header is de seriële debug-poort van de software en is niet nodig bij de uiteindelijke installatie.

Zorg ervoor dat u het door ONEWIRE_TO_I2C_ROM1 en ONEWIRE-TO_I2C_ROM2 gedefinieerde adres wijzigt zodat het overeenkomt met uw 1-draads naar I2C-adres.

/* IO Expander sketch geoptimaliseerd
*
* Irrigation System v1.1
*
*/

#include
#include // Bestand in \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 "iONE6>#define"
"t6s0300"
#define RTC_SENSOR "s4te"
#define I2C_EEPROM "s4tf"
#define I2C_OLED "s4t10"
#define I2C_LIGHT "s3t9;sc0"
# definieer OPTICAL_SENSOR "g5a"
#define BUTTON1 "g11d"
#define BUTTON2 "g12d"

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

#define MAX_ZONES 4

#define HOUR_IN_DA Y 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) DAY 7
#define SEC_IN_WEEK (SEC_IN_DAY * DAYS_IN_WEEK)

#define SUN 0x01
#define MA 0x02
#define TUE 0x04
#define WED 0x08
#define THR 0x10
#define FRI 0x20
#define SAT 0x40
#define EVERYDAY (SUN | MA | DI | WO | THR | VR | 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 weekdag[][4] ={"SUN","MON","TUE","WED","THU","FRI"," SAT"};

char menu[][13] ={"Volgende",
"Water",
"Reset",
"Clock Min +" ,
"Clock Min -",
"Clock Hour +",
"Clock Hour -",
"Zonsopgang",
"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 dagen;
int8_t uur;
int8_t min;
uint8_t duur;
} 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[] ={
{"Front Right", RELAY1},
{"Front Left", RELAY2},
{"Bushes", RELAY3},
{"Linkerkant", RELAY4},
};

SCHEMA schema[] ={
{ZONE1, ZONSOPGANG | 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 lengte)
{
uint8_t crc =0;

while (lengte--) {
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(decimaal, 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 if (schema[i].days &SUNRISE) {
clk_time =nvram.sunrise_time;
clk_time +=schema[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 =schema[i].uur;
clk.tm_min =schema[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) pauze; // Controleer slechts één week
}
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;
// Controleer of het geregend heeft
i =schema[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 =schedule[ nvram.water_schedule].zone;
if (i 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);
//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;
uint8_t wday;
lange n;
bool button1, button2;
static int8_t menu_select =-1;
statische 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() kan struct tm wijzigen
rtc_time =mktime(&clk);
localtime_r(&rtc_time, &rtc); // Get 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-fout! ");
// Initialiseer 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;
}
// Controleer de laatste watertijd niet minder dan een week
if (rtc_time - nvram.last_water_time> SEC_IN_WEEK) nvram.last_water_time =rtc_time - SEC_IN_WEEK;
// Controleer de zonsopgangstijd
if (rtc_time> nvram.sunrise_time) {
localtime_r(&nvram.sunrise_time, &sunrise_clk);
clk =rtc;
clk.tm_hour =zonsopgang_clk.tm_hour;
clk.tm_min =zonsopgang_clk.tm_min;
clk.tm_sec =zonsopgang_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;
}
}
}

// Verwerk slechts één keer per minuut
if (rtc.tm_min !=last_min)
{
// Vraag een 1-draads temperatuurmeting aan. Lees het later.
error_temp =!SerialCmdNoError(ONEWIRE_TEMPERATURE);
if (!error_temp) SerialCmdDone("tt");

error_light =!SerialCmdNoError(ONEWIRE_TO_I2C_ROM2 ";oo"ROM2 );
if (!error_light) {
SerialCmdDone(I2C_LIGHT); // Gebruik geen overdrive
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 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;
}
}
}

// Regent het?
if (regen <=RAIN_DETECT_LEVEL) {
for (i =0; i if (nvram.rain[i] <-1) 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) 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 water geven?
als (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);
pauze;
case MENU_WATER:
StartScheduleTime(water_time, water_schedule);
WaterScheduleTime();
pauze;
case MENU_CLOCK_MIN_PLUS:
clk_time +=SEC_IN_MIN;
pauze;
case MENU_CLOCK_MIN_MINUS:
clk_time -=SEC_IN_MIN;
pauze;
case MENU_CLOCK_HOUR_PLUS:
clk_time +=SEC_IN_HOUR;
pauze;
case MENU_CLOCK_HOUR_MINUS:
clk_time -=SEC_IN_HOUR;
pauze;
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 (S erialCmdNoError(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 ("Regen");
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) { // 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,\"");
Serieel .print((clk.tm_hour>12)?"PM":"AM");
Serial.print("\";sf0;sa1;sd127,1,\"");
Serial .print(weekdag[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> 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);
Seria l.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();
}

Opmerking: Als u de USB-poort gebruikt om de Arduino Nano te programmeren, moet u deze loskoppelen van de IO Expander, aangezien deze ook dezelfde enkele seriële poort gebruikt. Als u in plaats daarvan fouten wilt opsporen, gebruikt u de ICSP-poort om de ATmega328P te programmeren. Om de software-foutopsporingspoort in te schakelen, verwijdert u de SERIAL_DEBUG-definitie.

De splitter moet eerst worden geconfigureerd om de datalijn van de optische infraroodsensor te isoleren van de 1-draads sensorlijn op afstand. Soldeer in een 0 ohm 0603 weerstand op R2.

Boor een gat van 7/16" in de kleine behuizing en een gat van 11/16" in de grotere behuizing aan de rechterkant voor de PG7 en PG11. Gebruik een dremel gereedschap om de gaten iets groter te maken totdat de klier goed aansluit. De PG7 voedt de externe sensoren en de PG11 voor de 12VDC, 24VAC, spruitstukdraden en de RJ11-draad van de externe sensoren.

Sluit de SPST-microschakelaar met kortstondige drukknop aan en sluit deze aan op de RJ11-schroefklem. Gebruik krimpkous om de contacten te isoleren.

Sluit alle draden aan en monteer/voer alle onderdelen in de grote behuizing. Uw 50ft RJ11-draad voor de externe sensoren moet gewoon door de PG11-wartel passen zonder deze door te knippen.

Boor een gat van 9/16" in de bovenzijde van de kleine behuizing voor de optische infraroodwatersensor. Gebruik een dremelgereedschap om het gat iets groter te maken totdat de sensor past. De kleine behuizing van de externe sensor past goed, maar als de inhoud worden gelegd in de aanbevolen richting, moet het gewoon passen. Door de RJ11-draden zo kort mogelijk te maken, kan alles in de kleinere behuizing worden gepropt. Eenmaal gemonteerd, wordt aanbevolen om wat scheepslijm in de pakkingringmoerring toe te voegen voordat u de moer vastschroeft, om een ​​betere afdichting te creëren.

Installeer de behuizing van de externe sensor buiten en monteer deze verhoogd aan de oostkant van uw huis met de optische infrarood watersensor en lichtsensor naar de hemel gericht zonder obstakels.

Boor gaten van 1/4" in het midden bovenaan van de grote behuizing en monteer de knoppen. Gebruik een dremelgereedschap om het gat iets groter te maken totdat de knoppen passen.

Test het systeem en zorg ervoor dat alles correct werkt. Om het relais en de sensoren te testen, koppelt u de Arduino los van de IO Expander en sluit u deze rechtstreeks aan op uw computer om deze handmatig te bedienen. Zodra je hebt gecontroleerd of alles werkt, monteer je alle onderdelen in de behuizing met dubbelzijdig plakband en verpakkingsschuim om je planken vast te zetten en profiteer je van de voordelen en besparingen van je Smart Irrigation Controller.

Video in werking

Update 12-09-2019

Uitgebracht v1.1 die een opstartprobleem oploste als het systeem enkele dagen zonder stroom viel.

Update 2-10-2019

Bij het aansluiten van de 1-Wire op I2C op de DS3231 en vervolgens op het SSD1306 OLED-scherm heb je in totaal drie verschillende pullups op de SDA- en SCL-lijnen zoals weergegeven in de onderstaande afbeelding omcirkeld. Dit zal effectief resulteren in een pull-up van 4,7k / 3 =1,56k die te sterk kan zijn en kan resulteren in willekeurige schermbeschadigingen.

Aangezien de DS3231 een weerstandspakket gebruikt dat door andere lijnen wordt gebruikt, verwijdert u de andere pullup-weerstanden:

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

Code

  • Slimme irrigatiecontroller
Slimme irrigatiecontrollerC/C++
Gebruik uw Arduino om uw tuin of tuin intelligent te bewateren.
/* IO Expander sketch geoptimaliseerd * * Irrigation System v1.1 * */#include #include  // Bestand gelokaliseerd \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 "i6TENSPER8ATURETC"de6T6TSPER8ATURETC definieer I2C_EEPROM "s4tf"#define I2C_OLED "s4t10"#define I2C_LIGHT "s3t9;sc0"#define OPTICAL_SENSOR "g5a"#define BUTTON1 "g11d"#define BUTTON2 "g12d"#define WATER_TIMENRISEBEFORE_DEfine 100 definieer 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 (H) OUR)#define DAYS_IN_WEEK 7#define SEC_IN_WEEK (SEC_IN_DAY * DAYS_IN_WEEK)#define SUN 0x01#define MA 0x02#define TUE 0x04#define WED 0x08#define THR 0x10#define VR 0x20#define ZA 0x40#define ZA | MA | DI | WO | THR | VR | 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);[#4]char =weekdag {"SUN","MON","TUE","WED","THU","FRI","SAT"};char menu[][13] ={"Volgende", "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 relais;} ZONE;typedef struct { uint8_t zone; uint8_t dagen; int8_t uur; int8_t min; uint8_t duur;} SCHEDULE;typedef struct { time_t sunrise_time; time_t last_water_time; uint8_t waterschema; uint8_t water_duration; uint8_t regen[MAX_ZONES]; uint8_t staat; uint8_t crc;} NVRAM;enum { ZONE1, ZONE2, ZONE3, ZONE4};enum { RELAY1 =1, RELAY2, RELAY3, RELAY4};ZONE zone[] ={ {"Front Right", RELAY1}, {"Front Left" , RELAY2}, {"Bosjes", RELAY3}, {"Linkerkant", RELAY4},};SCHEMA schema[] ={ {ZONE1, ZONSOPGANG | 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 lengte){ uint8_t crc =0; while (lengte--) {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 (fout) Serial.print(F("NA")); else Serial.print(decimaal, 1);}time_t NextScheduleTime(time_t last_time, uint8_t* next_schedule){ time_t next_time =-1; time_t clk_time; uint8_t ik; tm clk; uint8_t wday; for (i =0; i  ZATERDAG) wday =ZONDAG; if (wday ==clk.tm_wday) pauze; // Controleer slechts één week } if (clk_time  0) { if (nvram.rain[i]> nvram.water_duration) nvram.water_duration =0; anders nvram.water_duration -=nvram.rain[i]; nvram.regen[i] =0; }}void WaterScheduleTime(void) { uint8_t i; nvram.water_duration--; update_nvram =waar; i =schema[nvram.water_schema].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); //vertraging (1000); wdt_enable(WDTO_8S);}void loop() {static tm rtc; tm clk, zonsopgang_clk; tijd_t rtc_tijd; time_t clk_time; statische tijd_t volgende_tijd; statisch uint8_t last_sec; statisch uint8_t last_min; bool error_rtc; bool error_light; bool error_temp; statisch lang lux =0; statische vlottertemperatuur, regen; statisch uint8_t sunrise_counter =MIN_IN_HOUR; statische bool check_sunrise =false; uint8_t ik; statische bool read_nvram =waar; statische time_t water_time; statisch uint8_t water_schedule; uint8_t sz; uint8_t wday; lang n; bool knop1, knop2; statisch int8_t menu_select =-1; statische time_t menu_time =0; Serieel.println(); if (SerialReadUntilDone()) {if (init_board) {SerialCmdDone(INIT_BOARD); init_board =onwaar; } if (init_oled) {if (SerialCmdNoError(ONEWIRE_TO_I2C_ROM1)) {SerialCmdDone(I2C_OLED ";si;sc;sd"); init_oled =onwaar; } } if (SerialCmdDone(RTC_SENSOR)) { error_rtc =!SerialReadTime(&rtc); if (!error_rtc) { clk =rtc; // mktime() can change struct tm rtc_time =mktime(&clk); localtime_r(&rtc_time, &rtc); // Get 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!"); // Initialize 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; // Check sunrise time 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--; else 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); pauze; case MENU_WATER:StartScheduleTime(water_time, water_schedule); WaterScheduleTime(); pauze; case MENU_CLOCK_MIN_PLUS:clk_time +=SEC_IN_MIN; pauze; case MENU_CLOCK_MIN_MINUS:clk_time -=SEC_IN_MIN; pauze; case MENU_CLOCK_HOUR_PLUS:clk_time +=SEC_IN_HOUR; pauze; case MENU_CLOCK_HOUR_MINUS:clk_time -=SEC_IN_HOUR; pauze; case MENU_ON_OFF:nvram.state ^=STATE_ON_OFF; update_nvram =true; pauze; } 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) { // Sunrise 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  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"); Serieel.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();}

Schema's

Intelligently water your yard or garden

Productieproces

  1. Open-source slimme landbouwsystemen ontwerpen
  2. Slim sensorbord versnelt edge AI-ontwikkeling
  3. 433MHz Smart Home Controller met Sensorflare en een RaspberryPi
  4. Raspberry Pi-temperatuursensor
  5. Cellular IoT:Smart Garbage Can
  6. Slimme barman
  7. Emotiesensor / EEG
  8. Win10 IOT-irrigatiecontroller met vochtsensoren
  9. Ultragevoelige, veerkrachtige sensor voor slim textiel
  10. Ultradunne sensor voor slimme contactlenzen
  11. Slimme mechatronica helpt sensorproductie bij Sensata Technologies