что написать вместо delay() в функции прерывания?

Я пытался разработать контроллер сигнала светофора . при нажатии кнопки зеленый свет для пешеходов загорается быстрее, чем раньше. Я использовал delay() в функции прерывания, но она работает не так, как ожидалось. Я совершенно новичок в кодировании Arduino. Весь мой код приведен ниже:

int carred = 11;
int caryellow = 10;
int cargreen = 9;

int padred = 13;
int padgreen = 12;

int padpushbutton = 3;
int buspushbutton = 2;

void setup(){
  pinMode(carred , OUTPUT);
  pinMode(cargreen , OUTPUT);
  pinMode(caryellow , OUTPUT);
  
  pinMode(padgreen , OUTPUT);
  pinMode(padred , OUTPUT);
  
  pinMode(padpushbutton, INPUT_PULLUP);
  pinMode(buspushbutton,INPUT);
  attachInterrupt(digitalPinToInterrupt(padpushbutton), padcontrol,CHANGE);
 attachInterrupt(digitalPinToInterrupt(buspushbutton), buscontrol,CHANGE);
}
void loop()
    {
     carchangeLights();
 }
void carchangeLights(){
  
  
  
   //включите режим carred, padgreen выключите режим padred high и включите режим cargreen на 10 секунд
  digitalWrite(carred, LOW);
  digitalWrite(caryellow,LOW);
  digitalWrite(padred, HIGH);
  digitalWrite(cargreen, HIGH);
  delay(10000);
  
   // cargreen выкл., включите caryellow на 4 секунды
  
  digitalWrite(cargreen, LOW);
  digitalWrite(caryellow, HIGH);
  delay(4000);
  
   // выключите caryellow и padred, включите padgreen, включите carred на 7 секунд
  digitalWrite(caryellow, LOW);
  digitalWrite(padred,LOW);
  digitalWrite(padgreen,HIGH);
  digitalWrite(carred, HIGH);
  delay(7000);
  //выключите padgreen и включите padred high, caryellow high для 3-секундной
  digitalWrite(padgreen, LOW);
  digitalWrite(padred, HIGH);
  digitalWrite(caryellow, HIGH);
  delay(3000);
  
}


void padcontrol(){
  
  int red = digitalRead(carred);
  int yellow = digitalRead(caryellow);
  int green = digitalRead(cargreen);
  
  if (red == HIGH && yellow == LOW ) {
    digitalWrite(carred, HIGH);
    delay(2000);
    digitalWrite(padred, LOW);
    digitalWrite(padgreen, HIGH);
    delay(15000);
     }
    
 
  else if(yellow == HIGH && red == LOW){  
     digitalWrite(caryellow, HIGH);
    delay(2000);
    digitalWrite(caryellow,LOW);
    digitalWrite(carred,HIGH);
    digitalWrite(padred,LOW);
    digitalWrite(padgreen,HIGH);
      delay(15000);
    }
  else if(yellow == HIGH && red == HIGH) {  
   digitalWrite(caryellow, HIGH);
    delay(1000);
    digitalWrite(caryellow,LOW);
    digitalWrite(padred,LOW);
    digitalWrite(padgreen,HIGH);
      delay(15000);
    }
   else{
    digitalWrite(cargreen,LOW); 
    digitalWrite(caryellow,HIGH);
    delay(3000);
     
    digitalWrite(caryellow,LOW);
    digitalWrite(carred,HIGH);
    digitalWrite(padred,LOW);
    digitalWrite(padgreen,HIGH);
    delay(15000);
   }
     
     
}

void buscontrol(){
  
  int red = digitalRead(carred);
  int yellow = digitalRead(caryellow);
  int green = digitalRead(cargreen);
  
  if (red == HIGH && yellow == LOW ) {
    digitalWrite(carred, HIGH);
    delay(3000);
    digitalWrite(carred,LOW);
    digitalWrite(padgreen, LOW);
    digitalWrite(padred, HIGH);
    digitalWrite(caryellow, HIGH);
    delay(2000);
    digitalWrite(caryellow,LOW);
    digitalWrite(cargreen, HIGH);
    delay(10000);
    
     }
    
 
  else if(yellow == HIGH && red == LOW) {
    digitalWrite(padgreen,LOW);
    digitalWrite(padred,HIGH);
   digitalWrite(caryellow, HIGH);
    delay(2000);
    digitalWrite(caryellow,LOW);
    digitalWrite(cargreen,HIGH);
      delay(10000);
    }
  else if(yellow == HIGH && red == HIGH) {  
   digitalWrite(caryellow, HIGH);
    delay(1000);
    digitalWrite(carred,LOW);
    digitalWrite(caryellow,LOW);
   
    digitalWrite(padgreen,LOW);
       digitalWrite(padred,LOW);
     digitalWrite(cargreen, HIGH);
      delay(10000);
    }
   else{
    digitalWrite(padred,HIGH);
    digitalWrite(cargreen,LOW); 
    delay(10000);
     
   }
}

, 👍1


1 ответ


1

что написать вместо функции dely() в функции прерывания?

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

delay() не работает в ISR, поскольку для увеличения он использует счетчик millis(). Но это делается в другом ISR. Пока работает один ISR, ни один другой не может работать одновременно. Таким образом, delay() ожидает вечно, что счетчик millis() увеличится.

Что делать вместо этого?

Вместо этого вы должны использовать ISR только для установки простой переменной флага, например, типа boolean (потому что это должен быть однобайтовый тип). Затем в вашем основном коде (имеется в виду внутренний цикл ()) вы проверяете наличие этого флага. Когда он установлен ISR, вы выполняете соответствующий код и сбрасываете флаг. Обязательно объявите переменную flag как volatile, чтобы компилятор знал, что она может измениться в любое время.


Тем не менее, вам действительно следует отказаться от всех вызовов delay(). Вместо этого используйте неблокирующий стиль кодирования, включающий millis(), как в примере BlinkWithoutDelay, который поставляется с Arduino IDE. В Интернете и на этом сайте есть множество руководств и объяснений по этому поводу. Просто поищите его. Использование неблокирующего стиля кодирования необходимо, если вы хотите, чтобы код был отзывчивым при выполнении длительных задач.

Также вам следует изучить конечные автоматы (FSM). Это очень мощный принцип, который пригодится. Он точно вписывается в проект светофора. Однажды я написал более подробное объяснение FSMs в своем ответе на этот вопрос, хотя вы также можете погуглить что-то вроде "Arduino fsm". Вы в основном делите поведение проекта на отдельные состояния. Текущее состояние удерживается переменной. Изменяя эту переменную, вы переходите между состояниями. Например, padcontrol() может изменить переменную состояния на состояние для пешеходного света. Я настоятельно рекомендую вам изучить этот принцип для структурирования вашего кода. Я могу засвидетельствовать, что это действительно полезно.

,

Просто чтобы добавить к превосходному ответу Криси, я бы вообще не использовал прерывания для этого проекта. Представьте себе нетерпеливого пешехода, который постоянно нажимает на кнопку "идти". Каждый раз, когда это происходит, ISR срабатывает и берет на себя управление MCU, независимо от того, что происходит в данный момент. Итак, в то время как микроконтроллер пытается отреагировать на первый толчок пешехода, он прерывается и начинает пытаться реагировать СНОВА, и СНОВА, и СНОВА... Если ваша программа не структурирована для обработки случайно возникающих прерываний, это может привести к непредсказуемому поведению программы (читай "трудному для отладки")., @user3765883

Вы должны просто использовать опрос, чтобы проверить состояние кнопок. Таким образом, MCU находится под полным контролем и может игнорировать состояния кнопок, пока он занят, @user3765883

Большое вам спасибо . Теперь я просто нашел способ идти вперед, @Saikot Das

@SaikotDas Хотя важно изучить вышесказанное о прерываниях, пользователь3765883 прав в том, что простая проверка кнопок может быть легко выполнена без прерываний в основном коде, когда вы используете неблокирующий стиль кодирования. Затем цикл () может легко выполняться достаточно быстро, чтобы своевременно перехватывать все нажатия кнопок. Кроме того, таким образом, демонтаж может быть проще. Может быть, взгляните на библиотеку Bounce2 на [github] (https://github.com/thomasfredericks/Bounce2 ), @chrisl