Полив растений в саду

Тема в разделе "Глядите, что я сделал", создана пользователем Evgeniy_, 22 апр 2013.

  1. qwabba

    qwabba Нуб

    Евгений, успехов в вашем проекте! А не подскажете, какие вы выбрали краны? Может и ссылкой поделитесь?:) Спасибо!
     
  2. Evgeniy_

    Evgeniy_ Нуб

    Спасибо за советы!

    Краны брал вот эти
     
  3. Evgeniy_

    Evgeniy_ Нуб

    Работа над проектом подходит к завершению. На днях мне достался модуль gprs от "замороженного" проекта друга. Поставил его в систему - будет отправлять смс при каждом включении полива, еще можно будет запросить температуру в теплице по смс, для этого добавил датчик DHT11.
    Но столкнулся с одной проблемой - при попытке записать в переменную char данные о дате и времени (для статистики) записывается только дата, а время отсекается. (если выводить в serial - выводится полностью, а в другую переменную - либо дата, либо время до двоеточия). С длинной переменных экспериментировал - не помогает....


    [​IMG]
    [​IMG]

    Ниже прикладываю скетч. Сырой конечно, но вполне рабочий
     
  4. Evgeniy_

    Evgeniy_ Нуб

    PHP:

    // Пины:
    // GPRS: 7, 8
    // Дисплей: 2, 3, 4, 5, 11, 12 (13 - подсветка)
    // Реле: 9, 10
    // Датчик DHT11: А5
    // Датчики влажности почвы: А2, А3
    // Датчик температуры воды: А1
    // Кнопки: А0
     
    //Подключаем библиотеки
    #include <SoftwareSerial.h>
    #include <dht.h>
    #include <LiquidCrystal.h>
    LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
     
     
    //для DHT11
    #define dht_dpin A5
    dht DHT;
     
    //Переменные для GPRS-модуля
    SoftwareSerial gprsSerial(7, 8);
    int i=0;
    char msg[160]=""; //входящее смс-сообщение
    char phoneNum[20]=""; //номер телефона
    char phoneNumOk[20]="7912ХХХХХХХ";
    char time[30]=""; //текущее время
    char timehors[2]=""; //текущий час
    char timemin[2]=""; //текущая минута
    char timedate[8]=""; //текущая дата
    int hrs=0; //текущий час int
    int minuta=0; //текущая минута int
    boolean isMessage=false; //ответ с модуля является сообщением
    unsigned long previousTimer=0;
    unsigned interval=1000;
     
     
    int soil1Pin = 3; //пин датчика почвы 1
    int soil2Pin = 2; //пин датчика почвы 2
    int relay1Pin = 9; //пин реле 1
    int relay2Pin = 10; //пин реле 2
     
     
    //состояния для реле
    int ON = 0;
    int OFF = 1;
     
    double normTemp = 30.0; //допустимая температура воды
    int soilMax = 900; // влажность почвы
    int button = 0; //состояние кнопок
    int isSettings = 0; //режим настроек
     
    char* myStat1[]={"-------------------", "-------------------", "-------------------",
    "-------------------", "-------------------", "-------------------", "-------------------", "-------------------", "-------------------", "-------------------"};
    char* myStat2[]={"-------------------", "-------------------", "-------------------",
    "-------------------", "-------------------", "-------------------", "-------------------", "-------------------", "-------------------", "-------------------"};
     
     
    void setup()
    {
        digitalWrite(relay1Pin, OFF);
        digitalWrite(relay2Pin, OFF);
        pinMode(relay1Pin, OUTPUT);
        pinMode(relay2Pin, OUTPUT);
     
        DHT.read11(dht_dpin);
     
        Serial.begin(9600);
        delay(2000);
        gprsSerial.begin(19200);               
        delay(300);
       
        lcd.begin(16, 2);
       
    }
     
     
    double GetWaterTemp() //Получение температуры воды в баке
    {
      double temp;
      temp = log(((10240000/analogRead(1)) - 10000));
      temp = 1 / (0.001129148 + (0.000234125 * temp) + (0.0000000876741 * temp * temp * temp));
      temp = temp - 273.15;
      return temp;
    }
     
    void loop()
    {
     
      //КОД ДЛЯ РАБОТЫ С GPRS-МОДУЛЕМ:
     
      unsigned long currentTimer = millis();
      if ((currentTimer - previousTimer) > interval) {
        previousTimer = currentTimer;
        gprsSerial.print("AT+CCLK?\r");  //Запрашиваем время каждую секунду
      }
     
      if (gprsSerial.available()){    //Считываем время, а также СМС и т.д.
        char buf = gprsSerial.read();
        //Serial.print(buf);
        if ('\r' == buf) {
          msg[i++] ='\0';  //Добавляем нуль терминатор
          if (isMessage) {
            //если текущая строка - SMS-сообщение,
            //отреагируем на него соответствующим образом
            //Serial.println(phoneNum); //Печатаем номер телефона с которого пришла СМС
            //Serial.println(msg);  //Печатаем текст СМС
                    //lcd.clear();
                    //lcd.print(phoneNum);
                    //lcd.setCursor(0, 1);
                    //lcd.print(msg);
                    //delay(3000);
                    if (String(phoneNum).toInt() == String(phoneNumOk).toInt()) {
                      String textSms = String("Temp v teplice:")+int((DHT.temperature))+String("C. Temp vody: ")+int(GetWaterTemp())+String("C");
                      sendTextMessage(textSms);
                      //delay(3000);
                    }
            isMessage = false;
          }
          else {
            if (!strncmp("+CMT",msg,4)) {
              int i=0;
              //если текущая строка начинается с "+CMT",
              //то следующая строка является сообщением
              isMessage = true;
              for (i=8;(msg[i]!=',') && (i<30);i++) {  //Выбираем из первой строки сообщения номер телефона с которого оно было отправлено
              }
              msg[i-1]='\0';          //Добавляем нуль терминатор в конец строки с номером телефона
              strcpy(phoneNum,msg+8); //Копируем номер телефона в другую строку
            }
     
            if (!strncmp("+CCLK",msg,5)) {  //Делаем все то же самое с последовательностью символов начинающейся на +CCLK
              int i=0;                    //Эта последовательность является ответом шилда на запрос текущего времени
              for (i=8;(msg[i]!='"') && (i<40);i++) {  //Выделяем из ответа строку содержащую текущее время
              }
              msg[i-3]='\0';
              strcpy(time,msg+8);
              //Serial.println(time);   //и печатаем ее  
                     
                      //Выделяем из строки текущий час и переводим в число
                  int k=0;
              for (k=9; (k<11);k++) {
              }
              time[k]='\0';
              strcpy(timehors,time+9);
              //Serial.println(timehors);  
                      hrs = String(timehors).toInt();
                      //Serial.println(hrs);
                     
                      int l=0;
              for (l=12; (l<14);l++) {
              }
              time[l]='\0';
              strcpy(timemin,time+12);
              //Serial.println(timemin);  
                      minuta = String(timemin).toInt();
                      //Serial.println(minuta);
                     
                      int m=0;
              for (m=0; (m<8);m++) {
              }
              time[m]='\0';
              strcpy(timedate,time);
              //Serial.println(timedate);
                     
            }
          }
          i=0;         
        }
        else if ('\n' != buf) {
          msg[i++] = buf;
        }  
      }
     
      //________________________________
      //КОД ДЛЯ ПРОВЕРКИ НАЖАТИЯ КНОПОК:
     
      button=analogRead(0);//считываем сигнал с пина 0
           
        if(button>675&&button<690)
        {
          //действие первой кнопки
          button1();
        }
           
          if(button>845&&button<855)
        {
          // действие второй кнопки
          button2();
        }
           
        if(button>920&&button<935)
        {
          // действие третьей кнопки
          button3();
        }
     
      //__________________________   
      //КОД ДЛЯ ПРОВЕРКИ ДАТЧИКОВ:
     
      if(analogRead(soil1Pin)>soilMax/*&&hrs==18*/)
      {
        if(GetWaterTemp()>normTemp)
        {
          //поливаем первую зону
            //String textSms = String("Poliv Zona 1. Vlaga:")+int(analogRead(soil1Pin))+String(" Temp vody: ")+int(GetWaterTemp())+String("C");
            //sendTextMessage(textSms);
            digitalWrite(relay1Pin, ON);
            lcd.clear();
            lcd.print("Polivaem zonu 1");
            lcd.setCursor(0, 1);
            lcd.print(time);
            for (int i = 9; i > 0; i--){
              myStat1[i] = myStat1[i-1];
            }
            myStat1[0] = time;
           
            long_delay(10);
            digitalWrite(relay1Pin, OFF);
            lcd.clear();
        }
      }
     
      if(analogRead(soil2Pin)>soilMax/*&&hrs>18*/)
      {
        if(GetWaterTemp()>normTemp)
        {
          //поливаем вторую зону
            //String textSms = String("Poliv Zona 2. Vlaga:")+int(analogRead(soil2Pin))+String(" Temp vody: ")+int(GetWaterTemp())+String("C");
            //sendTextMessage(textSms);
            digitalWrite(relay2Pin, ON);
            lcd.clear();
            lcd.print("Polivaem zonu 2");
            lcd.setCursor(0, 1);
            lcd.print(time);
            for (int i = 9; i > 0; i--){
              myStat2[i] = myStat2[i-1];
            }
            myStat2[0] = time;
            long_delay(10);
            digitalWrite(relay2Pin, OFF);
            lcd.clear();
        }
      }
     
                     
    }
     
      //__________________
      //ФУНКЦИИ:
     
    void button1()
    {
      if(isSettings == 0) {
        //здесь будет вывод краткой статистики на дисплей
        lcd.clear();
        lcd.print("Knopka 1");
        delay(1000);
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("1:");
        lcd.print(analogRead(soil1Pin));
        lcd.print(" 2:");
        lcd.print(analogRead(soil2Pin));
        lcd.setCursor(0, 1);
        lcd.print("Vod:");
        lcd.print(GetWaterTemp());
        lcd.print(" Tep:");
        lcd.print(DHT.temperature);
        delay(5000);
      }
     
      if(isSettings == 1) {
        editSoilMinus();
        delay(300);
      }
     
      if(isSettings == 2) {
        editSoilMinus();
        delay(300);
      }
    }
     
     
    void button2()
    {
      if(isSettings == 0) {
        //здесь будет вывод подробной статистики на дисплей
        lcd.clear();
        lcd.print("Knopka 2");
        delay(1000);
        for (int i = 0; i < 10; i++){
          lcd.clear();
          lcd.print("Zona 1: ");     
          lcd.print(i);
          lcd.setCursor(0, 1);
          lcd.print(myStat1[i]);
          delay(2000);
        }
     
        for (int i = 0; i < 10; i++){
          lcd.clear();
          lcd.print("Zona 2: ");
          lcd.print(i);  
          lcd.setCursor(0, 1);
          lcd.print(myStat2[i]);
          delay(2000);
        }
        lcd.clear();
      }
     
      if(isSettings == 1) {
        editSoilPlus();
        delay(300);
      }
     
      if(isSettings == 2) {
        editSoilPlus();
        delay(300);
      }
    }
     
     
    void button3()
    {
      if(isSettings == 0) {
        // здесь будет выводиться на экран текущее значение soilMax
        lcd.clear();
        lcd.print("soilMax=");
        lcd.print(soilMax);
        isSettings = 1;
        delay(300);
        loop();
      }
     
      if(isSettings == 2) {
        //здесь будет вывод сообщения о новом значении soilMax
        lcd.clear();
        lcd.print("Novoe znachenie");
        lcd.setCursor(0, 1);
        lcd.print(soilMax);
        isSettings = 0;
        delay(1000);
      }
    }
     
     
    void editSoilPlus()
    {
      soilMax = soilMax + 10;
      isSettings = 2;
      lcd.clear();
      lcd.print(soilMax);
    }
     
    void editSoilMinus()
    {
      soilMax = soilMax - 10;
        isSettings = 2;
      lcd.clear();
      lcd.print(soilMax);
    }
     
     
    void sendTextMessage(String text) {
        // Устанавливает текстовый режим для SMS-сообщений
        gprsSerial.print("AT+CMGF=1\r");
        delay(100); // даём время на усваивание команды
        // Устанавливаем адресата: телефонный номер в международном формате
        gprsSerial.println("AT + CMGS = \"+7912ХХХХХХХ\"");
        delay(100);
        // Пишем текст сообщения
        gprsSerial.println(text);
        delay(100);
        // Отправляем Ctrl+Z, обозначая, что сообщение готово
        gprsSerial.println((char)26);
    }
     
    void long_delay(unsigned long seconds){while(seconds--){delay(1000);}}
     
     
    dwk26111974 и vaust нравится это.
  5. эдик

    эдик Нерд

    Добрый день! Подскажите а можно ли заменить ваш экранчик вот таким http://ru.aliexpress.com/item/LCD-1602-Keypad-Shield/2030261556.html (что бы кнопки отдельно не ставить)??? и без жпс модуля система работать будет? (он мне не к чему)??
     
  6. andriano

    andriano Нерд

    А почему сначала предпринимается попытка что-то записать в порты и только потом они устанавливаются в режим записи?
     
  7. sva

    sva Нуб

    добрый день. Евгений, вопрос по установке времени когда полив должен включаться и все зоны сразу поливаются или по очереди?
     
  8. dwk26111974

    dwk26111974 Гик

    Евгений день добрый.Заинтнресовал Ваш проект, планирую повторить.Скажите как в эксплуатации показал себя Ваш девайс?И про подключение кнопок- можно поподробнее.Как подключали?
    Уважаемые форумчане- если кто то данный проект повторил, или создал сам что подобное- большая просьба поделитесь опытом создания и эксплуатации.
    Заранее благодарен Всем.
     
  9. ostrov

    ostrov Гуру

    Кнопки на нем удобные, но адаптер i2c замучаешься припаивать.
     
  10. dwk26111974

    dwk26111974 Гик

    Согласен,Ваш дисплей с кнопками-удобнее)) Я правильно понял-у Вас данный проект трудиться на славу?:)
     
  11. ostrov

    ostrov Гуру

    У меня нет такого проекта. Но я использовал этот шилд с кнопками, мне понравилось, кнопки удобные, заведены на один пин. Но еще больше мне понравился вот такой адаптер для дисплея, который позволяет использовать его всего через три пина:
    [​IMG]
    Он припаивается к 1602 или к 2004 один в один, но для этого шилда потребуется доработка в виде переплетенных проводков, что не хорошо.
     
  12. dwk26111974

    dwk26111974 Гик

    С шилдом с кнопками дел пока не имел((( Подскажите, а он потребует изменения в скетче? У меня со скетчами-туго:( Адаптер-штука отличная, собрал на нем уже 2 девайса (но скетчи были). Да и скетч предложенный увы не скомпилировался...выдает ошибку:
    C:\Users\Ариночка\Documents\Arduino\sketch_jul21c\sketch_jul21c.ino:12:17: fatal error: dht.h: No such file or directory

    compilation terminated.
    Понимаю,что то с датчиком DHT11...но не более....
     
  13. ostrov

    ostrov Гуру

    У шилда к кнопками все 6 кнопок заведены на 1 аналоговый пин. Нажатая кнопка определяется по уровню сигнала. Можно обрабатывать с помощью библиотеки или использовать например функцию приведенную ниже, она возвращает код нажатой кнопки или 0 если ничего не нажато.
    Код (C++):
    byte buttonPress () {             // обработка нажатия кнопок на LСD (срабатывает после отжатия)
      byte bP = 0;
      int tx = analogRead (BUTTONS);
      if (tx < 60) {                  // right
        bP = 5;
      }  else if (tx < 200) {         // up
        bP = 3;
      }  else if (tx < 350) {         // down
        bP = 4;
      }  else if (tx < 600) {         // left
        bP = 2;
      }  else if (tx < 800) {         // select
        bP = 1;
      }
      if (tx < 800) {                 // ждем отжатия кнопки
        delay(10);
        while ((analogRead (BUTTONS)) < 800);
      }
      return bP;
    }
    Ошибка в вашем примере связана с русскими буквами в названии папки, попробуйте перетащить IDE в другую папку, например C:\Arduino
     
    ИгорьК нравится это.
  14. dwk26111974

    dwk26111974 Гик

    Премного благодарен!)))Обязательно испробую.
     
  15. Kloppo

    Kloppo Нуб

    а сможете модернизировать садовый опрыскиватель?
     
  16. alp69

    alp69 Форумчанин

    Понимаю, что не очень актуально но...
    Судя по тому, что выводится в строке сообщения об ошибке, причина другая. Отсутствует файл dnt.h.