Podczas wakacyjnej nieobecności, nasze domowe rośliny, z powodu braku regularnego podlewania i odpowiedniego oświetlenia, narażone są często na uschnięcie. Prezentowany układ (Fig. 1) umożliwia kontrolę podstawowych parametrów wegetacji roślin, t.j. wilgotności gleby i stopnia nasłonecznienia. W zależności od wartości tych parametrów układ umożliwia podjęcie automatycznych akcji nawadniania i/lub doświetlania rośliny. Projekt wykorzystuje tanie i łatwo dostępne komponenty elektroniczne: płytkę prototypową Arduino oraz czujniki, silnik pompy wody i inne.
Projekt wykorzystuje dwa rodzaje czujników: wilgotności oraz nasłonecznienia. Do pomiaru wilgotności gleby wykorzystuje się tzw. higrometry. Są to czujniki rezystancyjne. Tanie sensory dostępne w handlu składają się z dwóch części: małej płytki z elektroniką oraz czujnika złożonego z dwóch elektrod, służącego do kontroli zawartości wody w glebie (Fig. 2). Czujnik posiada potencjometr slużący do regulacji czułości wyjścia cyfrowego oraz diodę LED zasilania oraz diodę LED wyjścia cyfrowego. Układ posiada piny: VCC, GND, oraz dwa sygnały wyjściowe: cyfrowe (D0) oraz analogowe (A0). W handlu znajduje się wiele podobnych czujników np. typu YL-69, HL-69 czy FC-28.
Czujnik umożliwia skorzystanie z dwóch rodzajów sygnałów wyjściowych: cyfrowego (stan niski bądź wysoki) oraz analogowego. Napięcie na wyjściu analogowym czujnika wilgtności zmienia się płynnie w zależności od zawartości wilgoci w glebie. Kiedy gleba jest wilgotna, napięcie wyjściowe jest niskie. Gdy gleba jest sucha, napięcie wyjściowe jest wysokie (Tab. 1). Przetwornik analogowo-cyfrowy układu arduino zmienia to napięcie na odpowiadające mu wartości sygnałów wyrażone w skali od 0-1023. Wartość cyfrowego sygnału wyjściowego uzależniona jest od predefiniowanej wartości progowej. Poniżej niej wartość sygnalu cyfrowego będzie niska (0), a powyżej - wysoka (1). Wartość progową reguluje się za pomocą potencjometra.
Gleba | Napięcie na wy analogowym | Wartość na wy przetwornika AC Arduino |
---|---|---|
sucha | wysokie (np. 4,2V) | 1023 |
wilgotna | niskie (0V) | 0 |
Jako czujnik oświetlenia wykorzystano fotorezystor. Wykonano dzielnik napięcia, który podłączono do pinu analogowego mierzącego napięcie wyjściowe. Wartość rezystora dobrano eksperymentalnie (około 1,5kΩ).
Elementem odpowiedzialnym za nawadnianie roślin jest silnik (pompa) RS-360SH (Fig. 3). Wymaga ona zasilania 3-12V (do ciągłej pracy rekomendowane jest napięcie 5V 2A). Nie powinno się go podłączać na dłuższy czas do napięcia większego niż 7,5V.
Układ stale dokonuje pomiarów wilgotności gleby i usłonecznienia. Pomierzone wartości z czujników przekazywane są na wejścia analogowe Arduino (kolejno: A0 i A5). Po przeworzeniu, parametry w postaci procentowej są wyświetlane na wyświetlaczu ciekłokrystalicznym Nokia 5110. Pomiary dokonywane są z częstotliwością wyznaczaną za pomocą zmienej MeasurementBreak
. W zależności od ustawienia zmiennej NumberOfMeasurements
, układ dokonuje zliczeń n pomiarów. Wartości analogowe są sumowane, a następnie obliczana jest z nich średnia arytmetyczna. Wartość uśredniona decyduje o uruchomieniu urządzenia nawadniającego i lampy doświetlającej roślinę. Wartości progowe wilgotności gleby oraz usłonecznienia dobrano eksperymentalnie. W przypadku wilgotności, włączenie przekaźnika następuje wtedy gdy średni pomiar parametru staje się mniejszy bądź równy 850. Spadek wilgotności gleby poniżej wartości krytycznej powoduje załączenie przekaźnika pompy, co uruchamia silnik. Woda zaczyna być pompowana ze zbiornika źródłowego do doniczki. Silnik popmpuje wodę przez okres 3 sek. Po tym czasie pompa zostaje wyłączona i następuje okres 10-sekundowej przerwy, potrzebnej na wsiąknięcie wody i rozprowadzenie jej w przestrzeniach porowych gruntu. Po tym okresie układ przechodzi do trybu wykonania kolejnej serii pomiarów i sytuacja zaczyna się powtarzać. Bezpośrednio po dokonaniu pomiaru wilgotności, układ dokonuje pomiaru usłonecznienia. Aby zapobiec sytuacji ciągłego włączenia oświetlenia w godzinach nocnych, zdarzenie załączenia lampy uzależniono od zaistnienia warunków niepełnego oświetlenia. Jeżeli przeciętny pomiar oświetlenia obliczony jako średnia arytmetyczna z n pomiarów, wskaże wartość z przedziału (700, 850>, mikrokontroler zaświeci lampę. Będzie ona zapalona do momentu kolejnego pomiaru. W praktyce, kolejny pomiar dokonywany jest w warunkach doświetlenia i kolejna uśredniona wartość pomiarów wyłączy lampę. Jeśli w kolejnym okresie czasu warunki pomiarowe światła nie pogorszą się (np. z powodu nocy), światło zostanie ponownie zapalone. Sytuacja zacznie się od tego momentu powtarzać. Wartości chwilowe czujników oraz wartości uśrednione, wysyłane są na port szeregowy.
#include <SPI.h> #include <Adafruit_GFX.h> #include <Adafruit_PCD8544.h> #define MeasurementBreak 1000 // time interval between measurements 5min - 300.000ms #define NumberOfMeasurements 20 // number of measurements to averaging // Adafruit_PCD8544 display = Adafruit_PCD8544(SCLK, DIN, D/C, CS, RST); Adafruit_PCD8544 display = Adafruit_PCD8544(7, 6, 5, 4, 3); int relay_pump = 8; // pin of the pump relay int relay_light = 10; // pin of the light relay int moistureValue = 0; // initial values of the measurements of the percent of the moisture int moisturePercent = 0; String percentMoistureString = "0"; int stringMoistureLength = 0; int lightValue = 0; // initial values of the measurements of the percent of the light int lightPercent = 0; String percentLightString = "0"; int stringLightLength = 0; int sum_of_moisture = 0; // initial value of the sum of the moisture measurements int sum_of_light = 0; // initial value of the sum of the light measurements int mesurement = 0; // initial value of the measurement item unsigned long LastTime = 0; int convertMoistureToPercent(int value) { // function to convert moisture analog values to percent values int percentMoistureValue = 0; percentMoistureValue = map(value, 1023, 410, 0, 100); if (percentMoistureValue > 100) percentMoistureValue = 100; return percentMoistureValue; } int convertLightToPercent(int value) { // function to convert light analog values to percent values int percentLightValue = 0; percentLightValue = map(value, 970, 160, 0, 100); if (percentLightValue > 100) percentLightValue = 100; return percentLightValue; } void displayMoisturePercent(int length) { // function to display percent moisture values in Nokia LCD display switch (length) { case 1: display.setCursor(58, 5); display.print(percentMoistureString); break; case 2: display.setCursor(45, 5); display.print(percentMoistureString); break; case 3: display.setCursor(34, 5); display.print(percentMoistureString); break; default: display.setCursor(34, 5); display.print(percentMoistureString); break; } } void displayLightPercent(int length) { // function to display percent light values in Nokia LCD display switch (length) { case 1: display.setCursor(58, 29); display.print(percentLightString); break; case 2: display.setCursor(45, 29); display.print(percentLightString); break; case 3: display.setCursor(34, 29); display.print(percentLightString); break; default: display.setCursor(34, 29); display.print(percentLightString); break; } } void setup() { pinMode(relay_pump, OUTPUT); // set the relay_pump pin as an OUTPUT pinMode(relay_light, OUTPUT); // set the relay_light pin as an OUTPUT digitalWrite(relay_pump, HIGH); // initialy turn OFF pump relay digitalWrite(relay_light, HIGH); // initialy turn OFF light relay display.begin(); // start of the Nokia LCD display display.setContrast(40); // Nokia LCD display contrast settings Serial.begin(9600); // start of the serial port } void loop() { unsigned long CurrentTime = millis(); // time from start of the sketch if (CurrentTime - LastTime > MeasurementBreak) { // if the time of the mesurements is longer than MeasurementBreak value: LastTime = CurrentTime; mesurement += 1; // add the current mesurement to the total measurement no sum_of_moisture += analogRead(A0); // add the current moisture value to the sum of the moisture measurements sum_of_light += analogRead(A5); // add the current light value to the sum of the light measurements if (mesurement >= NumberOfMeasurements) { int mean_moisture = ceil(sum_of_moisture / mesurement); int mean_light = ceil(sum_of_light / mesurement); Serial.print("Mean of moisture: "); // send to serial port the string "Mean of moisture: " Serial.print(mean_moisture); // send to serial port the mean_moisture value Serial.print(" Mean of light: "); // send to serial port the string "Mean of light: " Serial.println(mean_light); // send to serial port the mean_light value if (mean_moisture <= 800) { // if the soil is wet: digitalWrite(relay_pump, HIGH); // turn OFF of the pump } else { // if the soil is dry: digitalWrite(relay_pump, LOW); // turn ON of the pump delay(3000); // watering 3 sek. digitalWrite(relay_pump, HIGH); delay(10000); // wait 10 sec. until a water soaks } if ((mean_light > 700) && (mean_light <= 850)) { // if there is too little light (but there is not yet night)- digitalWrite(relay_light, LOW); // turn OFF of the light } else { // if there is too much light - digitalWrite(relay_light, HIGH); // turn ON of the light } mesurement = sum_of_moisture = sum_of_light = 0; // reset the variables values calculated in the loops } display.clearDisplay(); // clear of the display display.setTextSize(1); // font size settings to 1 display.setTextColor(BLACK); // display font color settings display.setCursor(3, 14); // set cursor in column no 3 and row no 14 position display.print("Wilg."); // write "Wilg" (moisture symbol) display.setTextSize(2); // font size settings to 2 moistureValue = analogRead(0); // read the moisture value from the analog pin A0 moisturePercent = convertMoistureToPercent(moistureValue); percentMoistureString = String(moisturePercent); stringMoistureLength = percentMoistureString.length(); displayMoisturePercent(stringMoistureLength); display.setCursor(70, 5); // set cursor at the end of the moisture mesurement frame display.print("%"); // write "%" display.drawRect(32, 2, 51, 19, BLACK); // draw a rectangle from (x1,y1) to (x2,y2) display.drawLine(2, 24, 81, 24, BLACK); // draw a line from (x1,x2) to (y1,y2) display.setTextSize(1); // font size settings to 1 display.setCursor(3, 37); // set cursor in column no 3 and row no 37 position display.print("Nasl."); // write "Nasl" (light symbol) display.setCursor(34, 29); // set cursor in column no 34 and row no 29 position display.setTextSize(2); // font size settings to 2 lightValue = analogRead(5); // read the light value from the analog pin A5 lightPercent = convertLightToPercent(lightValue); percentLightString = String(lightPercent); stringLightLength = percentLightString.length(); displayLightPercent(stringLightLength); display.setCursor(70, 29); // set cursor at the end of the light mesurement frame display.print("%"); // write "%" display.drawRect(32, 27, 51, 18, BLACK); // draw a rectangle from (x1,y1) to (x2,y2) display.drawLine(2, 47, 81, 47, BLACK); // draw a line from (x1,x2) to (y1,y2) display.display(); Serial.print(mesurement); // send to serial port the masurement no Serial.print(" "); Serial.print(analogRead(A0)); // send to serial port the moisture instantaneous value Serial.print(" "); Serial.print(analogRead(A5)); // send to serial port the light instantaneous value Serial.println(" "); } }