Таймер полива с детектированием дня и ночи.

zsm@nxt.ru
Offline
Зарегистрирован: 27.05.2013

Задача: сделать таймер полива без привязки к реальному времени определяющий время суток.
Подошла бы полная копия такого устройства. Интервалы времени нужны меньше от 10сек. до часа примерно.

В зависимости от времени день или ночь – его определяет фото датчик, время работы насоса и время паузы между работой насоса регулируется отдельно 4-мя разными ручками, 2-мя справа (дневной режим) и 2-мя слева (ночной режим).

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

Очень желательно чтобы в фоне могли выполняться другие действия.
Всем заранее спасибо)

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

zsm@nxt.ru пишет:

Как понимаю обычный delay не подойдет..

Очень желательно чтобы в фоне могли выполняться другие действия.
Всем заранее спасибо)

http://arduino.ru/Reference/Millis

tsostik
Offline
Зарегистрирован: 28.02.2013

Шаг первый. Повторяем схему из http://arduino.ru/tutorials/BlinkWithoutDelay целиком с нуля.

Шаг второй. Модифицируем предыдущую схему так, чтобы светодиод горел одно фиксированое время, а не горел другое, но тоже фиксированное время.

Шаг третий. Вставляем в эту схему поненциометр, который определяет продолжительность мигания. Продолжительность паузы оставляем фиксированной.

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

Шаг пятый. Добавляем датчик освещения. В зависимости от датчика пусть светодиожд мигает "днем" = "согласно установкам потенциометра", а "ночью" - с фиксированными интервалами.

Шаг шестой. Еще два потенциометра, определяющих интервали мигания "ночью".

Шаг седьмой. Заменяем светодиод на насос.

Profit.

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

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

Добавьте модуль часов на батарейке RTC, у китайцев 3 бакса вместе с литиевой батарейкой и пересылкой... 

фотодатчик тож не очень обязателен... восход и заход солнца можно посчитать... хотя если вы будете считать количества солнца, типа сколько воды вылить....

zsm@nxt.ru
Offline
Зарегистрирован: 27.05.2013

Большое спасибо, за ответы.

zsm@nxt.ru
Offline
Зарегистрирован: 27.05.2013

Tsostik , cпасибо за чёткий план действий)   millis() это то что нужно.

Не могли бы по 2 пункту подсказать , создал две переменные - previousMillis2 и interval2 смотрю на них и не понимаю что с ними делать :)  

 не ожидал что так сложно будет честно говоря, думаю со следующими пунктами сам справлюсь)

 

tsostik
Offline
Зарегистрирован: 28.02.2013
/* Blink without Delay
 2005
 by David A. Mellis
 modified 8 Feb 2010
 by Paul Stoffregen
 */

const int ledPin =  13;      // номер выхода, подключенного к светодиоду
// Variables will change:
int ledState = LOW;             // этой переменной устанавливаем состояние светодиода 
long previousMillis = 0;        // храним время последнего переключения светодиода

long intervalOn = 1000;           // время включения светодиода (1 секунда)
long intervalOff = 500;           // время выключения светодиода (0.5 секунды)

void setup() {
  // задаем режим выхода для порта, подключенного к светодиоду
  pinMode(ledPin, OUTPUT);      
}

void loop()
{
  // здесь будет код, который будет работать постоянно
  // и который не должен останавливаться на время между переключениями свето
  unsigned long currentMillis = millis();
 
  //проверяем не прошел ли нужный интервал, если прошел то
  if (ledState == LOW) {
    if(currentMillis - previousMillis > intervalOff) {
      // сохраняем время последнего включения
      previousMillis = currentMillis;  
      //включаем светодиод
      ledState = HIGH;
      digitalWrite(ledPin, ledState);
  }

   if (ledState == HIGH) {
    if(currentMillis - previousMillis > intervalOn) {
      // сохраняем время последнего выключения
      previousMillis = currentMillis; 
      //выключаем светодиод 
      ledState = LOW;
      digitalWrite(ledPin, ledState);
  }

}

 

zsm@nxt.ru
Offline
Зарегистрирован: 27.05.2013

Всё заработало! Спасибо за помощь. хотелось бы только усовершенствовать строчки:

 
  if (fotorezval<500)  //ночь

и

  if (fotorezval>500) //день

чтобы if срабатывало через циклов 100 например , чтобы исключить ложные переключения.
то есть, если fotorezval будет сто раз подряд меньше 500 тогда перейти к ночной части кода.

 

#define FOTO_REZ A0// фото резистор
#define VAR_REZ1 A1 // регулятор паузы ночью
#define VAR_REZ2 A2 // регулятор полива ноью
#define VAR_REZ3 A3 // регулятор паузы днем
#define VAR_REZ4 A4 // регулятор полива днем
const int ledPin =  13;   // номер выхода, подключенного к светодиоду
// Variables will change:
int ledState = LOW;    // этой переменной устанавливаем состояние светодиода
long previousMillis = 0;        // храним время последнего переключения светодиода
long interval = 1000;        // интервал между включение/выключением светодиода (1 секунда)

void setup() {
  // задаем режим выхода для порта, подключенного к светодиоду
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);  
}

void loop()
{
  delay(1000);


  int fotorezval = analogRead(FOTO_REZ);

  Serial.print("fotorezval...");
  Serial.println(fotorezval);




  if (fotorezval<500)  //ночь

  {

    int pause = analogRead(VAR_REZ1);
    int watering = analogRead(VAR_REZ2);

    long pauseTime = pause; // Время паузы в секундах
    long lightTime = watering; // Время свечения в секундах

    Serial.print("PAUSE NIGHT---");
    Serial.println(pause);
    Serial.print("WATERING NIGHT---");
    Serial.println(watering);


    // здесь будет код, который будет работать постоянно
    // и который не должен останавливаться на время между переключениями свето
    unsigned long currentMillis = millis();

    //проверяем не прошел ли нужный интервал, если прошел то
    if(currentMillis - previousMillis > pauseTime * 1000 && ledState == LOW)
    {
      // сохраняем время последнего переключения
      previousMillis = currentMillis;  
      ledState = HIGH;
      // устанавливаем состояния выхода, чтобы включить или выключить светодиод
      digitalWrite(ledPin, ledState);
    }

    //проверяем не прошел ли нужный интервал, если прошел то
    if(currentMillis - previousMillis > lightTime * 1000  && ledState == HIGH)
    {
      // сохраняем время последнего переключения
      previousMillis = currentMillis;  
      ledState = LOW;
      // устанавливаем состояния выхода, чтобы включить или выключить светодиод
      digitalWrite(ledPin, ledState);
    }

  }


  if (fotorezval>500) //день


  {
    int pause1 = analogRead(VAR_REZ3);
    int watering1 = analogRead(VAR_REZ4);  


    long pauseTime1 = pause1; // Время паузы в секундах
    long lightTime1 = watering1; // Время свечения в секундах

    Serial.print("PAUSE DAY---");
    Serial.println(pause1);
    Serial.print("WATERING DAY---");
    Serial.println(watering1);


    // здесь будет код, который будет работать постоянно
    // и который не должен останавливаться на время между переключениями свето
    unsigned long currentMillis = millis();

    //проверяем не прошел ли нужный интервал, если прошел то
    if(currentMillis - previousMillis > pauseTime1 * 1000 && ledState == LOW)
    {
      // сохраняем время последнего переключения
      previousMillis = currentMillis;  
      ledState = HIGH;
      // устанавливаем состояния выхода, чтобы включить или выключить светодиод
      digitalWrite(ledPin, ledState);
    }

    //проверяем не прошел ли нужный интервал, если прошел то
    if(currentMillis - previousMillis > lightTime1 * 1000  && ledState == HIGH)
    {
      // сохраняем время последнего переключения
      previousMillis = currentMillis;  
      ledState = LOW;
      // устанавливаем состояния выхода, чтобы включить или выключить светодиод
      digitalWrite(ledPin, ledState);
    }

  }









}

 

tsostik
Offline
Зарегистрирован: 28.02.2013

Обычно для этого не считают количество "срабатываний", а вводят гистерезис.


 if ( (state == DAY) && (fotorezval<450))  // потемнело - значит ночь

 if ( (state == NIGHT) && (fotorezval>550))  // посветлело - значит день

Цифры 450 и 550 взяты "от балды", правильные зависят от чувствительности и размаха Вашего датчика.

zsm@nxt.ru
Offline
Зарегистрирован: 27.05.2013

Большое спасибо.