Going to the Start of the Loop after an Interrupt

Hi everyone, I was wondering if it would be possible to go back to the start of the loop after an interrupt is over rather than going back to where we left off when the interrupt was called. I have done a lot of research on google and I cannot find an answer for this.

Code for my interrupt:

//alternate method
void laserFire()
{
    digitalWrite(andG,LOW); //stop flashlamps
    delayMicroseconds(100000); //delay 100ms
    //makes flash lamps and laser trigger at same time
    PORTD |= B01100000;    
    digitalWrite(Q, HIGH); //start flashlamps at 10 Hz again
    //digitalWrite(andG, HIGH);  //fire flashlamps when pin2 is brought low
    //digitalWrite(trig, HIGH);    // fire laser when pin2 is brought low
}

Essentially, when I get an input from HIGH to LOW (FALLING mode) for my interrupt, I want to change many of my outputs to HIGH. However, if after my interrupt is over, it goes back to where it left off in the code, I could possibly be changing an output back to LOW which I don't want. For instance, I change the output Q to high in my interrupt. However, if I go back to where I left off, I could possibly be changing the output Q back to low in my loop code. This is why I would like to start back at the loop after the interrupt is over because I have if conditions that make sure I wouldn't be changing Q back to LOW unless the conditions are met.

Code for an example in my loop code (S/R Latch):

  if(Sstate==1 && Rstate==1){
    //digitalWrite(led, LOW);
    digitalWrite(Q, LOW);
  }
  else{
    if(Sstate==1){
      
      
      //digitalWrite(led, HIGH);
      
      digitalWrite(Q, HIGH);
    }
    if(Rstate==1){
      //digitalWrite(led, LOW);
      digitalWrite(Q, LOW);
    }
  }

Any help would be appreciated. Please ask for more details if you need any.

Only by setting a flag in the interrupt routine and checking for that flag at relevant places in loop, at which point you can "return" from the loop function to restart it.

void software_Reset() 
{
asm volatile ("  jmp 0"); 
 }

This starts the sketch from the begining. You should be able to achieve what you want.
Also check EEPROM.

Thank you for your responses guys!

To majenko:

I have always wondered about this alternative. Does this mean that after an interrupt is over, you return to an if condition within the loop function? If you don't return to an if condition, I will still be seeing the same problem because if for instance, the interrupt was called right before digitalWrite(Q, LOW), then after the interrupt is over, I would return to that spot in the loop and run digitalWrite(Q, LOW) which I don't want. Then I would be checking the flag after that but by then, it's too late. Am I misinterpreting this?

To Vinter:

That does sound like what I want. Where exactly would I put that code? Would I call that function within the interrupt?

Wrap the sensitive bits in a "critical block" - i.e., disable interrupts before, and enable them afterwards, and surround them by a check for the flag.

Oh wow, I understand that a lot more clearly now. I believe that fixes my original problem, but I believe it brings up another problem. I'm using the FALLING mode for the interrupt so once the input for the interrupt goes to LOW state, it goes back to a HIGH state (basically a pushbutton). Couldn't this possibly become a timing issue? If the code runs much faster than checking for an interrupt, I could see how this would fix my problem. However, if I call the interrupt when it's disabled, I run the sensitive bits, and then enable the interrupt, isn't it possible that the interrupt signal will be gone because when I call the interrupt, it will give a LOW state and then quickly go back to a HIGH state because it's a pushbutton. Thus, if I check the interrupt now, isn't it possible that the input is now a HIGH state (which would mean the interrupt doesn't happen)? I guess I'm really wondering about the timing of this.

The interrupt is buffered (i.e., delayed) until they are enabled again.

Oh okay, thank you so much! That should be able to solve my problem then. I really couldn't find the solution to this for so long.

altan92:
Hi everyone, I was wondering if it would be possible to go back to the start of the loop after an interrupt is over rather than going back to where we left off when the interrupt was called.

Almost anything is possible if you're determined enough, but if you want the main code to resume somewhere other than where it was when the interrupt handler was called, then you're probably solving your problem the wrong way.

If you want the interrupt handler to inhibit the main code from taking some action then set a (volatile) flag in the interrupt handler and test the state of that flag in the main code before taking the action, nothing clever needed.

You'll probably run into issues using delays and digitalWrite's in your ISR. Last I checked digitalWrites don't even work in the ISR?

. Last I checked digitalWrites don't even work in the ISR?

That sound serious.
Have you any evidence?

Vinter:

void software_Reset() 

{
asm volatile ("  jmp 0");
 }




This starts the sketch from the begining. You should be able to achieve what you want. 
Also check EEPROM.

What has EEPROM got to do with it? Also your suggestion does not go back to loop, it goes back to setup and then loop. Restarting from the start is a rather brute force way of handling an interupt.

altan92:
... if for instance, the interrupt was called right before digitalWrite(Q, LOW), then after the interrupt is over, I would return to that spot in the loop and run digitalWrite(Q, LOW) which I don't want.

Why not? The interrupt might easily have happened just after you set it LOW, so I don't see how it can matter that much.

Code for my interrupt:

//alternate method

void laserFire()
{
    digitalWrite(andG,LOW); //stop flashlamps
    delayMicroseconds(100000); //delay 100ms

It is undesirable to introduce 0.1 second delays into an interrupt routine. They are supposed to be fast. That will throw out millis() calculations as you have now stopped Timer 0 interrupts.

Didn't say it restarts loop. From what I remember this restarts the program completely. I think it redeclares the variables which is why I proposed to use EEPROM to know where to go to in the sketch. I'll have to check again later.

To PeterH:

Yes, thank you. There were some issues that would arise from that in my project which I addressed before, but majenko answered them for me. Also, I mainly want to use interrupts because it instantly knows when an input has changed and I want to happen something immediately after that input has changed states.

To Things:

Yeah, delay() doesn't work in an ISR, but digitalWrite() does. I have tried it out with some circuitry.

To Nick Gammon:

Yes, I understand that but the thing is after the interrupt, I want Q to remain in the HIGH state and only change states after checking conditions from inputs. In the case you're talking about, I wouldn't mind that because then after the interrupt, Q remains in the HIGH state. However, if the interrupt happened before I set it LOW, then although it would be HIGH from the interrupt function, it would change back to LOW without checking any inputs which I don't want to happen.

Oh, thank you for pointing that out to me. I mainly did that because I was told I needed to delay 0.1 s after I set Q to LOW. Also, I thought that delayMicroseconds() worked in an interrupt, but delay() did not. However, I do not want to throw out millis() calculations because I do use it in the main code. Is there any suggestion you could give me to somehow do a delay for 0.1 s. Also, thanks for the link. I'll definitely check that out.

The advice we usually give. Set a flag in the interrupt routine. Test the flag in the main loop. If you are delaying for 0.1 seconds an extra microsecond or two won't make much difference.

Unusually nobody has asked for the whole program to be posted, nor have they questioned the need for an interrupt to be used in the first place. It may well be that there is a simpler solution than the interrupt driven one being discussed, but without the full code it is impossible to say.

It is tempting to use an interrupt, after all, its name indicates that it interrupts what the program is doing, but the point in the program that it happens is, by its very nature, uncontrolled. The same result can often be achieved by reading an input in the loop() function which, if the code is written properly, repeats fast enough to give the effect of responding to an input immediately.

There may be exceptions to this, such as the need to read a sensor with a slow response time in loop() which will also slow down the reaction to user input, but in general the technique works well. Reading an input in loop() is, in many ways, the same as setting a flag in an ISR and responding to it in loop() but it does mean that you have control over when it happens.

I wonder if an interrupt is actually needed in this case.

... nobody has asked for the whole program to be posted ...

Good point. I must have been sleepy. :slight_smile:

And indeed this is usually the "trigger" question: "How do I make an interrupt jump to the start of the loop?"

The answer really should be: "why do you want to?"