Скидки, ограниченное предложение! Полный список акционных товаров

Урок 30. Автоматический полив растений

Необходимые детали
Видео уроки

Система автоматического полива растений - незаменимый помощник, как для ухода за комнатными растениями, так и на огороде. Система включает мембранный насос для полива растений, если влажность почвы снизилась ниже определённого (порогового) значения. Пороговое значение влажности почвы и время на которое требуется включать насос, устанавливается при помощи кнопок.

Нам понадобится:

Для реализации проекта нам необходимо установить библиотеку:

О том как устанавливать библиотеки, Вы можете ознакомиться на странице Wiki - Установка библиотек в Arduino IDE.

Видео:

Схема подключения:

LED индикатор и кнопки, подключаются к любым выводам Arduino (как цифровым, так и аналоговым), номера указываются в скетче.

Датчик влажности почвы подключается к любому аналоговому входу, номер указывается в скетче.

Силовой ключ (для управления насосом) подключается к цифровому выводу с ШИМ, номер указывается в скетче.

Схема автоматического полива растений на Arduino Uno

В данном уроке, LED индикатор подключён к цифровым выводам 2 и 3, кнопки подключены к цифровым выводам 11 и 12, силовой ключ к цифровому выводу 10 (с ШИМ), датчик влажности почвы к аналоговому входу A0.

Алгоритм работы:

  • При подаче питания, устройство не активно (на индикаторе мигает текущее значение влажности почвы).
    • Если однократно нажать на обе кнопки «A» и «B», то текущее состояние влажности почвы будет сохранено как пороговое (то при котором требуется начать полив) и устройство перейдёт в рабочий режим. Пороговое значение влажности почвы можно изменить в режиме ввода значений.
    • Если нажать и удерживать обе кнопки «A» и «B» дольше 2 секунд, то устройство перейдёт в режим ввода значений.
  • В рабочем режиме устройство выводит на индикатор показания: текущей влажности почвы, пороговой влажности почвы и времени прошедшего с момента последнего полива. (Пороговая влажность почвы отображается тусклее чем остальные показания). Если устройство находится в рабочем режиме и значение текущей влажности почвы упадёт ниже значения пороговой влажности почвы, то устройство перейдёт в режим полива.
  • В режиме полива устройство выводит на индикатор количество секунд до окончания полива и мигает точками, а также подаёт сигнал ШИМ на силовой ключ, который включает насос. Значение ШИМ (скорость мотора насоса) указывается в скетче. Длительность полива устанавливается в режиме ввода значений. По окончании полива, устройство переходит в режим ожидания.
  • В режиме ожидания устройство выводит на индикатор надпись STOP и мигает точками. Данный режим предусмотрен для того, что бы влага равномерно распределилась по грунту до перехода устройства в рабочий режим. Время нахождения в режиме ожидания указывается в скетче. По истечении времени режима ожидания, устройство перейдёт в рабочий режим.
  • В режим ввода значений можно перейти из любого режима, удерживая обе кнопки «A» и «B» дольше 2 секунд. Данный режим состоит из двух пунктов: • установка пороговой влажности почвы (при котором требуется начать полив) и • установка длительности самого полива. Вначале отобразится значение пороговой влажности, которое можно изменить нажатием или удержанием кнопки «A» (уменьшение), или кнопки «B» (увеличение). Если однократно нажать на обе кнопки «A» и «B», то значение изменится на текущую влажность почвы. После того как пороговая влажность задана, нужно нажать и удерживать дольше 2 секунд обе кнопки «A» и «B», на экране отобразится длительность полива, которую можно изменить нажатием или удержанием кнопки «A» (уменьшение), или кнопки «B» (увеличение). После того как длительность полива задана, нужно нажать и удерживать дольше 2 секунд обе кнопки «A» и «B», устройство перейдёт в рабочий режим.
  • Если в режиме полива нажать любую кнопку, устройство прекратит полив и перейдёт в режим ожидания.
  • Если в режиме ожидания нажать любую кнопку, устройство перейдёт в рабочий режим.

Код программы:

#include <iarduino_4LED.h>                                  //  подключаем библиотеку для работы с четырёхразрядным LED индикатором
iarduino_4LED  dispLED(2,3);                                //  объявляем объект для работы с функциями библиотеки iarduino_4LED, с указанием выводов индикатора ( CLK , DIO ) 
const uint8_t  pinSensor   = A0;                            //  объявляем константу с указанием номера аналогового входа, к которому подключен датчик влажности почвы
const uint8_t  pinButtonA  = 12;                            //  объявляем константу с указанием номера вывода, к которому подключена кнопка A
const uint8_t  pinButtonB  = 11;                            //  объявляем константу с указанием номера вывода, к которому подключена кнопка B
const uint8_t  pinPump     = 10;   /* вывод с ШИМ  */       //  объявляем константу с указанием номера вывода, к которому подключен силовой ключ
      uint8_t  btnState;                                    //  объявляем переменную для хранения состояний кнопок: 0-не нажаты, 1-нажата A, 2-нажата B, 3-нажата A и B, 4-удерживается A, 5-удерживается B, 6-удерживались A и B
      uint16_t arrMoisture[10];                             //  объявляем массив для хранения 10 последних значений влажности почвы
      uint32_t valMoisture;                                 //  объявляем переменную для расчёта среднего значения влажности почвы
      uint32_t timWatering;                                 //  объявляем переменную для хранения времени начала последнего полива           (в миллисекундах)
      uint32_t timSketch;                                   //  объявляем переменную для хранения времени прошедшего с момента старта скетча (в миллисекундах)
const uint8_t  timWaiting  = 60;                            //  объявляем константу для хранения времени ожидания после полива               (в секундах)     от 0 до 99
const uint8_t  pwmPump     = 100;                           //  объявляем константу для хранения скорости вращения мотора насоса             (коэффициент)    от 0 до 255
      uint16_t timDuration = 5;    /* по умолчанию */       //  объявляем переменную для хранения длительности полива                        (в секундах)     от 0 до 99
      uint16_t limMoisture = 0;    /* по умолчанию */       //  объявляем переменную для хранения пороговой влажности почвы                  (для вкл насоса) от 0 до 999
      uint8_t  modState    = 0;    /* при старте   */       //  объявляем переменную для хранения состояния устройства: 0-не активно, 1-ожидание, 2-активно, 3-полив, 4-установка пороговой влажности, 5-установка времени полива
void setup(){
  dispLED.begin();                                          //  инициируем LED индикатор
  pinMode(pinButtonA, INPUT);                               //  переводим вывод pinButtonA в режим входа
  pinMode(pinButtonB, INPUT);                               //  переводим вывод pinButtonB в режим входа
  pinMode(pinPump,   OUTPUT);                               //  переводим вывод pinPump    в режим выхода
  digitalWrite(pinPump, LOW);                               //  выключаем насос
  timWatering = 0;                                          //  сбрасываем время начала последнего полива
}
void loop(){
//*******Чтение данных:*******
  btnState    = Func_buttons_control();                     // читаем состояние кнопок, но не дольше 2 секунд
  timSketch   = millis();                                   // читаем текущее время с момента старта скетча
  if(timWatering>timSketch){timWatering=0;}                 // обнуляем время начала последнего полива, если произошло переполнение millis()
  valMoisture = 0; for(int i=0; i<9; i++){arrMoisture[i]=arrMoisture[i+1];} arrMoisture[9]=analogRead(pinSensor); for(int i=0; i<10; i++){valMoisture+=arrMoisture[i];} valMoisture/=10; // вычисляем среднее значение влажности почвы
//*******Управление устройством:*******
  switch(modState){
//  Устройство не активно
    case 0: if(btnState){                                   // если зафиксировано нажатие или удержание кнопок
              if(btnState==6){modState=4;}
              if(btnState==3){modState=2; limMoisture=valMoisture;}
            }
            if(timSketch%100==0){                           // если начинается десятая доля секунды
              if(timSketch/1000%2){dispLED.print(valMoisture);}else{dispLED.print("    ");}
            }
    break;
//  Устройство в режиме ожидания (после полива)
    case 1: if(btnState){                                   // если зафиксировано нажатие или удержание кнопок
              if(btnState==6){modState=4;}
              if(btnState==1){modState=2;}
              if(btnState==2){modState=2;}
              if(btnState==3){modState=2;}
            } 
            if(timSketch%100==0){                           // если начинается десятая доля секунды
              dispLED.print("stop");
              dispLED.point((timSketch/100%4)+1,true);
            }
            if(timDuration+timWaiting-((timSketch-timWatering)/1000)<=0){// если закончилось время ожидания
              modState=2;
            }
    break;
//  Устройство активно
    case 2: if(btnState){                                   // если зафиксировано нажатие или удержание кнопок
              if(btnState==6){modState=4; dispLED.light(7);}
            }
            if(timSketch%100==0){                           // если начинается десятая доля секунды
              if(timSketch/1000%15<5 ){dispLED.light(7); dispLED.print(valMoisture);}else
              if(timSketch/1000%15<10){dispLED.light(1); dispLED.print(limMoisture,LEN4);}else
                                      {dispLED.light(7); if(timWatering){dispLED.print(int((timSketch-timWatering)/1000%3600/60),int((timSketch-timWatering)/1000%3600%60),TIME);}else{dispLED.print("----");}}
            }
            if(valMoisture<=limMoisture){                    // если текущая влажность почвы меньше пороговой
              timWatering=timSketch; modState=3; dispLED.light(7); analogWrite(pinPump,pwmPump);
            }
    break;
//  Устройство в режиме полива
    case 3: if(btnState){                                   // если зафиксировано нажатие или удержание кнопок
              if(btnState==6){modState=4;}else{modState=1;} analogWrite(pinPump,0);
            }
            if(timSketch%100==0){                           // если начинается десятая доля секунды
              dispLED.print(timDuration-((timSketch-timWatering)/1000));
              dispLED.point(0,true);
              dispLED.point((timSketch/100%4)+1,true);
            }
            if(timDuration-((timSketch-timWatering)/1000)<=0){// если закончилось время полива
              modState=1; analogWrite(pinPump,0);
            }
    break;
//  Устройство в режиме установки пороговой влажности почвы
    case 4: if(btnState){                                   // если зафиксировано нажатие или удержание кнопок
              if(btnState==6){modState=5;}
              if(btnState==1){if(limMoisture>0  ){limMoisture--;}}
              if(btnState==2){if(limMoisture<999){limMoisture++;}}
              if(btnState==3){limMoisture=valMoisture;}
              if(btnState==4){while(digitalRead(pinButtonA)){if(limMoisture>0  ){limMoisture--;} delay(100); dispLED.print(limMoisture);}}
              if(btnState==5){while(digitalRead(pinButtonB)){if(limMoisture<999){limMoisture++;} delay(100); dispLED.print(limMoisture);}}
            }
            if(timSketch%100==0){                           // если начинается десятая доля секунды
              dispLED.print(limMoisture);
            }
    break;
//  Устройство в режиме установки длительность полива
    case 5: if(btnState){                                   // если зафиксировано нажатие или удержание кнопок
              if(btnState==6){modState=2;}
              if(btnState==1){if(timDuration>0 ){timDuration--;}}
              if(btnState==2){if(timDuration<99){timDuration++;}}
              if(btnState==4){while(digitalRead(pinButtonA)){if(timDuration>0 ){timDuration--;} delay(100); dispLED.print(timDuration);}}
              if(btnState==5){while(digitalRead(pinButtonB)){if(timDuration<99){timDuration++;} delay(100); dispLED.print(timDuration);}}
            }
            if(timSketch%100==0){                           // если начинается десятая доля секунды
              dispLED.print(timDuration); dispLED.point(0,true);
            }
    break;
  }
}
// Функция определения состояния кнопок
uint8_t Func_buttons_control(){
  uint8_t a=0, b=0;                                         // время удержания кнопок A и B (в десятых долях секунды)
  while(digitalRead(pinButtonA)||digitalRead(pinButtonB)){  // если нажата кнопка A и/или кнопка B, то создаём цикл, пока они нажаты
     if(digitalRead(pinButtonA)){if(a<200){a++;}}           // если удерживается кнопка A, то увеличиваем время её удержания
     if(digitalRead(pinButtonB)){if(b<200){b++;}}           // если удерживается кнопка B, то увеличиваем время её удержания
     if(a>20 && b>20){dispLED.print("----");}               // если обе кнопки удерживаются дольше 2 секунд, выводим на экран прочерки, указывая что их пора отпустить
     if(a>20 && b==0){return 4;}                            // если кнопка A   удерживается дольше 2 секунд, возвращаем 4
     if(a==0 && b>20){return 5;}                            // если кнопка B   удерживается дольше 2 секунд, возвращаем 3
     delay(100);                                            // задержка на 0,1 секунды, для подавления дребезга
  }  if(a>20 && b>20){return 6;}                            // если обе кнопки удерживались дольше 2 секунд, возвращаем 6
     if(a> 0 && b> 0){return 3;}else                        // если обе кнопки удерживалась меньше 2 секунд, возвращаем 5
     if(a> 0 && b==0){return 1;}else                        // если кнопка A   удерживалась меньше 2 секунд, возвращаем 2
     if(a==0 && b> 0){return 2;}else                        // если кнопка B   удерживалась меньше 2 секунд, возвращаем 1
                     {return 0;}                            // если ни одна из кнопок не была нажата,        возвращаем 0
}

скачать

Ссылки:

Обсуждение

Присоединяйся

Другие уроки

На главную