Best way to integrate a interrupt into my code

I'm working on my code trying to incorporate a interrupt into my code but I'm running into issues.
This is my previous code without interrupt:

#include <avr/io.h>
#define F_CPU 16000000
#include <util/delay.h>
void setup()
{
  DDRB = 0b00111000; 
  DDRD = 0b11111011;
  PORTD = 0b00000000;
}
void loop()
{
  int PButton=digitalRead(2);
	if (PButton == 0b00000000)
  {
    delay(3000);        
    PORTB = 0b00010000;
    delay(3000);              
    PORTB = 0b00001000;    
    delay(2000);              
    PORTD = 0b01000000;    
    delay(8000);
    PORTD = 0b10000000;
    delay(2000); 
    
  }
   else    
   {

    PORTB = 0b00100000;
    PORTD = 0b10000000;       
   }
}

This is my code after trying to incorporate a interrupt:

#include <avr/io.h>
#define F_CPU 16000000
#include <util/delay.h>
#include <avr/interrupt.h>
void setup();
void initint0();
void loop(){};
void setup()
{
  DDRB = 0b00111000; 
  DDRD = 0b11111011;
  PORTD = 0b00000000;
}
void initint0()
{
SREG |= 0b10000000; 
EIMSK |= 0b00000001; 
EICRA |= 0b00000001; 
}
ISR (INT0_vect) 
{
  int PButton=digitalRead(2);
	if (PButton == 0b00000000)
  {
    delay(3000);        
    PORTB = 0b00010000;
    delay(3000);              
    PORTB = 0b00001000;    
    delay(2000);              
    PORTD = 0b01000000;    
    delay(8000);
    PORTD = 0b10000000;
    delay(2000); 
    
  }
   else    
   {

    PORTB = 0b00100000;
    PORTD = 0b10000000;       
   }
}

This code is used to run a stoplight circuit with pedestrian push button and light
The circuit is attached:
The project is supposed to a green light on while the pedestrians red light is on. When the button is pressed the light goes from green to yellow in 3 seconds and red in another 3 seconds. Then the pedestrian will get the green light. Then after 8 seconds it goes back to red.
I want to add a interrupt that when the button is pressed the lights will automatically both go to red but I'm having trouble if you have any tips or advice how to go upon this please let me know, Thank you.

My tip is “ask yourself why you think you need an interrupt”.

Maybe also ask yourself “why am I making things hard for myself, having to remember port-to-pin mappings?”

And, “even when I’ve been told not to, why do I put huge delays in an ISR?”

Basically echoing above

It might help if you actually call initint0.

Don't use delay in interrupts; delay relies on interrupts.

And if you like to play with direct port manipulation, be consistent and don't use digitalRead :wink:

Lastly, for your application, there is no need for interrupts; just write non-blocking code based on millis().

Leaving aside the (non-) desirability of using an interrupt, I don't understand this line:

when the button is pressed the lights will automatically both go to red

Is that over and above this requirement:

When the button is pressed the light goes from green to yellow in 3 seconds and red in another 3 seconds. Then the pedestrian will get the green light. Then after 8 seconds it goes back to red.

.... and at what point in the process does that happen?

I guess this is a school type project (or similar learning exercise) and you’ve been asked to solve it demonstrating certain techniques such as use of interrupts and direct port manipulation, or you want to do a basic timing using delay() statements, and want some way of skipping over the delay statements when a button is pressed.

It has already been pointed out that delay() statements in an interrupt service routine don’t work.

If you must use an external interrupt, set a global (volatile) flag (say interruptFlag )in its interrupt service routine and test that in your main logic, then reset the flag for the next time.

If you have to use delay() statements in your main loop() you can do this, but using the millis() timer function as demonstrated in the classic example “blink without delay” is the much better way of doing it :

    for( int i=0; i<300 && interruptFlag == false ; i++) delay( 10 );       
    PORTB = 0b00010000;  // possibly also only if interruptFlag == false

    for( int i=0; i<300 && ! interruptFlag ; i++) delay( 10 );             
    PORTB = 0b00001000;   
    . . .

That is not what interrupts are for!

As a beginner, it is incredibly unlikely that interrupts will be useful to you.

A common “newbie” misunderstanding is that an interrupt is a mechanism for altering the flow of a program - to execute an alternate function. Nothing could be further from the truth! :astonished:

An interrupt is a mechanism for performing an action which can be executed in “no time at all” with an urgency that it must be performed immediately or else data - information - will be lost or some harm will occur. It then returns to the main task without disturbing that task in any way though the main task may well check at the appropriate point for a “flag” set by the interrupt.

Now these criteria are in a microprocessor time scale - microseconds. This must not be confused with a human time scale of tens or hundreds of milliseconds or indeed, a couple of seconds. A switch operation is in this latter category and even a mechanical operation perhaps several milliseconds; the period of a 6000 RPM shaft rotation is ten milliseconds. Sending messages to a video terminal is clearly in no way urgent,

Unless it is a very complex procedure, you would expect the loop() to cycle many times per millisecond. If it does not, there is most likely an error in code planning; while the delay() function is provided for testing purposes, its action goes strictly against effective programming methods. The loop() will be successively testing a number of contingencies as to whether each requires action, only one of which may be whether a particular timing criteria has expired. Unless an action must be executed in the order of microseconds, it will be handled in the loop().

So what sort of actions do require such immediate attention? Well, generally those which result from the computer hardware itself, such as high speed transfer of data in UARTs(, USARTs) or disk controllers.

An alternate use of interrupts, for context switching in RTOSs, is rarely relevant to this category of microprocessors as it is more efficient to write cooperative code as described above.


If indeed, this happens to be a school assignment, you have a big problem. Asking you to use interrupts for this purpose would ipso facto indicate either that the instructor is playing a very devious game by expecting you to have this advanced knowledge of the function of interrupts and reply accordingly with an explanation of how inappropriate it is, or is himself actually incompetent! :roll_eyes:

Paul__B:
That is not what interrupts are for!

As a beginner, it is incredibly unlikely that interrupts will be useful to you.
. . .
. . .
. . .

Whereas generally all that is true, (although I would not go so far as to questions the competence of any possible instructor involved if, indeed, this is a school assignment), there are legitimate applications for interrupts triggered by push buttons. Take the case of a battery powered device where the MCU is in sleep mode to preserve power. Here it makes perfect sense that a button on the device triggers an interrupt to wake the device and then goes on to perform another set function.

Further, for educational purposes, important is that the student is exposed to a particular relevant topic, and is given easily verifiable assignments to test the knowledge acquired. Often, such assignments are dressed up as a concrete example of a real world problem so it is not too abstract for the student although, clearly, some liberties may be taken in presenting it as something practical.

Err, yes! :grinning:

I want to rewrite this code using a interrupt but I’m not sure where to insert the code I already have into a interrupt function using volatile and ISR. I want to make an interrupt that executes on the falling edge.

#include <avr/io.h>
#define F_CPU 16000000
#include <LiquidCrystal.h>
#include <util/delay.h>
int Photoresistor = 0;
const int rs = 10, en = 9, d4 = 8, d5 = 5, d6 = 4, d7= 3;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
void setup()
{
  DDRB = 0b00111000; 
  DDRD = 0b11111011;
  PORTD = 0b00000000;
  
    pinMode(A0, INPUT);
  Serial.begin(9600);

  pinMode(13, OUTPUT);
  pinMode(7, OUTPUT);
    
  lcd.begin(16, 2);
  lcd.print("Dont Walk");
  
  

}
void loop()
{
  Photoresistor = analogRead(A0);
  Serial.println(Photoresistor);
  analogWrite(13, map(Photoresistor, 0, 1023, 0, 200));
  analogWrite(7, map(Photoresistor, 0, 1023, 0, 200));
  delay(100);
  
  lcd.setCursor(0,1);
  

 int PButton=digitalRead(2);
	if (PButton == 0b00000000)    
  {
    delay(3000);        
    PORTB = 0b00010000;
    delay(3000);              
    PORTB = 0b00001000;    
    delay(2000);              
    PORTD = 0b01000000;  
      lcd.print("Walk Now");
    delay(8000);
    PORTD = 0b10000000;
    delay(2000);
      
    }
   else    
   {
    PORTB = 0b00100000;
    PORTD = 0b10000000;
       
   }
  }

Some help or advice on how to proceed would be great, thank you so much.

I don't see anything in there that needs an interrupt. I see plenty of delays that should be replaced with millis based timing.

Hello,
Sorry, that was a quick answer on my mobile phone. Here is what I hope is a more helpful answer.

You need to re-write your code to be multi tasking. Tutorials that should help are:
Using millis for timing
Demonstration for several things at the same time

Once you write your code that way you should find you don't need interrupts.

On Uno, Nano, ProMini, pins 7 and 13 are NOT PWM pins( analogWrite doesn't work like you expect).

Making your code interrupt driven, is not a simple drag and drop code operation. You usually need to restructure the program substantially. There are many hidden requirements and potential pitfalls. So it's not a good idea unless you really, truly, absolutely need it.

Interrupts are NOT an easy feature to implement at later stages of the code. It can be very unstable depending on the implementation, and implementing them as an “added feature” is a surefire way to making sub-optimal implementation.

For your code, I really don’t think you need interrupts. That code itself is “fine” and will work. If you need to do several different things, you can try using millis() for timing instead of delay, like mentioned by those above me.

Edit: Arduino project hub has a project tutorial for “multithreading”, here

...have into a interrupt function using volatile and ISR...

Sounds like a request from an instructor/teacher. Is it?

It does look like a exercise in direct port manipulation and interrupts. I guess you are expected to have the button press call that interrupt function (interrupt service routine) you talked about.
Look up the attachInterrupt() function. You will also see that pin 2 was a good choice for the button.
That collection of #include statements looks rather odd. You could probably comment out 3 of them without adverse effect.

Hi,
What model Arduino are you using?
What does your code do?
Why do you want to add interrupts?

Is this thread associated with this?

Thanks.. Tom.. :slight_smile:

OK, I'm "in" having answered your previous posting.

Why on earth would you imagine that an interrupt is relevant to this task? :roll_eyes:

Yes Tom the Codes are very similar but I backtracked on my previous code to work on implementing a LCD so now I'm working on using an interrupt in my code.

The interrupt is a required part of a project I'm working on. Though I know it is not needed and the code works fine my teacher would like us to have a interrupt in our code. Using a specific interrupt isn't required just need to use any form of interrupt.