Зона видимости millis()

Sirocco
Offline
Зарегистрирован: 28.09.2013

Есть простейший код:

const int kontroller =  13;      
int altonika = 5;
unsigned long currentMillis;
long preMillis = 0;        

void setup() {
pinMode(kontroller, OUTPUT);   
pinMode(altonika, INPUT);   

}

void loop()
{

 
  if (digitalRead(altonika) == LOW)
  {
    currentMillis = millis();
   digitalWrite(kontroller, HIGH);
   
     if(currentMillis - preMillis > 5000) 
       {
         preMillis = currentMillis;   
         digitalWrite(kontroller, LOW);
       }
   }
  
}

Суть - когда нет сигнала на выходе датчика "Альтроника" должен появиться сигнал на выходе "5" на 5 секунд. На выходе 5 должна быть единица всегда, если сигнала с датчика нет. С момента каждого пропадания сигнала, должен быть сигнал на выходе 5, отсчитываться заново. Поэтому delay не вариант.

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

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

 А почему не

unsigned long currentMillis = 0;
unsigned long preMillis = 0;

?

axill
Offline
Зарегистрирован: 05.09.2011

У вас логика нарушена, сами посмотрите на свой код внимательно

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

 

Sirocco
Offline
Зарегистрирован: 28.09.2013

Нет, ни первое, ни второе не помогло. А вот если currentMillis = millis(); вынести из первого условия, тогда код работает и параметр currentMillis виден во втором условии, и оно выполняется. Но мне нужно чтоб время начинало отсчитываться по условию - с момента пропадания сигнала.

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

У Вас условия немножко противоречивые:

"При пропадании сигнала включаем LED на 5 секунд"

"С момента каждого пропадания сигнала, должен быть сигнал на выходе 5, отсчитываться заново."

То есть, если сигнал появился через секунду - таймаут сбрасываем? А если сигнал не появился и после пятой секунды - это как считать: новый тамаут, или старый?

Вложенность if-ов тут, на мой взгляд, действительно не нужна. Один if определяет наличие сигнала с датчика и взводит таймер и LED (а если таймер уже взведен: не равен нулю - не делает ничего), а второй - проверяет не истек ли таймер и гасит лед (и обнуляет таймер) по его истечению.

Sirocco
Offline
Зарегистрирован: 28.09.2013

Я понял о чём Вы. Но этот код не работает:

const int kontroller =  13;      
int altonika = 5;
unsigned long currentMillis = 0;
unsigned long preMillis = 0;       

void setup() {
pinMode(kontroller, OUTPUT);   
pinMode(altonika, INPUT);   

}

void loop()
{
//-----------------
  if (digitalRead(altonika) == LOW)
  {
    currentMillis = millis();
   digitalWrite(kontroller, HIGH);
   }
//------------------------   
  if(currentMillis - preMillis > 1000) 
       {
         preMillis = currentMillis;   
         digitalWrite(kontroller, LOW);
       }
//---------------------
}

Тут два отдельных условия, но я не могу понять, почему строка currentMillis = millis(); из первого условия, не видится во втором условии. Если её вынести уз условия и поместить в loop, то во втором условии она обнаруживается и условие срабатывает. Но мне нужно запускать отсчёт по собитию.

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

Навтыкайте отладочных принтов до и после цикла if-а. Есть подозрение, что currentMillis внутри if и снаружи - просто разные,  хотя объявлена только одна...

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Sirocco, работать с событиями удобно по флагам, я бы сделал примерно так:

unsigned long preMillis;
boolean start5sec;

void setup() {

  pinMode (13,OUTPUT);
  pinMode (5,INPUT);
  

}
void loop() 
{

  if (digitalRead (5) == LOW && !start5sec) {
    preMillis=millis();
    start5sec=true;
    digitalWrite(13, HIGH);
  }
  
  if(millis()-preMillis >5000 && start5sec){
    start5sec=false;
    digitalWrite(13, LOW);
  }
}

 

Sirocco
Offline
Зарегистрирован: 28.09.2013

Какая то ерунда. Во-первых millis не идёт пока нет условия, Serial.println выводит одно и тоже значение, и нарастает только когда условие есть, Во-вторых он не обнуляется по достижению значения описанного в условии 2.

P.S. не к предыдущему сообщению написано.

Sirocco
Offline
Зарегистрирован: 28.09.2013

dimax пишет:

Sirocco, работать с событиями удобно по флагам, я бы сделал примерно так:

unsigned long preMillis;
boolean start5sec;

void setup() {

  pinMode (13,OUTPUT);
  pinMode (5,INPUT);
  

}
void loop() 
{

  if (digitalRead (5) == LOW && !start5sec) {
    preMillis=millis();
    start5sec=true;
    digitalWrite(13, HIGH);
  }
  
  if(millis()-preMillis >5000 && start5sec){
    start5sec=false;
    digitalWrite(13, LOW);
  }
}

 

Этот код работает. Спасибо! Но не совсем правильно. Если событие наступило, выполняется условие и на 5 сек зажигается пин 13. Но если в течениие этих пяти секунд поступил снова сигнал, скажем на четвёртой секунде и пропал до истечения пяти секунд, то время не продляется. А должен начинаться отсчёт заново с каждого сигнала, при этом не гася выход.

Пытаюсь разобраться в вашем коде.

upd---------------------------------

Разобрался. Просто убрал проверку  && !start5seиз первого условия. В итоге рабочий код такой:

unsigned long preMillis;
boolean start5sec;

void setup() {

  pinMode (13,OUTPUT);
  pinMode (5,INPUT);
  

}
void loop() 
{

  if (digitalRead (5) == LOW) {
    preMillis=millis();
    start5sec=true;
    digitalWrite(13, HIGH);
  }
  
  if(millis()-preMillis >1000 && start5sec){
    start5sec=false;
    digitalWrite(13, LOW);
  }
}

Всем огромное спасибо!