1

I was trying to develop a traffic light signal controller . when the button is pressed, the pedestrian green light will turn on faster than before . I used delay() in Interrupt function, But it is not working as expected . I am totally new in Arduino coding. My whole code is below:

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(){
  
  
  
   //turn  carred,padgreen off padred high and cargreen on for 10 seconds
  digitalWrite(carred, LOW);
  digitalWrite(caryellow,LOW);
  digitalWrite(padred, HIGH);
  digitalWrite(cargreen, HIGH);
  delay(10000);
  
   //cargreen off,  turn on caryellow for 4 seconds
  
  digitalWrite(cargreen, LOW);
  digitalWrite(caryellow, HIGH);
  delay(4000);
  
   // turn caryellow and padred off,turn on padgreen, turn on carred for 7 seconds
  digitalWrite(caryellow, LOW);
  digitalWrite(padred,LOW);
  digitalWrite(padgreen,HIGH);
  digitalWrite(carred, HIGH);
  delay(7000);
  //turn padgreen off and padred high , caryellow high for 3 second
  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

what to write instead of dely() in interrupt function?

Nothing. An interrupt service routine (ISR) should not do any things, that take long. That will block any other things from happening, for example Serial communication (which is done by interrupts in the background).

delay() does not work in an ISR, because it relies on the millis() counter to increment. But that is done in another ISR. While one ISR is running, no other can run at the same time. Thus delay() waits forever, that the millis() counter increments.

What to do instead?

Instead you should only use the ISR to set a simple flag variable, for example of type boolean (because it should be a single byte type). Then in your main code (meaning inside loop()) you check for this flag. When it is set by the ISR, you execute the corresponding code and reset the flag. Be sure to declare the flag variable as volatile, so that the compiler knows, that is can change at any time.


That said, you should really ditch all the delay() calls. Instead use a non-blocking coding style involving millis() like in the BlinkWithoutDelay example, that comes with the Arduino IDE. There are tons of tutorials and explanations about that on the web and this site. Just search for it. Using a non-blocking coding style is needed, if you want the code to be responsive while doing long timed things.

Also you should look into Finite State Machines (FSM). Thats a very powerful principle, that will come in useful. It fits exactly on a traffic light project. I have once wrote a longer explanation about FSMs in my answer to this question, though you can also google something like "Arduino fsm". You basically divide the behavior of the project into individual states. The current state is hold by a variable. By changing that variable you transition between states. For example padcontrol() could change the state variable to the state for the pedestrian light. I strongly suggest, that you learn that principle to structure your code. I can attest, that it is really helpful.

4
  • 1
    Just to add to chrisi's excellent answer, I wouldn't use interrupts at all for this project. Imagine an impatient pedestrian repeatedly pushing the 'walk' button. Every time this happens, the ISR fires and takes over control of the MCU, no matter what is happening at the time. So, while the MCU is trying to respond to the pedestrian's first push, it gets interrupted and starts trying to respond AGAIN, and AGAIN, and AGAIN... If your program isn't structured to handle randomly occurring interrupts, it can make the program behave in unpredictable (read "hard to debug") ways.
    – starship15
    Nov 1 '20 at 17:02
  • You should just use polling to check the state of the buttons. That way the MCU is in total control, and can ignore the button states while it's busy
    – starship15
    Nov 1 '20 at 17:03
  • Thank you so much . Now I just found a way to go ahead
    – Saikot Das
    Nov 2 '20 at 15:35
  • @SaikotDas While it is important to learn the above about interrupts, user3765883 is right in that simple button checking can be easily done without interrupts in the main code when you use a non-blocking coding style. The loop() can then easily run fast enough to catch all button presses in a timely manner. Also debouncing can be easier that way. Maybe have a look at the Bounce2 library on github
    – chrisl
    Nov 2 '20 at 15:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.