📜 ⬆️ ⬇️

Clever floriculture, or Let Itshnik in the garden ... Part 2

Friends, our technological excavations in the field of home-office gardening have aroused a clear interest on your part (previous article Clever Floriculture, or Let IT Schnick in the garden ... Part 1 ). Therefore, as promised, we answer your questions.

But first - a photo of the components. The microcontroller-brain itself:


Self-powered real time clock:
')


Soil Moisture Sensor (killed):


LCD module, 4 screws :)


1. And where are the details themselves? Code, crutches, problems encountered?
Actually, the code itself is remade for a circuit with one relay. The heading section provides links to used libraries.

/* Pich Irrigation Box (c) Mikhail Pichugin 2016 */ #include <avr/sleep.h> #include <Wire.h> #if defined(ARDUINO) && ARDUINO > 18 // Arduino 0019 or later #include <SPI.h> #endif #include <Sodaq_DS3231.h> // rep/ https://github.com/SodaqMoja/Sodaq_DS3231 #include <LiquidCrystal_I2C.h> // https://github.com/marcmerlin/NewLiquidCrystal #include <LcdBarGraph.h> // rep/ https://github.com/prampec/LcdBarGraph #include <Streaming.h> // http://arduiniana.org/libraries/streaming/ // ------------------------------------------------------------------------- // -- character with one bar byte ch_level1[8] = { B10000, B10000, B10000, B10000, B10000, B10000, B10000, B10000 }; // -- character with two bars byte ch_level2[8] = { B11000, B11000, B11000, B11000, B11000, B11000, B11000, B11000 }; // -- character with three bars byte ch_level3[8] = { B11100, B11100, B11100, B11100, B11100, B11100, B11100, B11100 }; // -- character with four bars byte ch_level4[8] = { B11110, B11110, B11110, B11110, B11110, B11110, B11110, B11110 }; #define I2C_ADDR 0x27 #define BACKLIGHT_PIN 3 #define En_pin 2 #define Rw_pin 1 #define Rs_pin 0 #define D4_pin 4 #define D5_pin 5 #define D6_pin 6 #define D7_pin 7 //#define SD_pin 4 boolean last_hour_irrig = false; boolean errorFlag = false; boolean errorPulse = false; boolean dispPulse = false; byte int0Button = 0; byte int0ButtonPin = 7; //pin   byte irrig_hours[] = {9,20}; //   xx  yy byte lcdNumCols = 20; //       int sensorPin = A0; //pin    int sensorValue = 0; //   int last_hour_sensor = 0; //      int moisturemin = 850; //       int irrig_delay = 10; //   . int pinINT0 = 2; //pin  INT0     int Relay1 = 4; unsigned long prevMillis =0; const long dispInterval =1000; DateTime last_date_irrig; LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin); LcdBarGraph lbg(&lcd,lcdNumCols, 0, 3); volatile boolean alarmFlag; void alarm() { alarmFlag = true; } // ------------------------------------------------------------------------- void setup() { // Initialize common Serial.begin(57600); //while (!Serial) { // ; // wait for serial port to connect. Needed for native USB port only //} Wire.begin(); // Initialize Real Time Clock rtc.begin(); pinMode(pinINT0, INPUT); last_date_irrig = rtc.now(); //if(last_date_irrig.year() == 2000){ //DateTime t(2016,2,28,11,0,0,6); //rtc.setDateTime(t); //Serial.println(F("-Setting date&time")); } // Initialize INT0 for accepting interrupts PORTD |= 0x04; DDRD &=~ 0x04; attachInterrupt(0, alarm, FALLING); rtc.enableInterrupts(EveryHour); //interrupt at EverySecond, EveryMinute, EveryHour or rtc.enableInterrupts(18,4,0); // interrupt at (h,m,s) // Initialize LCD lcd.begin (lcdNumCols,4); lcd.createChar(1, ch_level1); lcd.createChar(2, ch_level2); lcd.createChar(3, ch_level3); lcd.createChar(4, ch_level4); lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE); lcd.setBacklight(HIGH); lcd.home (); // go home //lcd.print("Start"); // Initialize Relay & Button pinMode(Relay1, OUTPUT); // relay init digitalWrite(Relay1, HIGH); // relay off pinMode(int0ButtonPin, INPUT_PULLUP); // int0button //Serial.println(F("-Init OK")); } // ------------------------------------------------------------------------- void loop() { unsigned long currentMillis = millis(); // -- Input circut ------------------------------------------------------- int0Button = digitalRead(int0ButtonPin); //int0 button if (int0Button == LOW) { alarmFlag = true; errorFlag = false; } rtc.convertTemperature(); DateTime now = rtc.now(); //get the current date-time sensorValue = analogRead(sensorPin); // -- Output circut ------------------------------------------------------ if (currentMillis-prevMillis>= dispInterval) { prevMillis = currentMillis; lcd.setCursor (0,0); lcd.print(int(rtc.getTemperature())); lcd.write((byte)223); lcd.setCursor (4,0); lcd.print(now.year(), DEC); lcd.print('/'); lcd.print(now.month(), DEC); lcd.print('/'); lcd.print(now.date(), DEC); lcd.print(' '); lcd.print(now.hour(), DEC); if (dispPulse) { dispPulse = false; lcd.print(F(":")); } else { dispPulse = true; lcd.print(F(" ")); } if (now.minute()<=9) {lcd.print("0");} lcd.print(now.minute(), DEC); lcd.setCursor (0,1); lcd.print(F("Sensor:")); lcd.print(sensorValue); lcd.print(F(" ")); lcd.print(F("min:")); lcd.print(moisturemin); lcd.setCursor (0,2); if (errorFlag) { if (errorPulse) {errorPulse = false; lcd.print(F("Relay :OFF, ERROR ")); } else {errorPulse = true; lcd.print(F("Relay :OFF, ERROR")); } Serial.println(F("ERROR")); } else { lcd.print(F("irH:")); lcd.print(irrig_hours[0], DEC); lcd.print(F(" to ")); lcd.print(irrig_hours[1], DEC); lcd.print(" "); lcd.print(irrig_delay); lcd.print(F("Sec ")); } lcd.setCursor (0,3); lcd.print(F("Lst:")); lcd.print(last_date_irrig.year(), DEC); lcd.print('/'); lcd.print(last_date_irrig.month(), DEC); lcd.print('/'); lcd.print(last_date_irrig.date(), DEC); lcd.print(' '); lcd.print(last_date_irrig.hour(), DEC); lcd.print(':'); if (last_date_irrig.minute()<=9) {lcd.print("0");} lcd.print(last_date_irrig.minute(), DEC); } // -- Action circut ------------------------------------------------------- if (alarmFlag && !errorFlag && now.hour()>=irrig_hours[0] && now.hour()<=irrig_hours[1]) { alarmFlag = false; //reset alarmFlag for next interrupt Serial.println(F("Moisture check Interrupt")); lcd.clear(); lcd.setCursor (0,0); lcd.print(F("Moisture check Int.")); if (sensorValue>=moisturemin) { lcd.setCursor (0,1); lcd.print(F("Sensor data :")); lcd.print(sensorValue); if (last_hour_irrig && abs(last_hour_sensor-sensorValue)<=5) { errorFlag = true; } else { Serial.println(F("-Irrigation")); lcd.setCursor (0,2); lcd.print(F("Relay :ON")); lcd.setCursor (0,3); lcd.print(F("Irrigation ")); lcd.print(irrig_delay); lcd.print(F(" Sec ")); digitalWrite(Relay1, LOW); // Relay ON for (int x=1; x<irrig_delay*5; x++) { lbg.drawValue( x, irrig_delay*5); delay(200); } digitalWrite(Relay1, HIGH); // Relay OFF last_date_irrig = rtc.now(); last_hour_irrig = true; last_hour_sensor = sensorValue; } } else { last_hour_irrig = false; last_hour_sensor = 0; } lcd.clear(); } rtc.clearINTStatus(); Serial.println(sensorValue); } 

Crutches and problems touched only the hardware. For example, specifically with our LCD-module correctly earned only this library.

2. And where is WiFi and the application for android / ios? Where are the statistics of water consumption with data from the cloud? How long will the flower live when disconnecting 220V?
Connecting via Wi-Fi, as well as via Bluetooth, was not planned at the initial stage - the resources of this controller are not enough. It will live a flower enough for everyone who knows about it, to assume that there is something wrong with watering, and to let the poor man get drunk

I can only say that at home I connected the Ethernet module and the system reported on Twitter on its actions. At work, this module had to be disabled, because it is not clear what to write in the application for the information support department: “Please connect the Ficus of the Kukhukonosny type to the LAN, the MAC address of such and such ...”? By the way, what is the real view, who will say?

3. How to cope with the excess power of the washer motor? Was there any thought of using an aquarium pump? Car is too all the same.
There were fears that a powerful jet of water would erode the ground - we even stocked up with headlight washer jets. But the usual separation of one stream into two through the T-connector was enough.

4. How will you solve the issue of corrosion of the humidity sensor? Humidity sensor where located.
In fact, the sensor is not so corrosive, so much is destroyed by electrolysis. There is an understanding that, most likely, it is unprofitable for a flower to have traces of this process in the soil, but so far we cannot offer anything else. There were ideas of turning off the sensor for the time between measurements, weighing, induction sensor, differential temperature sensors and something else - I don’t remember already;)

I can say that the standard sensor lasts for about 3-4 weeks, but here we must take into account the salinity of a particular soil. Now there will be a new homemade version of stainless steel. Let's see how much it is enough.

5. How was the irrigation rate calculated?
Water consumption was calculated experimentally. They read the relevant literature on ficuses, and empirically calculated how much water they need. Then, similarly, we found out what water flow the pump had. In our case, it takes 10 seconds for the pump to pump the required amount of water. This duration and embedded in the firmware. In the current version, no settings can be changed interactively.

Source: https://habr.com/ru/post/313308/


All Articles