Много условий а результат 0.

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

Вроде и блок схему нарисовал и цепочку всю построил, а программа работать не хочет.

Смысл какой:

Включили в ванной свет. Если свет горит больше 1 минуты, необходимо приготовиться.

Приготовились. Ждем когда свет выключится. Свет погас и включаем вытяжной вентилятор на интервал (задан заранее пользователем). Ждем интервал. Если время вышло и влажность ниже аварии (задается заранее пользователем) выключаем вентилятор.

А вот и код

void fan (){
  int present_time = RTC.get(DS1307_HR,true)*3600+RTC.get(DS1307_MIN,false)*60+RTC.get(DS1307_SEC,false);
  int time; //для фиксации времени начала периода
  int time_light; //для подтверждения начала периода
  if (light == true &&  stat == LOW && time_light != true ) { //если зажгли свет и вентилятор выключен
    time = present_time; // запоминаем время включения света
    time_light = true; // фиксируем факт включения света
    Serial.println ("light ok ");
    Serial.println (stat);
  }
  if (light == false) { // если свет выключили
    Serial.println ("light off ");
    Serial.println (stat);
    if ((present_time-time) > 60 && time_light == true) { //если текущее время минус время включения света больше 60 сек. и свет действительно был включен минуту назад
      stat = HIGH;  // включаем вентилятор
      time = present_time; //перезаписываем время, на время включения вентилятора
      time_light = false; //обнуляем факт записи включения света
      Serial.println ("fan - ON");
      Serial.println (stat);
    }
  }
    if (stat == HIGH && humidity < h) { //Если вентилятор работает и влажность в норме
      if ( present_time-time > delay_fan) { //если текущее время минус время с начала включения вентилятора больше интервала задержки включения вентилятора
        stat = LOW; //выключаем вентилятор  
       Serial.println ("fan - OFF");
       Serial.println (stat);
      }
    }
}
   

По факту, свет включается и гаснет, интервалы проходят, а сигнала о вкл вентелятора нет.

JollyBiber
JollyBiber аватар
Offline
Зарегистрирован: 08.05.2012

Вы бы хоть весь скетч выложили что-ли.

step962
Offline
Зарегистрирован: 23.05.2011

Ну.... каГ-бЕ в общем случае:

"Значения локальных переменных не сохраняются после выхода из функции."

Поэтому значения переменных time и time_light могут приниматься от совершеннейшей балды.

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

JollyBiber пишет:

Вы бы хоть весь скетч выложили что-ли.

смысл вас грузить ~500 строками, не относящимися к данной части кода, кроме, заданных ранее, глобальных переменных?

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

step962 пишет:

Ну.... каГ-бЕ в общем случае:

"Значения локальных переменных не сохраняются после выхода из функции."

Поэтому значения переменных time и time_light могут приниматься от совершеннейшей балды.

 

конструктивно. попробую зделать их глобальными.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

зачем DS1307 для отсчета времени работы вентилятора и тп? еще время показывать?

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

jeka_tm пишет:

зачем DS1307 для отсчета времени работы вентилятора и тп? еще время показывать?

да, просто вывод на LCD текущего времени, ну а раз DS1307 уже стоит, то почему бы его и не использовать для таймера?

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

step962 пишет:

Ну.... каГ-бЕ в общем случае:

"Значения локальных переменных не сохраняются после выхода из функции."

Поэтому значения переменных time и time_light могут приниматься от совершеннейшей балды.

 

действительно, это оказалось так.

 

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

 

Всем спасибо!

RainMan
Offline
Зарегистрирован: 21.06.2011

при входе в функцию "fan" значение переменной time_light берется от фонаря. При переходе на глобальные переменные не забудьте сделать начальную инициализацию флагов. 

toc
Offline
Зарегистрирован: 09.02.2013

ingener.solovyev пишет:

блок схему нарисовал

 

картинку в студию.
Я бы сделал конечный автомат. Типа

...
void loop()
{
    doFan();
}

byte state; // состояние автомата

unsigned long myTimer;
unsigned long delayMs=60000;

void doFan()
{
  // включили свет
  if(state==0 && СветВключён()==true)
  {
	state =  1;
	myTimer = millis();
  }

  // выключили свет когда минута ещё не прошла
  if(state==1 && СветВключён()==false && 
      myTimer + delayMs > millis() )
  {
    state = 0;
  }

  // минута прошла и свет всё ещё горит
  if(state==1 && СветВключён()==true && 
      myTimer + delayMs < millis() )
  {
    state = 2;  // "приготовились"
  }
  
  // свет выключили
  if(state==2 && СветВключён()==false )
  {
    state = 3;  
	myTimer = millis();
	ВентиляторВключить();
  }
  
  if(state==3 &&
      myTimer + delayMs < millis() )
  {
    state = 0;  
	if(ВлажностьНижеАварии()==true)
      ВентиляторВыключить();
  }
}

 

RainMan
Offline
Зарегистрирован: 21.06.2011

жаль что я упустил из вида теорию автоматов. Очень удобно и прозрачно.

Сейчас сам пишу код для контроллера солнечного коллектора и уже ноги можно поломать в условиях, флагах. 

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

toc пишет:

ingener.solovyev пишет:

блок схему нарисовал

 

картинку в студию.
Я бы сделал конечный автомат. Типа

...
void loop()
{
    doFan();
}

byte state; // состояние автомата

unsigned long myTimer;
unsigned long delayMs=60000;

void doFan()
{
  // включили свет
  if(state==0 && СветВключён()==true)
  {
	state =  1;
	myTimer = millis();
  }

  // выключили свет когда минута ещё не прошла
  if(state==1 && СветВключён()==false && 
      myTimer + delayMs > millis() )
  {
    state = 0;
  }

  // минута прошла и свет всё ещё горит
  if(state==1 && СветВключён()==true && 
      myTimer + delayMs < millis() )
  {
    state = 2;  // "приготовились"
  }
  
  // свет выключили
  if(state==2 && СветВключён()==false )
  {
    state = 3;  
	myTimer = millis();
	ВентиляторВключить();
  }
  
  if(state==3 &&
      myTimer + delayMs < millis() )
  {
    state = 0;  
	if(ВлажностьНижеАварии()==true)
      ВентиляторВыключить();
  }
}

 

Как вариант. Надо запесать в примеры. Спасибо.

RainMan
Offline
Зарегистрирован: 21.06.2011
 if(state==3 &&
44       myTimer + delayMs < millis() )
45   {
46     state = 0; 
47     if(ВлажностьНижеАварии()==true)
48       ВентиляторВыключить();
49   }
50 }

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

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

toc
Offline
Зарегистрирован: 09.02.2013

RainMan, моя "реализация" не соответствует "тех.заданию"* товарища инженера Соловьёва? ;) 

* я прочитал только текстовую часть первого сообщения. Код не осилил, сорри.

RainMan
Offline
Зарегистрирован: 21.06.2011

Не берите на свой счет. Это просто мысли в слух.

sva1509
Offline
Зарегистрирован: 07.12.2012

Доброго времени суток !

Я бы пробовал так:

typedef enum {
          off,
          onlight1l,
          onlight1h,
          offlight
} StatType;

StatType status = off;
volatile unsigned long tim;

void loop()
{
        switch(status) {
        case off:
                do_off();
                break;
        case onlight1l:
                do_light1l();
                break;
        case onlight1h:
                do_light1h();
                break;
        case offlight:
                do_offlight();
                break;
        }
}
void do_off()
{
        if (свет включен)  {
            tim = millis();
            status = onlight1l;}
}
void do_light1l()
{
unsigned long tim2;

         if (свет включен) {
                  tim2 = millis();
                  tim2 -= tim;
                  if (tim2 > 60000) status = onlight1h;
         } else status = off;
}
void do_light1h()
{
        if (свет погас) {
               вентилятор_включить();
               tim = millis();
               status = offlight;
        }
}
void do_offlight()
{
unsigned long tim2;

        tim2 = millis();

        tim2 -= tim;
        if (tim2 > интервал) {
                   if (авария) tim = mills(); else {ветилятор_выключить();status = off;}
         }
}