Задержка без delay

Iskander-ufa
Offline
Зарегистрирован: 11.05.2015

Всем привет. есть светодиод, который должен включиться при наступлении определенного события (в loop'e) с задержкой  в ~0,5 сек. Если событие наступило-  включается через 0,5сек, отступило - выключается через 0,5сек.

MILLIS? че то не получается. подскажите пожалуйста

int ledPin = 9;    
int analogPin = 5; 
int val = 0;       
 unsigned long currentTime;
unsigned long loopTime;

void setup()
{ currentTime = millis();       // считываем время, прошедшее с момента запуска программы
  loopTime = currentTime;
  
    pinMode(ledPin, OUTPUT);   
 pinMode(12, OUTPUT);    // установка порта на выход
}
 
void loop()
{
 
   val = analogRead(analogPin);
if (val > 254)       //при наступлении этого события должен вкл. светодиод
          { val = 255;
         currentTime = millis();                           // считываем время, прошедшее с момента запуска программы
  if(currentTime - loopTime >500){              // сравниваем текущий таймер с переменной loopTime + 1 секунда
   digitalWrite(12, HIGH);     /
    loopTime = currentTime;                         // в loopTime записываем новое значение
  }
         }
            if (val >80)       
           { val = 250;
            currentTime = millis();                           // считываем время, прошедшее с момента запуска программы
  if(currentTime - loopTime >500){              // сравниваем текущий таймер с переменной loopTime + 1 секунда
   digitalWrite(12, LOW);     
    loopTime = currentTime;                         // в loopTime записываем новое значение
  }}
          
    if (val < 80)       
           { val = 0;
           currentTime = millis();                           // считываем время, прошедшее с момента запуска программы
  if(currentTime - loopTime >500){              // сравниваем текущий таймер с переменной loopTime + 1 секунда
   digitalWrite(12, LOW);     
    loopTime = currentTime;                         // в loopTime записываем новое значение
  }}
           
                         

          
    analogWrite(ledPin, val); 
   



}

 

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

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

:)

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

куррентайм - это же и есть миллис , лишняя переменная
луптайм - время жизни программы не нужно

для событий нужно millisOldEvent1 , millisOldEvent2 , millisOldEvent3 ..........
и отслеживать по
if ( 
millis() - millisOldEvent1 > 500 )
if ( millis() - millisOldEvent2 > 100 )
if ( millis() - millisOldEvent3 > 58 )

vov4ik
Offline
Зарегистрирован: 10.09.2013

Как по условию я понял что нужно два таймера один с задержкой на включение второй с задержкой на отключение, по уставкам лудше поставить защелку типа RS-тригер 

if((analogRead (5)) > (250)) trgrs = 1;
if((analogRead (5)) < (80)) trgrs = 0;
как только тригер 1 запустить первый таймер после его отработки включить светик, тригер 0 сбростить таймер
как только тригер 0 запустить второй таймер после его отработки выключить светик, тригер 1 сбростить таймер
dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Мой вариант решения, по флагам events_now (0..5) программа всегда знает в какой фазе исполнения она находится:

#define ledPin  13    
#define analogPin  5 
int val;
byte events_now=0;
unsigned long prevmillis;
void setup(){
pinMode(ledPin, OUTPUT);   
}
 
void loop(){
val=analogRead(analogPin);
  if (val>254&&events_now==0) events_now=1 ; 
  if (val<254&&events_now==3) events_now=4  ; 
  if (events_now) led_mode();
}

void led_mode (){
switch (events_now) { 
       case 1: // если сработало 1 раз
          prevmillis=millis(); 
          events_now=2; //флаг что идёт отсчёт до начала включения лед
           break;     
       case 2: //если считаем время до включения
          if (millis()-prevmillis >500) {
          digitalWrite (ledPin,HIGH);  
          events_now=3;}// лед горит, ожидаем val <254
          break;  
        case 4: // заявка на отключение лед
             prevmillis=millis(); 
             events_now=5;
             break;
        case 5: // счёт до отключения идёт
             if (millis()-prevmillis >500){ 
             digitalWrite (ledPin,LOW);
             events_now=0;} //все этапы пройдёны
      }            
}
 

 

vov4ik
Offline
Зарегистрирован: 10.09.2013

dimax 

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

X-Dron
Offline
Зарегистрирован: 24.01.2015

Аналогичный алгоритм я делал так

#include <Timer_P.h>
bool Night;

Timer_P LightFilterOn, LightFilterOff;

void setup()
{
}

void loop()
{
  //датчик света
  if (LightFilterOn.Timer(analogRead(A0) > 100, false, 2, 10000)) Night = true;
  if (LightFilterOff.Timer(analogRead(A0) < 100, false, 2, 10000)) Night = false;
}

Это фильтрация аналогового датчика освещенности. Временной гистерезис. 10000 в таймерах - период в течение которого должно выполняться условие первого операнда метода .Timer. Гистерезис по значению тоже есть <=99 отключение  и >=101 включение, но вданном примере не играет основную роль.
Понадобится эта библиотека.
https://yadi.sk/d/hGQy8xu1fZNks

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

dimax пишет:

Мой вариант решения, по флагам events_now (0..5) программа всегда знает в какой фазе исполнения она находится:

#define ledPin  13    
#define analogPin  5 
int val;
byte events_now=0;
unsigned long prevmillis;
void setup(){
pinMode(ledPin, OUTPUT);   
}
 
void loop(){
val=analogRead(analogPin);
  if (val>254&&events_now==0) events_now=1 ; 
  if (val<254&&events_now==3) events_now=4  ; 
  if (events_now) led_mode();
}

void led_mode (){
switch (events_now) { 
       case 1: // если сработало 1 раз
          prevmillis=millis(); 
          events_now=2; //флаг что идёт отсчёт до начала включения лед
           break;     
       case 2: //если считаем время до включения
          if (millis()-prevmillis >500) {
          digitalWrite (ledPin,HIGH);  
          events_now=3;}// лед горит, ожидаем val <254
          break;  
        case 4: // заявка на отключение лед
             prevmillis=millis(); 
             events_now=5;
             break;
        case 5: // счёт до отключения идёт
             if (millis()-prevmillis >500){ 
             digitalWrite (ledPin,LOW);
             events_now=0;} //все этапы пройдёны
      }            
}
 

 

А нафиг здесь вообще в loop такие сложности, проще в луп вызывать led_mode, а уже в нем считывать analogRead и тогда будет всё под рукой и этот конечный автомат (а он здесь напрашивается по полной програме, тупо и просто) будет в одном месте, а не размазан по разным точкам.

Вместо 12 строки проверка в switch (events_now) { case 0: ...
А вместо 13 строки проверка в switch... case 3: if(val<254) events_now = 4; или типа того.

UPD: И да, классика, всё что в аналоге, имеет сволочную особенность, ловить помехи и лучше в таких местах закладывать гистерезис (разносить точки включения и выключения). Да что говорить, тут описано

tika
Offline
Зарегистрирован: 22.07.2015

Здравствуйте - Подскажите что врезать здесь- для выполнение команды с задержкой до 6 секунд.

1-кнопка - нажатие первое старт таймера 1, нажатие 2-раза старт таймера 2. эта кнопка работает нормально.

Проблема с 2 кнопкой.

2-кнопка нужно 1-вое нажатие стоп таймера 1 и через 6 секунд само сброс таймера 1,нажатие 2 -го раза этой кнопки стоп таймере 2 и через 6 секунд само брос иаймера 2.

 

ТО ЕСТЬ__________________________________________________________________________________

if (Last2State && Lap2State == LOW) {// выполнять действие     
    LapCount2++;  
 
if (LapCount2 == 0 || LapCount2 == 1) {// выполнять действие "СТОП-1"ЭТО ПЕРВОЕ НАЖАТИЕ КНОПКИ -2
      Timer1State= LOW;
      Serial.print("Raider Num ");//выводит строку "Raider Num "
      Serial.print(Raider1);
      Serial.print(", Time - ");//выводит строку ", Time - "
      Serial.println(buffer1);
 
ЗДЕСЬ НУЖНА КОМАНДА ЗАДЕРЖКИ НА 6СЕКУНД И ВЫПОЛНЕНИЕ СЛЕДУЮЩЕЙ НИЖЕ САМО ВЫПОЛНЕНИЕ
 
    }
    if (LapCount2 == 1) {// выполнять действие "СБРОС Timer-1" при 1 нажатие кнопки -2
      LapCount2 = 0; 
      TimerMillis1=0;
      print_time1(0);
      Timer1State= LOW;
    }
    if (LapCount2 == 0 || LapCount2 == 2) {// выполнять действие  "СТОП-2"ЭТО ВТОРОЕ НАЖАТИЕ КНОПКИ-2
      Timer2State= LOW;
      Serial.print("Raider Num ");//выводит строку "Raider Num "
      Serial.print(Raider2);
      Serial.print(", Time - ");//выводит строку ", Time - "
      Serial.println(buffer2);
 
    ЗДЕСЬ НУЖНА  КОМАНДА ЗАДЕРЖКИ НА 6СЕКУНД И ВЫПОЛНЕНИЕ СЛЕДУЮЩЕЙ НИЖЕ САМО ВЫПОЛНЕНИЕ
     }
    if (LapCount2 == 2) {// выполнять действие "СБРОС Timer-2" при 2 нажатие кнопки -2
      LapCount2 = 0; 
      TimerMillis2=0;
      print_time2(0);

      Timer2State= LOW;

 

Клапауций 777
Offline
Зарегистрирован: 21.11.2015

tika пишет:

Здравствуйте - Подскажите что врезать здесь- для выполнение команды с задержкой до 6 секунд.

1-кнопка - нажатие первое старт таймера 1, нажатие 2-раза старт таймера 2. эта кнопка работает нормально.

Проблема с 2 кнопкой.

2-кнопка нужно 1-вое нажатие стоп таймера 1 и через 6 секунд само сброс таймера 1,нажатие 2 -го раза этой кнопки стоп таймере 2 и через 6 секунд само брос иаймера 2.

ТО ЕСТЬ__________________________________________________________________________________

if (Last2State && Lap2State == LOW) {// выполнять действие     
    LapCount2++;  
 
if (LapCount2 == 0 || LapCount2 == 1) {// выполнять действие "СТОП-1"ЭТО ПЕРВОЕ НАЖАТИЕ КНОПКИ -2
      Timer1State= LOW;
      Serial.print("Raider Num ");//выводит строку "Raider Num "
      Serial.print(Raider1);
      Serial.print(", Time - ");//выводит строку ", Time - "
      Serial.println(buffer1);
 
ЗДЕСЬ НУЖНА КОМАНДА ЗАДЕРЖКИ НА 6СЕКУНД И ВЫПОЛНЕНИЕ СЛЕДУЮЩЕЙ НИЖЕ САМО ВЫПОЛНЕНИЕ
    }
    if (LapCount2 == 1) {// выполнять действие "СБРОС Timer-1" при 1 нажатие кнопки -2
      LapCount2 = 0; 
      TimerMillis1=0;
      print_time1(0);
      Timer1State= LOW;
    }
    if (LapCount2 == 0 || LapCount2 == 2) {// выполнять действие  "СТОП-2"ЭТО ВТОРОЕ НАЖАТИЕ КНОПКИ-2
      Timer2State= LOW;
      Serial.print("Raider Num ");//выводит строку "Raider Num "
      Serial.print(Raider2);
      Serial.print(", Time - ");//выводит строку ", Time - "
      Serial.println(buffer2);
    ЗДЕСЬ НУЖНА  КОМАНДА ЗАДЕРЖКИ НА 6СЕКУНД И ВЫПОЛНЕНИЕ СЛЕДУЮЩЕЙ НИЖЕ САМО ВЫПОЛНЕНИЕ
     }
    if (LapCount2 == 2) {// выполнять действие "СБРОС Timer-2" при 2 нажатие кнопки -2
      LapCount2 = 0; 
      TimerMillis2=0;
      print_time2(0);

      Timer2State= LOW;

проверь, должно скомпилиться

tika
Offline
Зарегистрирован: 22.07.2015

Вау- клева. А по вопросу как?