Прервать выполнение функции немедленно

antonzol
Offline
Зарегистрирован: 09.01.2017

Друзья, привет!

Делаю светофор с четырьма режимами:

0. автопереключалка

1. красный

2. желтый

3. зеленый

Все хорошо пока не выполняю функцию autol() она выполняется непрерывно.

Подскажите пожалуйста, как можно:

1. Прервать выполнение функции немедленно.

2. При возвращении в функцию начать не с того же места а с начала. То-есть заново ее запустить и забыть о прерваной итерации.

Код ниже:

int red = 2;
int yellow = 3;
int green = 4;
int sb = 12;
int modec = 1;
int reading;
int lastButtonState=LOW;
int buttonState=LOW;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 0;

void setup() {
  // put your setup code here, to run once:
  pinMode(red, OUTPUT);     
  pinMode(yellow, OUTPUT);     
  pinMode(green, OUTPUT);     
  pinMode(sb, INPUT);    
}



void loop (){
  int reading = digitalRead(sb);
  if (reading != lastButtonState) {
      lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
     if (reading != buttonState) {
      buttonState = reading;
      if (buttonState == HIGH) {
       modec++;
  if (modec==4) {
    modec=0;
  }
      }
    }
  }

  
if (modec==0) {
  digitalWrite(red,LOW);
  digitalWrite(yellow,LOW);
  digitalWrite(green,LOW);
  autol();
}
if (modec==1) {
  digitalWrite(red,HIGH);
  digitalWrite(yellow,LOW);
  digitalWrite(green,LOW);
}
if (modec==2) {
  digitalWrite(red,LOW);
  digitalWrite(yellow,HIGH);
  digitalWrite(green,LOW);
}
if (modec==3) {
  digitalWrite(red,LOW);
  digitalWrite(yellow,LOW);
  digitalWrite(green,HIGH);
}
}

void autol() {
   digitalWrite(red, HIGH);
  delay(5000);
  digitalWrite(red, LOW);

  digitalWrite(yellow, HIGH);
  delay(1000);
  digitalWrite(yellow, LOW);

  digitalWrite(green, HIGH);
  delay(5000);
  digitalWrite(green, LOW);

  digitalWrite(yellow, HIGH);
  delay(2000);
  digitalWrite(yellow, LOW);
  return;
}

 

inspiritus
Offline
Зарегистрирован: 17.12.2012

А какое событие должно вызвать это прерывание?

(мне кажется , или я ответил на его вопрос)

Клапауций 234
Offline
Зарегистрирован: 24.10.2016
void reset() {
red = 2;
yellow = 3;
green = 4;
sb = 12;
modec = 1;
lastButtonState=LOW;
buttonState=LOW;
lastDebounceTime = 0;
debounceDelay = 0;
}

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

antonzol пишет:

Все хорошо пока не выполняю функцию autol() она выполняется непрерывно.

Подскажите пожалуйста, как можно:

1. Прервать выполнение функции немедленно.

2. При возвращении в функцию начать не с того же места а с начала. То-есть заново ее запустить и забыть о прерваной итерации.

Повторяю для тах кто в ТАНКЕ, delay() прервать нельзя. Разве подождать когда она закончится. А будет это в loop(), или в функции безразлично.

Поэтой причине удобная функция delay() так НЕУДОБНА. используйте millis().

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Пока нет ответа на вопрос inspiritus, всё остальное - толчение воды в ступе. Ждем-с :)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

qwone пишет:

Повторяю для тах кто в ТАНКЕ, delay() прервать нельзя. 

Да, ладно Вам. Любое, самое замухрыжное прерывание, прервёт delay за милую душу.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

ЕвгенийП пишет:

Да, ладно Вам. Любое, самое замухрыжное прерывание, прервёт delay за милую душу.

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

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

qwone пишет:
Повторяю для тах кто в ТАНКЕ, delay() прервать нельзя. Разве подождать когда она закончится. А будет это в loop(), или в функции безразлично.

всегда можно нажать кнопку reset и случится то, чего желает ТС

inspiritus
Offline
Зарегистрирован: 17.12.2012

... или сделать программный ресет...

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

inspiritus пишет:

... или сделать программный ресет...

ага - из делея прерыванием

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

qwone пишет:

И дальше что?

Что нужно программисту, то и дальше.

nik182
Offline
Зарегистрирован: 04.05.2015

Ну так напишите свой delay() в котором будет выход по условию. Это ж программа. Не нравится стандартный delay - ни кто не запрещает написать свой, если клапауция всуе не упоминать.

Voodoo Doll
Voodoo Doll аватар
Offline
Зарегистрирован: 18.09.2016
#include <avr\wdt.h>
const byte ldata[120]={1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,
  3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
  4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,4,0,4,0,4,2,2,2,2,
  2,2,2,2,2,2};
#define RED    (2)
#define YELLOW (3)
#define GREEN  (4)
#define BTN    (12)
unsigned long last_d=millis(), // last data change
              last_b=millis(); // last button time
byte pos=0;                    // cycle position
bool hold=false;               // stay on single color
void setup() {                
  wdt_enable(WDTO_2S);
  pinMode(RED, OUTPUT);     
  pinMode(YELLOW, OUTPUT);     
  pinMode(GREEN, OUTPUT);
  pinMode(BTN, INPUT);
}
void loop() {
  wdt_reset();
  if(hold){
    if(millis()-last_b>=500 && digitalRead(BTN)){     // button poll
      switch(pos){
        case 0:   pos=110; break; // yellow
        case 104: pos=0;   break; // red
        case 109: pos=0;hold=false;last_d=millis();break; // ret to normal mode
        case 110: pos=109; break; // green
      }
      last_b=millis();
    }
  }else{
    if(millis()-last_d>=500){            // animation cycle
      if(pos<119) pos+=1;
       else pos=0;
      last_d=millis();
    }
    if(millis()-last_b>=500 && digitalRead(BTN)){     // button poll
      hold=true;
      pos=104;                           // no color
      last_b=millis();
    }
  }
  digitalWrite(RED,   ldata[pos]&1);     //show
  digitalWrite(YELLOW,ldata[pos]&2);
  digitalWrite(GREEN, ldata[pos]&4);
}
gena
Offline
Зарегистрирован: 04.11.2012

   Не хочу вникать в программу ТС, но если Вы хотите быстро прервать delay-длиное, то можно вместо длиного  delay использовать свою функцию, которая будет тысячу раз, в цикле, использовать в тысячу раз болеее короткий delay. А между использованиями короткого delay, проверяйте нужное Вам условие для быстрого прекращения длинного delay. Если оно, условие, возникло, то прекращаете работу своей функции. Например, в операторе  for(int i=0; i <= 1000; i++){delay(1);..........}  переменной  i по нужному Вам условию присваиваете  i=1000 и цикл скоропостижно завершается.

Клапауций 234
Offline
Зарегистрирован: 24.10.2016
qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Ну я конечно не решил вопрос с перыванием delay(). Я просто написал иначе программу. Я проверил собирайте и закачивайте скетч.

/*millis_antonzol.ino
  #1 светодиоды красный ->2 (Red_pin)    1 горит / 0 нет
              желтый  ->3 (Yellow_pin) 1 горит / 0 нет
              зеленый ->4 (Green_pin)  1 горит / 0 нет
  #2 кнопка             ->5 (Btn1_pin)   0 нажата / 0 нет
*/
//#1
const int Red_pin = 2;
bool Red;
const int Yellow_pin = 3;
bool Yellow;
const int Green_pin = 4;
bool Green;
//#2 кнопка
const int Btn1_pin = 5;
bool Btn1, Btn1_old;
bool Bounce_Btn1 = 0; // антидребезговый флаг
byte modec = 1; // режим 1 красный мигает / 2 желтый мигает /3 зеленый / переключение R -> Y -> G -> Y -> R
byte step = 1; // 1  мигает красный /1  мигает желтый /1  мигает зеленый
void setup() {
  //#1
  pinMode(Red_pin, OUTPUT);
  digitalWrite(Red_pin, Red = 0);
  pinMode(Yellow_pin, OUTPUT);
  digitalWrite(Yellow_pin, Yellow = 0);
  pinMode(Green_pin, OUTPUT);
  digitalWrite(Green_pin, Green = 0);
  //#2
  pinMode(Btn1_pin, INPUT_PULLUP);// подключить кнопку 1 с подтяжкой
  Btn1 = digitalRead(Btn1_pin);
}
void loop () {
  //#1
  static uint32_t past_1 = 0 ;
  static uint32_t past_3 = 0 ;
  if ((modec == 1 || modec == 4 && step == 1) && millis() - past_1 > 300) { // 0,3 сек мигание красным
    past_1 = millis();
    digitalWrite(Red_pin, Red = ! Red);
    if (! Red &&  millis()- past_3 > 5000) { // если красный в режиме 4 мигает больше 5 сек
      past_3 = millis();
      step = 2;
    }
  }
  if ((modec == 2 || modec == 4 && (step == 2 || step == 5)) && millis() - past_1 > 300) { // 0,3 сек мигание желтым
    past_1 = millis();
    digitalWrite(Yellow_pin, Yellow = ! Yellow);
    if (! Yellow && millis()- past_3 > 2000) { // если желтым в режиме 4 мигает больше 2 сек
      past_3 = millis();
      if (step == 2)step = 3; // R->Y->G
      if (step == 5)step = 1;// G->Y->R
    }
  }
  if ((modec == 3 || modec == 4 && step == 3) && millis() - past_1 >  300) { // 0,3 сек мигание зеленым
    past_1 = millis();
    digitalWrite(Green_pin, Green = ! Green);
    if (! Green && millis()- past_3 > 5000) { // если желтым в режиме 4 мигает больше 5 сек
      past_3 = millis();
      step = 5;
    }
  }
  //#2
  static uint32_t past_2 = 0 ;
  if (! Bounce_Btn1 && Btn1 != digitalRead(Btn1_pin)) { // если прошел фронт изм на выводн
    Bounce_Btn1 = 1;                                 // выставить флаг
    past_2 = millis();                          // сделать временую засветку
  }
  else if ( Bounce_Btn1 && millis() - past_2 >= 5 ) { // если прошло антидребезговое время
    Bounce_Btn1 = 0;      // то снять флаг
    Btn1_old = Btn1;
    Btn1 = digitalRead(Btn1_pin) ; // прочитать реальное значение на выводе
    if (Btn1_old && ! Btn1) {
      modec ++ ;
      if (modec > 4) modec = 1;
      digitalWrite(Red_pin, Red = 0);
      digitalWrite(Yellow_pin, Yellow = 0);
      digitalWrite(Green_pin, Green = 0);
    }
  }
}

 

AmateurFF
Offline
Зарегистрирован: 02.02.2015

А ТС еще спит?

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

AmateurFF пишет:

А ТС еще спит?

разбудить?

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

qwone пишет:
Повторяю для тах кто в ТАНКЕ, delay() прервать нельзя. 

Ахахахаха! Срочно за учебник!

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

andreykrasnodar пишет:

qwone пишет:
Повторяю для тах кто в ТАНКЕ, delay() прервать нельзя. 

Ахахахаха! Срочно за учебник!

Достал банку с попкорном... ))

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

Лучше учебник.

b707
Offline
Зарегистрирован: 26.05.2017

универсальный прерыватель функций

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

v258 пишет:

andreykrasnodar пишет:

qwone пишет:
Повторяю для тах кто в ТАНКЕ, delay() прервать нельзя. 

Ахахахаха! Срочно за учебник!

Достал банку с попкорном... ))

Присоединяюсь

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

b707 пишет:

универсальный прерыватель функций

у него время срабатывания 100 миллисекунд, при токе более 200 ампер )))

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Если делей на 5 часов, то пойдеть )))))

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

andreykrasnodar пишет:

qwone пишет:
Повторяю для тах кто в ТАНКЕ, delay() прервать нельзя. 

Ахахахаха! Срочно за учебник!

ну давай, вещай, прерыватель делеев.

сегодня твой день, что не пост прям хоть записывай.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

xDriver пишет:

ну давай, вещай, прерыватель делеев.

...иш...петь хотели заставить...