Автополив

Whynot.
Offline
Зарегистрирован: 19.11.2015

Здравствуйте, в Ардуино я новичок, прошу сильно не пинать и помочь мне! Решил сделать автополив растений. Программу собрал сам из разных скетчей найденных в сети. Логика проста, в определенное время по часам на датчик влажности подается +5В и он начинает работать(якобы он быстро выходит из строя если постоянно под напряжением), если почва сухая поливает 4 секунды и ждет 1 минуту. Попутно выводится текущая влажность, время, и кол-во раз полива(своеобразная проверка мной Ардуины - если счетчик растет значит поливает)

Не могу избавиться от последнего delay в 4 сек, на это время как вы понимаете информация на дисплее замирает.  Вот код

#include <DS3231.h>
#include <Wire.h>  // Comes with Arduino IDE
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
DS3231  rtc(SDA, SCL);
Time RTC_T;
const int HUMIDY_MIN = 700;
const int HUMIDY_MAX = 300;
int i=0;
boolean flag = 0;
unsigned long new_time = 0;
#define POMPA_PIN  8
#define HUM_PIN  7

 
void setup(void)
{
  //инициализируем часы
  rtc.begin();
  //инициализируем дисплей
  lcd.begin(16,2);
  // включаем подсветку
  lcd.backlight();
  // set cursor to positon x=0, y=0
  lcd.home();
  //POMPA_PIN  пин управляет ПОМПОЙ
  pinMode(POMPA_PIN, OUTPUT); 
  //HUM_PIN пин подает +5В на датчик влажности A3
  pinMode(HUM_PIN, OUTPUT); 
  digitalWrite(POMPA_PIN,HIGH);
  digitalWrite(HUM_PIN,LOW);
  
}
 
void loop(void)
{
  lcd.setCursor(0, 0);
  static unsigned long wait = millis() + 60000;
  static unsigned int oldhumidy = 0;
  unsigned int humidy = analogRead(A3);
  
  if(humidy != oldhumidy && humidy >100) {
   oldhumidy = humidy; 
  }
 ////выводит на дисплей показания влажности с задержкой 1с
 if(!flag){
     flag=1;
     new_time=millis()+1000;
 }
 else if(millis() > new_time){
     flag=0;
     lcd.clear();
     lcd.print(humidy); 
     lcd.setCursor(POMPA_PIN, 0);
     lcd.println(rtc.getTimeStr());
     lcd.setCursor(0, 1);
     //печать счетчика полива(если значение растет,значит поливает)
     lcd.print(i);
 }    
 ////
/////управляет питанием датчика влажности А3 по времени
 RTC_T = rtc.getTime();

  if (RTC_T.hour == 18 && RTC_T.min == 25) {
   digitalWrite(HUM_PIN,HIGH);
     }

     if (RTC_T.hour == 18 && RTC_T.min == 27) {
   digitalWrite(HUM_PIN,LOW);
     }
 /////    
  if(wait != 0 && wait-millis() > 10) {
    return;
  } else wait = 0;
 
  if(humidy > HUMIDY_MIN) {
    i++;
    digitalWrite(POMPA_PIN, LOW);
    delay(4000);
    digitalWrite(POMPA_PIN, HIGH);
    wait = millis() + 1*60000;
    }
}
    

Пробовал разные варианты millis(), см. ниже, который не работают. Так же пробовал на примере кода с 46 по 59 строку избавиться от delay так же не выходит.

Одна и таже ошибка

collect2.exe: error: ld returned 5 exit status
 
exit status 1
Ошибка компиляции.
Заранее спасибо за оказанную помощь.
 
#include <DS3231.h>
#include <Wire.h>  // Comes with Arduino IDE
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
DS3231  rtc(SDA, SCL);
Time RTC_T;
const int HUMIDY_MIN = 700;
const int HUMIDY_MAX = 300;
int i=0;
boolean flag = 0;
unsigned long new_time = 0;
unsigned long previousMillis= 0;
#define POMPA_PIN  8
#define HUM_PIN  7

 
void setup(void)
{
  //инициализируем часы
  rtc.begin();
  //инициализируем дисплей
  lcd.begin(16,2);
  // включаем подсветку
  lcd.backlight();
  // set cursor to positon x=0, y=0
  lcd.home();
  //POMPA_PIN  пин управляет ПОМПОЙ
  pinMode(POMPA_PIN, OUTPUT); 
  //HUM_PIN пин подает +5В на датчик влажности A3
  pinMode(HUM_PIN, OUTPUT); 
  digitalWrite(POMPA_PIN,HIGH);
  digitalWrite(HUM_PIN,LOW);
  
}
 
void loop(void)
{
  lcd.setCursor(0, 0);
  static unsigned long wait = millis() + 60000;
  static unsigned int oldhumidy = 0;
  unsigned int humidy = analogRead(A3);
  
  if(humidy != oldhumidy && humidy >100) {
   oldhumidy = humidy; 
  }
 ////выводит на дисплей показания влажности с задержкой 1с
 if(!flag){
     flag=1;
     new_time=millis()+1000;
 }
 else if(millis() > new_time){
     flag=0;
     lcd.clear();
     lcd.print(humidy); 
     lcd.setCursor(POMPA_PIN, 0);
     lcd.println(rtc.getTimeStr());
     lcd.setCursor(0, 1);
     //печать счетчика полива(если значение растет,значит поливает)
     lcd.print(i);
 }    
 ////
/////управляет питанием датчика влажности А3 по времени
 RTC_T = rtc.getTime();

  if (RTC_T.hour == 18 && RTC_T.min == 25) {
   digitalWrite(HUM_PIN,HIGH);
     }

     if (RTC_T.hour == 18 && RTC_T.min == 27) {
   digitalWrite(HUM_PIN,LOW);
     }
 /////    
  if(wait != 0 && wait-millis() > 10) {
    return;
  } else wait = 0;
 
  if(humidy > HUMIDY_MIN) {
    i++;
    digitalWrite(POMPA_PIN, LOW);
    if(POMPA_PIN==LOW){
     if (millis() -previousMillis >4000)
     previousMillis = millis(); 
      digitalWrite(POMPA_PIN, HIGH); 
      }
  
    wait = millis() + 1*60000;
    }
}
    

 

 

Whynot.
Offline
Зарегистрирован: 19.11.2015

Не нашел как редактировать сообщение.

В кодах  ошибка в 1м в 54 строке lcd.setCursor(8, 0); и во 2м в 55 lcd.setCursor(8, 0);

Неудачно поигрался с автозаменой.

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013
static unsigned long wait = millis() + 60000L;
wait = millis() + 1*60000L;

 

Araris
Offline
Зарегистрирован: 09.11.2012

Обратите внимание на строку 80 в последнем скетче - какая-то она несбыточная )).

Whynot.
Offline
Зарегистрирован: 19.11.2015

Спасибо, заменил на if(digitalRead(POMPA_PIN)==LOW){

та же ошибка проблема не решена.

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

эм, это что?

lcd.setCursor(POMPA_PIN, 0);

 

Whynot.
Offline
Зарегистрирован: 19.11.2015

lcd.setCursor(8, 0);

это ошибка автозамены, в коде все верно. Пытался привести код в более наглядный вид.

Araris
Offline
Зарегистрирован: 09.11.2012

Whynot. пишет:

Спасибо, заменил на if(digitalRead(POMPA_PIN)==LOW){

та же ошибка проблема не решена.

У Вас пин сконфигурирован как pinMode(POMPA_PIN, OUTPUT); , поэтому digitalRead() работать не будет.

Заведите переменную, какой-нибудь boolean pompaState, и работайте с портом через неё.

bwn
Offline
Зарегистрирован: 25.08.2014

Araris пишет:

Whynot. пишет:

Спасибо, заменил на if(digitalRead(POMPA_PIN)==LOW){

та же ошибка проблема не решена.

У Вас пин сконфигурирован как pinMode(POMPA_PIN, OUTPUT); , поэтому digitalRead() работать не будет.

Заведите переменную, какой-нибудь boolean pompaState, и работайте с портом через неё.

По идее данная конструкция работать должна, строки типа "digitalWrite(led,!digitalRead(led));" отрабатываются вполне корректно.

Araris
Offline
Зарегистрирован: 09.11.2012

Да, Вы правы, я попробовал - digitalWrite(led,!digitalRead(led)); работает.

Whynot.
Offline
Зарегистрирован: 19.11.2015

Уважаемый Araris, возможно из-за того что сейчас утро, а может это никак не связано, я не могу изменить код с добавлением в него boolean pompaState. А точнее как я буду делать digitalWrite... Каждый раз добавлять pompaState =!pompaState ??

Araris
Offline
Зарегистрирован: 09.11.2012

Управление пинами через переменные - это не необходимость, это, скорее, концептуальное, на будущее. Не хочу повторяться, тем более, что совсем недавно вот здесь http://arduino.ru/forum/programmirovanie/tft-24-touch-shield-nuzhna-pomoshch-v-programmirovanie-knopok-na-ekrane#comment-146768 я пытался описать такой подход.

Whynot.
Offline
Зарегистрирован: 19.11.2015
#include <DS3231.h>
#include <Wire.h>  // Comes with Arduino IDE
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
DS3231  rtc(SDA, SCL);
Time RTC_T;
const int HUMIDY_MIN = 700;
const int HUMIDY_MAX = 300;
int i=0;
boolean flag = 0;
boolean pompaState=1;
unsigned long new_time = 0;
unsigned long previousMillis= 0;
#define POMPA_PIN  8
#define HUM_PIN  7

 
void setup(void)
{
  //инициализируем часы
  rtc.begin();
  //инициализируем дисплей
  lcd.begin(16,2);
  // включаем подсветку
  lcd.backlight();
  // set cursor to positon x=0, y=0
  lcd.home();
  //POMPA_PIN  пин управляет ПОМПОЙ
  pinMode(POMPA_PIN, OUTPUT); 
  //HUM_PIN пин подает +5В на датчик влажности A3
  pinMode(HUM_PIN, OUTPUT); 
  digitalWrite(POMPA_PIN, pompaState);
  digitalWrite(HUM_PIN,LOW);
  
}
 
void loop(void)
{
  lcd.setCursor(0, 0);
  static unsigned long wait = millis() + 60000;
  static unsigned int oldhumidy = 0;
  unsigned int humidy = analogRead(A3);
  
  if(humidy != oldhumidy && humidy >100) {
   oldhumidy = humidy; 
  }
 ////выводит на дисплей показания влажности с задержкой 1с
 if(!flag){
     flag=1;
     new_time=millis()+1000;
 }
 else if(millis() > new_time){
     flag=0;
     lcd.clear();
     lcd.print(humidy); 
     lcd.setCursor(8, 0);
     lcd.println(rtc.getTimeStr());
     lcd.setCursor(0, 1);
     //печать счетчика полива(если значение растет,значит поливает)
     lcd.print(i);
 }    
 ////
/////управляет питанием датчика влажности А3 по времени
 RTC_T = rtc.getTime();

  if (RTC_T.hour == 18 && RTC_T.min == 25) {
   digitalWrite(HUM_PIN,HIGH);
     }

     if (RTC_T.hour == 18 && RTC_T.min == 27) {
   digitalWrite(HUM_PIN,LOW);
     }
 /////    
  if(wait != 0 && wait-millis() > 10) {
    return;
  } else wait = 0;
 
  if(humidy > HUMIDY_MIN) {
    i++;
    pompaState=!pompaState;
    digitalWrite(POMPA_PIN, pompaState);
    if(digitalRead(POMPA_PIN)== pompaState){
     if (millis() -previousMillis >4000)
     previousMillis = millis(); 
     pompaState=!pompaState;
     digitalWrite(POMPA_PIN, pompaState); 
      }
      wait = millis() + 1*60000;
    }
}
    

Я изменил,так правильно? код писал с др. ПК попробовать смогу только позже, но ведь логики мы не меняли.

с pinMode() так ничего и не понял нужно объявлять OUTPUT чтоб управлять реле POMPA_PIN, или и без данной команды можно устанавливать состояние для POMPA_PIN

Whynot.
Offline
Зарегистрирован: 19.11.2015

Чудеса, последний код, скомпилировался нормально, при подключении к ардуино не вгрузился с тойже ошибкой. потом я закрыл открыл Ардуино  1.6.6, код скомпилировался нормально, подключил плату, вгрузил все ОК.

Счетчик растет, но POMPA_PIN 8 никак не управляет реле, оно молчит и не щелкает.

UPD: загрузил скетч из первого поста, реле щелкает - значит физически все подключено правильно.

Araris
Offline
Зарегистрирован: 09.11.2012

1. Ошибка "collect2.exe: error: ld returned 5 exit status" к конкретному скетчу отношения не имеет, это неполадки с Arduino IDE на конкретном компьютере. Проблема описана неоднократно, способы устранения - тоже.

2. Насчет использования переменной состояния реле - мне показалось, что Вы пока не до конца понимаете, зачем оно вообще надо. Будете программировать - понимание само придёт, всему свое время.

3. Пин, конечно же, надо переводить в режим OUTPUT.

Whynot.
Offline
Зарегистрирован: 19.11.2015

Моя помпа питается от 220в. Реле на транзисторе п-н-п типа на POMPA_PIN разрывает фазу в эл. Цепи. При digitalWrite(POMPA_PIN, LOW) реле срабатывает и начинает полив, при digitalWrite(POMPA_PIN, HIGH) реле снова разрывает фазу и полив прекращается.

Уважаемый Araris, я очень благодарен за оказанную помощь и найденные ошибки. Для меня Вы говорите, почти загадками. Я посмотрю в сети инфу касаемо моей ошибки. Означает ли то что мой код верный, и не требует исправлений.

Если это возможно опишите человеко понятным языком, то что описано здесь ниже, millis() очень тяжело мне дается.

static unsigned long wait = millis() + 60000;
if(wait != 0 && wait-millis() > 10) {
    return;
  } else wait = 0;
 
  if(humidy > HUMIDY_MIN) {
    i++;
    digitalWrite(POMPA_PIN, LOW);
    delay(4000);
    digitalWrite(POMPA_PIN, HIGH);
    wait = millis() + 1*60000;
    }

 

bwn
Offline
Зарегистрирован: 25.08.2014

Про работу с миллис неплохо рассказано у Лешака

Araris
Offline
Зарегистрирован: 09.11.2012

Whynot. пишет:

Если это возможно опишите человеко понятным языком, то что описано здесь ниже, millis() очень тяжело мне дается.

ОК, попробую. Надеюсь, по ссылке данной уважаемым bwn, Вы уже сходили, оно того стоит, я тоже на текстах Лешака многое постигал.

Для начала пару слов про millis(). После каждого запуска/ресета ардуиновский процессор начинает с нулевого значения отсчет, так сказать, внутреннего времени. Узнать, сколько там "натикало" мы можем, в частности, вызвав функцию millis(). Она вернет количество миллисекунд с момента старта/рестарта нашего скетча. Всегда иметь текущее значение внутреннего времени - чертовски удобно для множества применений, поэтому разобраться и понять millis() всё-равно Вам придется.

Есть важный нюанс: через приблизительно 50 дней работы скетча количество миллисекунд становится настолько большим, что не помещается уже в переменную типа unsigned long. Происходит переполнение, но это не страшно, просто millis() обнуляется и отсчет начинается с нуля. Этот нюанс надо учитывать для "долгоиграющих" устройств на Ардуино, Ваше к ним относится.

Теперь к скетчу.

// сразу отмечу, этот кусок кода мне совсем не нравится, как-то всё излишне хитровычурно написано..

static unsigned long wait = millis() + 60000; // объявляем и инициализируем (эта строка выполняется в скетче один раз) некую переменную для запоминания временных отметок. Время имеется в виду "внутреннее". Записываем в неё текущее значение счетчика миллисекунд плюс минуту (60000 мсек = 60 сек = 1 мин)

if(wait != 0 && wait-millis() > 10) { // проверяем, наступление нужного нам момента времени. wait != 0 используется тут как некий "флаг" для перехода к следующей проверке влажности, wait-millis() > 10  - означает "разница между ранее запомненным  "текущим плюс минута" временем и текущим временем составляет более 10-ти миллисекунд" - то есть нужный нам момент ещё не наступил.
    return; // если ещё рано, отправляемся в начало void loop()
  } else wait = 0; // если минута прошла и момент настал, либо wait уже равен нулю, "поднимаем флаг" и идем дальше проверять влажность.
// В общем, непросто всё тут написано.
// Я бы сделал иначе. Засекал бы время строкой wait = millis(); а проверял бы наступление нужного момента выражением if (millis() - wait > 60000) , лично мне так понятнее.
// Ну и напомню, что нигде в этом коде не учтен момент переполнения и обнуления по прошествии 50-ти дней работы скетча.
 
  if(humidy > HUMIDY_MIN) {  // почему здесь "больше" ? Может должно быть "меньше" ?
    i++;
    digitalWrite(POMPA_PIN, LOW);
    delay(4000);
    digitalWrite(POMPA_PIN, HIGH);
    wait = millis() + 1*60000; // опять запоминаем в переменную текущее значение счетчика миллисекунд плюс минуту
    }

 

Whynot.
Offline
Зарегистрирован: 19.11.2015

Благодарю bwn и Araris за предоставленную информацию и помощь.

1. Да меня как новичка этот хитрый отрезок кода просто повергает в ужас. Если вернуться к скетчу из 1го поста static unsigned long wait = millis() + 60000; находится внутри loop, а значит при возврате на return в начало loop, wait примет новое значение? ведь millis() не обнуляются в начале loop.

В этом выражении wait-millis() > 10) wait выходит все время растет, также как и растет millis().

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

выражение (humidy > HUMIDY_MIN) говорит, если текущее значение влажности суще(больше) чем минимальная влажность(самая сухая почва, при которой требуется полив) то полей.

3. нашел в сети еще один вариант как избавиться от моего delay() и адаптировал под свои нужны

//#include <DS3231.h>
//#include <Wire.h>  // Comes with Arduino IDE
//#include <LiquidCrystal_I2C.h>
//LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
//DS3231  rtc(SDA, SCL);
//Time RTC_T;
const int HUMIDY_MIN = 700;
const int HUMIDY_MAX = 300;
int i=0;
//boolean flag = 0;
int pompaState=0;
//unsigned long new_time = 0;
unsigned long previousMillis= 0;
#define POMPA_PIN  8
#define HUM_PIN  7
long OnTime = 60000; // перерыв между включением помпы
long OffTime = 4000; // время работы помпы

 
void setup(void)
{
  Serial.begin(9600);
  //инициализируем часы
  //rtc.begin();
  //инициализируем дисплей
  //lcd.begin(16,2);
  // включаем подсветку
  //lcd.backlight();
  // set cursor to positon x=0, y=0
  //lcd.home();
  //POMPA_PIN  пин управляет ПОМПОЙ
  pinMode(POMPA_PIN, OUTPUT); 
  //HUM_PIN пин подает +5В на датчик влажности A3
  pinMode(HUM_PIN, OUTPUT); 
  digitalWrite(POMPA_PIN, pompaState);
  digitalWrite(HUM_PIN,HIGH); //заменить на лоу
  
}
 
void loop(void)
{
  //lcd.setCursor(0, 0);
  static unsigned long wait = millis();
  static unsigned int oldhumidy = 0;
  unsigned int humidy = analogRead(A3);
  
  if(humidy != oldhumidy && humidy >100) {
   oldhumidy = humidy; 
  }
 ////выводит на дисплей показания влажности с задержкой 1с
 //if(!flag){
     //flag=1;
     //new_time=millis()+1000;
// }
 //else if(millis() > new_time){
     //flag=0;
     //lcd.clear();
     //lcd.print(humidy); 
     //lcd.setCursor(8, 0);
     //lcd.println(rtc.getTimeStr());
     //lcd.setCursor(0, 1);
     //печать счетчика полива(если значение растет,значит поливает)
     //lcd.print(i);
 //}    
 ////
/////управляет питанием датчика влажности А3 по времени
 //RTC_T = rtc.getTime();

  //if (RTC_T.hour == 18 && RTC_T.min == 25) {
   //digitalWrite(HUM_PIN,HIGH);
   //  }

     //if (RTC_T.hour == 18 && RTC_T.min == 27) {
   //digitalWrite(HUM_PIN,LOW);
     //}
 /////    
 Serial.println(i);
  //if(wait != 0 && wait-millis() > 10) {
    //return;
  //} else wait = 0;
  
 
  if(humidy > HUMIDY_MIN) {
    
    //pompaState=!pompaState;
    //digitalWrite(POMPA_PIN, pompaState);
    //if(digitalRead(POMPA_PIN)== pompaState){
     //if (millis() -previousMillis >4000){
     //previousMillis = millis(); 
     //pompaState=!pompaState;
     
     //digitalWrite(POMPA_PIN,!digitalRead(POMPA_PIN)); 
      //}
      //wait = millis() + 1*60000;
    // выясняем не настал ли момент сменить состояние светодиода
 
  unsigned long currentMillis = millis(); // текущее время в миллисекундах
  
  // если светодиод включен и светится больше чем надо
  if((pompaState == HIGH) && (currentMillis - previousMillis >= OnTime))
  {
    i++;
    pompaState = LOW; // выключаем
    previousMillis = currentMillis; // запоминаем момент времени
    digitalWrite(POMPA_PIN, pompaState); // реализуем новое состояние
  }
  else if ((pompaState == LOW) && (currentMillis - previousMillis >= OffTime))
  {
    pompaState = HIGH; // выключаем
    previousMillis = currentMillis ; // запоминаем момент времени
    digitalWrite(POMPA_PIN, pompaState); // реализуем новое состояние
  }

    }
}
    

и выяснил что ld.exe у меня рушится на стадии объявления библиотек, когда я раскоментировал пару строчек. Да у меня ВинХР. Буду пробовать переносить все на др. пк на вин7. Также и boolen pompaState рушила ld.exe

 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

Araris ,   эта тема давно обсуждаема... про крах систем при переходе с 1999 на 2000 - давно забыли , так и с миллис()

например:
пусть период отслеживания 1000 mS
пусть крайняя фиксация миллис()=FFFFFE0C=4294966796 - это за 500 mS до переполнения
следФиксация миллис()=000001F4=500 - это спустя 500 mS после переполнения

вычисления:
в данной разрядной сетке , и по правилам вычитания - вычитание заменяется на сложение с дополнительным кодом вычитаемого значения

результат:
newMillis() - oldMillis() = 000001F4 - FFFFFE0C = 000001F4 = 000003E8 => 1000 mS

в чём проблема-то ?
она будет если период слежения больше периода переполнения миллис()....
...тогда нужно учесть колво переполнений и вычислить реальное значение

нет ?

Araris
Offline
Зарегистрирован: 09.11.2012

Whynot. пишет:

1. Да меня как новичка этот хитрый отрезок кода просто повергает в ужас. Если вернуться к скетчу из 1го поста static unsigned long wait = millis() + 60000; находится внутри loop, а значит при возврате на return в начало loop, wait примет новое значение? ведь millis() не обнуляются в начале loop.

В этом выражении wait-millis() > 10) wait выходит все время растет, также как и растет millis().

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

выражение (humidy > HUMIDY_MIN) говорит, если текущее значение влажности суще(больше) чем минимальная влажность(самая сухая почва, при которой требуется полив) то полей.

3. нашел в сети еще один вариант как избавиться от моего delay() и адаптировал под свои нужныи выяснил что ld.exe у меня рушится на стадии объявления библиотек, когда я раскоментировал пару строчек. Да у меня ВинХР. Буду пробовать переносить все на др. пк на вин7. Также и boolen pompaState рушила ld.exe

1. Да и плюньте на него. Замечу ещё раз, что в скетче static unsigned long wait = millis() + 60000; выполняется один раз - почитайте про static, неспроста он там. Переменная wait, а также любая другая, в которую Вы будете помещать значения millis() - растет, так и должно быть, а почему - уже знаете.

2. С датчиком вопрос снимается, я думал, что чем больше значение, тем больше влажность.

3. Этот код мною лучше понимается, думаю, и Вам легче будет.

С ld.exe разберётесь, Вы не первый попавший, проблема известная.

Araris
Offline
Зарегистрирован: 09.11.2012

SU-27-16 пишет:

...

в чём проблема-то ?
она будет если период слежения больше периода переполнения миллис()....
...тогда нужно учесть колво переполнений и вычислить реальное значение

нет ?

Ой, извините, я не все понял про вычисления в разрядной сетке, я лучше своими словами напишу. В моём понимании проблема в том, что я повсюду использую конструкцию вида

if ( millis() - mySavedMillis ) > myDuration ) { ....... mySavedMillis = millis(); } , подразумевая, что у меня millis() всегда больше mySavedMillis. Но это не так, после переполнения я получу millis() гораздо меньший, чем mySavedMillis, и все мои ifы перестанут работать. 

Поэтому для каждого такого ifа я пишу проверку вида

if ( millis() < mySavedMillis ) mySavedMillis = millis(); , имея себе в виду "ну пропустим срабатывание таймера раз в 49 дней 17 часов - да и фиг с ним."

 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

Araris , 
не , не так.... не станет после преполнения миллис()=0 , вернее станет - на 1 mS.... а потом станет 1,2,3,4,5,6......4294967295
и на каждом проходе лупа произойдёт описанное выше....

В моём понимании проблема в том, что я повсюду использую конструкцию вида
1 - if ( millis() - mySavedMillis ) > myDuration ) { ....... mySavedMillis = millis();

...не забываем , что перед этими операторами mySavedMillis уже имеет некоторое значение
приведи пример "на пальцах" - когда не сработает 1

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

myDuration=10
mySavedMillis=FFFFFFFB=4294967291 ( за 5 mS до переполнения )

далее по лупу и по изменению миллис() ( пусть лууп имеет длину - 0 )
millis() - mySavedMillis = 

FFFFFFFС - FFFFFFFB = 1 < 10
FFFFFFFD - FFFFFFFB = 2 < 10
FFFFFFFE - FFFFFFFB = 3 < 10
FFFFFFFF - FFFFFFFB = 4 < 10
00000000 - FFFFFFFB = 5 < 10
00000001 - FFFFFFFB = 6 < 10
00000002 - FFFFFFFB = 7 < 10
00000003 - FFFFFFFB = 8 < 10
00000004 - FFFFFFFB = 9 < 10
00000005 - FFFFFFFB = 10 < 10
00000006 - FFFFFFFB = 11 < 10 - ( millis() - mySavedMillis ) > myDuration ) - сработало !

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

if ( millis() - mySavedMillis ) > myDuration ) { ....... mySavedMillis = millis(); } , подразумевая, что у меня millis() всегда больше mySavedMillis. Но это не так, после переполнения я получу millis() гораздо меньший, чем mySavedMillis, и все мои ifы перестанут работать. 
это не важно , что меньше !!!!!!!!!!!
важно то , что "расстояние" от того до этого ,  при условии постоянного увеличения значения миллис() - не зависит от перехода через переполнение миллис().....

засекли время = 23:00 , ждём интервал 2 часа......
в 01:00 разница составит именно 2 часа ( если не использовать разрядную сетку с учётом числа месяца )
операция 1+24-23=2 в системе миллис() решается "автоматически" = разрядная сетка и правила вычитания

кататак :)

Whynot.
Offline
Зарегистрирован: 19.11.2015

Уважаемый SU-27-16  в коде который используется в скетче по вашему мнению есть защита от переставания срабатывания алгоритма через 50 дней?

01 static unsigned long wait = millis() + 60000;
02 if(wait != 0 && wait-millis() > 10) {
03     return;
04   else wait = 0;
05  
06   if(humidy > HUMIDY_MIN) {
07     i++;
08     digitalWrite(POMPA_PIN, LOW);
09     delay(4000);
10     digitalWrite(POMPA_PIN, HIGH);
11     wait = millis() + 1*60000;
12     }

 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

и смотреть не хочется ( такой проблемы нет )...
я не вам всё это написал....
:)-

тревожит строка 01 в #25
зачем это ?
переход с абсолютной точки отсчёта к относительной и потом наоборот ? зачем ?

а весь крайний код выложить - не помешало бы.... чем куски обсуждать....
нет ?

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

есть только миг между миллис() и олдМиллис - зачем плодить "производные" от их разницы и потом смещать это значение на то , что выше ??

Whynot.
Offline
Зарегистрирован: 19.11.2015

Спасибо за ответ.
Можно вообще убрать эти +60000, это не особо важно, а весь код например из 1го поста - второй

Araris
Offline
Зарегистрирован: 09.11.2012

SU-27-16 пишет:

if ( millis() - mySavedMillis ) > myDuration ) { ....... mySavedMillis = millis(); } , подразумевая, что у меня millis() всегда больше mySavedMillis. Но это не так, после переполнения я получу millis() гораздо меньший, чем mySavedMillis, и все мои ifы перестанут работать. 
это не важно , что меньше !!!!!!!!!!!
важно то , что "расстояние" от того до этого ,  при условии постоянного увеличения значения миллис() - не зависит от перехода через переполнение миллис().....

засекли время = 23:00 , ждём интервал 2 часа......
в 01:00 разница составит именно 2 часа ( если не использовать разрядную сетку с учётом числа месяца )
операция 1+24-23=2 в системе миллис() решается "автоматически" = разрядная сетка и правила вычитания

кататак :)

Всё, я понял, знака же там нет, они же unsigned !

Я ошибочно исходил из того, что 00000000 - FFFFFFFB = -5, а отрицательное число никогда не будет > myDuration. Блин, ганьба. Ещё раз перечитал http://playground.arduino.cc/Code/TimingRollover , где мои глаза раньше были ?

Спасибо большое, SU-27-16, в лоно истины меня вернули.

*посыпая голову пеплом, побрёл выжигать ересь из старых скетчей )).

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

Ещё раз перечитал http://playground.arduino.cc/Code/TimingRollover , где мои глаза раньше были ?
а мои - где ? я вообще такого не видел ! :)-
....надо будет прочитать :)

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

*посыпая голову пеплом, побрёл выжигать ересь из старых скетчей )).
зачем так круто ? работает - и пусть работает....
Блин, ганьба.
это что такое ? "ридна мова" ? я за 5 лет не смог постичь всю глубину и красоту....
песня есть... и любовь и ганьба... примерно понял - что это такое ....
:)

Araris
Offline
Зарегистрирован: 09.11.2012

Это я разволновался, в данном случае переводится как "позорище" )).

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

...понял
:)

Whynot.
Offline
Зарегистрирован: 19.11.2015
#include <DS3231.h>
#include <Wire.h>  // Comes with Arduino IDE
#include <LiquidCrystal_I2C.h>о
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
DS3231  rtc(SDA, SCL);
Time RTC_T;
const int HUMIDY_MIN = 700;  //минимально сухая почва
//const int HUMIDY_MAX = 300;
int i=0;
boolean flag = 0;
boolean pompaState=0;
unsigned long new_time = 0;
unsigned long previousMillis= 0;
#define POMPA_PIN  8
#define HUM_PIN  7
long OnTime = 60000; // перерыв между включением помпы
long OffTime = 4000; // время работы помпы

 
void setup(void)
{
  //инициализируем часы
  rtc.begin();
  //инициализируем дисплей
  lcd.begin(16,2);
  // включаем подсветку
  lcd.backlight();
  // set cursor to positon x=0, y=0
  lcd.home();
  //POMPA_PIN  пин управляет ПОМПОЙ
  pinMode(POMPA_PIN, OUTPUT); 
  //HUM_PIN пин подает +5В на датчик влажности A3
  pinMode(HUM_PIN, OUTPUT); 
  digitalWrite(POMPA_PIN, pompaState);
  digitalWrite(HUM_PIN,HIGH); //заменить на LOW по окончании отладки.
}
 
void loop(void)
{
 unsigned int humidy = analogRead(A3);
   ////выводит на дисплей показания влажности, времени и температуры с задержкой 1с
if(!flag){
     flag=1;
     new_time=millis()+1000;
 }
 else if(millis() > new_time){
     flag=0;
     lcd.clear(); // очистить дисплей
     lcd.setCursor(0, 0); 
     lcd.print(humidy); //курсор в поз 0,0 вывести значение влажности А3
     lcd.setCursor(8, 0); // курсор в поз 8,0
     lcd.println(rtc.getTimeStr()); //печать текущего времени
     lcd.setCursor(0, 1); // курсор в поз 0,1
     lcd.print(i); //печать счетчика полива(если значение растет,значит поливает)
 }    
 ////
/////управляет питанием датчика влажности А3 по времени
 RTC_T = rtc.getTime();

  if (RTC_T.hour == 18 && RTC_T.min == 25) { // время включения +5В на датчик А3, датчик считывает влажность 
   digitalWrite(HUM_PIN,HIGH);
    }

     if (RTC_T.hour == 18 && RTC_T.min == 27) { // время включения +5В на датчик А3, датчик считывает влажность 
   digitalWrite(HUM_PIN,LOW);
     }
 
  if(humidy > HUMIDY_MIN) {
   // управляем помпой
  unsigned long currentMillis = millis(); // текущее время в миллисекундах
  if((pompaState == HIGH) && (currentMillis - previousMillis >= OnTime)) // если помпа выключена и прошло больше времени, чем необходимо
  {
    pompaState = LOW; // включаем
    previousMillis = currentMillis; // запоминаем момент времени
    digitalWrite(POMPA_PIN, pompaState); // реализуем новое состояние
    i++; // выполнен еще один полив
  }
  else if ((pompaState == LOW) && (currentMillis - previousMillis >= OffTime)) //если помпа ВКЛ и прошло больше, чем установленное время работы
  {
    pompaState = HIGH; // выключаем
    previousMillis = currentMillis ; // запоминаем момент времени
    digitalWrite(POMPA_PIN, pompaState); // реализуем новое состояние
  }

    }
}
    
На вин7 действительно ld.exe меня не беспокоило, большинство скетчей вгружалось без проблем, хоть и не все работали с реле правильно, остановился пока на данном скетче
Araris
Offline
Зарегистрирован: 09.11.2012

Сейчас у Вас датчик влажности включен постоянно (digitalWrite(HUM_PIN,HIGH); //заменить на LOW по окончании отладки.).

А что будет с измерением влажности, когда датчик начнет включаться (18:25) и выключаться (18:27) по часам ? В строке 40 ведь никто не проверяет, включен ли датчик в данный момент времени ? 

И ещё, если датчик влажности работает всего две минуты в сутки, то перерыв между включениями помпы (1 минута) не слишком ли велик ? Ну, или наоборот, две минуты на работу датчика - не мало ли будет ? Может полив заканчивать стоит не по времени, а по достижении HUMIDY_MAX, незаслуженно забытой ?

Whynot.
Offline
Зарегистрирован: 19.11.2015

Датчик без питания возвращает 0. Поливать вероятно лучше днём, вечером этого не делают. Интервалы безусловно нужно ещё опытным путём выбирать. В большинстве времени я работал с нагрузкой в виде лампы, помпу я подключал всего раз в самом начале, поэтому объёмы воды(секунды) у меня не выверены ещё. Касаемо датчика отметил что буквально за полчаса нахождения под напряжением в почве контактные дорожки датчика были заметно съедены. Поэтому чем меньше датчик будет работать, тем лучше. Да и анализировать влажность почвы чаще раза в день не нужно. Садовод я просто нулевой, поэтому я и отказался от himidy_max, потому что боюсь залить. Сейчас логика очень проста в текущей настройке он скорее будет недоливать чем пере. Хочу подобрать интервал работы датчика и помпы таким, чтобы включившись датчик запустил помпу подождал минуту, убедился в изменении влажности(стала меньше 700), выключился(как раз эти 2-3 минуты).

Также остались не решенными проблемы переполнения, первое и самое простое, что приходит в голову, поставлю счётчик на дни и буду ресетить на 49день, хотя и надеюсь что с вашей помощью найду более правильное решение. И проблемы зависания ардуины, что наверное самое главное, т.к. замечал что по мере моего взаимодействия с ардуино, периодически скетчи зависали. 

Araris
Offline
Зарегистрирован: 09.11.2012

Whynot. пишет:

Также остались не решенными проблемы переполнения, первое и самое простое, что приходит в голову, поставлю счётчик на дни и буду ресетить на 49день, хотя и надеюсь что с вашей помощью найду более правильное решение. И проблемы зависания ардуины, что наверное самое главное, т.к. замечал что по мере моего взаимодействия с ардуино, периодически скетчи зависали. 

Вы меня разочаровываете ))), почитайте посты уважаемого SU-27-16 в этой теме, он прекрасно объяснил, почему  проблемы переполнения не существует.

Проблемы зависания Ардуино в большинстве случаев связаны не с ошибками в скетче, а с аппаратной частью - некачественным питанием, плохим контактом, электромагнитными помехами извне и т.п.

Whynot.
Offline
Зарегистрирован: 19.11.2015

 К сожалению SU-27-16 особо вступать в дискуссию со мной не захотел, указав что не для меня пишет. Да и разочаровывать Вас я не хотел, и благодарен Вам за выстроенный диалог со мной. Но тем не менее из четких, коротких, хлестких сообщений SU-27-16 я понял, что:

copy из #19

в чём проблема-то ?
она будет если период слежения больше периода переполнения миллис()....
...тогда нужно учесть колво переполнений и вычислить реальное значение

нет ?

Araris
Offline
Зарегистрирован: 09.11.2012

Нет. Имелся в виду случай, когда надо точно-точно знать, сколько миллисекунд прошло за большое-большое время. Вам это совсем не нужно, Вы не общее количество миллисекунд считаете, а маленькие отрезки по четыре и шестьдесят секунд.

Whynot.
Offline
Зарегистрирован: 19.11.2015

Спасибо. Буду тестировать.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

Whynot. ,   не передёргивай !!!!! 
та тема-подтема была именно для Araris  , и написал именно ему !!!! , т.к. тибе это было на том этапе не нужно....
Но тем не менее из четких, коротких, хлестких сообщений
...то ли лесть , то ли восхваления ? не надо нам таких !

...тогда нужно учесть колво переполнений и вычислить реальное значение
да , так и есть....
а что у вас за процессы по времени - раз в 2....3 месяца ?
тут проще перейти на часы реального времени с календарём...