back to loop() after interrupt

Hi there!

I am an arduino novice.
After browsing for a couple of hours and still not finding a way to jump back to the beginning of the loop() after an interrupt I would be very glad if someone could point me in the right direction.
My problem and code (very simplified but I hope it helps to see more easily where my problem is) follows:

Problem:

I have a motor doing a couple of things part1, part2 and part3, then it waits a bit and starts again.
Every now and then, there is an interrupt signal coming in.
When that happens, the motor successfully stops what it was doing and does motorDoesStuff() instead.
But when it has finished the void interrupt_signal, it continues finishing part1, part2 and part3 - depending on where it was interrupted.
But I want it to go back to the start of the loop and NOT finish what it was doing but start fresh with Part1 once it gets the signal.

Very, very appreciate any help!!

Simplified code:

#include <PinChangeInt.h>

/// setting lots of variables amongst which the interrupt pin

const int interruptPin = A0; ///to set the interrupt pin

//// setting a lot of FUNCTIONS for the motor do to certain things

int motorDoesSetupStuff(){
...
}

int motorDoesA_part1(){
...
}

int motorDoesA_part2(){
...
}

int motorDoesA_part3(){
...
}

int motorDoesStuff() {
...
}

///////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {

// start serial communication
Serial.begin(9600);

// many pins for a rotating stepper motor and a linear stage are being initialized []

/// interruptPin
pinMode(interruptPin, INPUT);
digitalWrite(interruptPin, LOW);
PCintPort::attachInterrupt(interruptPin, interrupt_signal, RISING);

motorDoesSetupStuff();

}

////////////////////////////////////////////////////////////////////////////////////////////////
void loop(){

motorDoesA_part1();
motorDoesA_part2(); /// the interrupt happens at some point while the motor does stuff
motorDoesA_part3();
}

//
void interrupt_signal() {
////

motorDoesStuff();

/// AND NOW I DON;t WANT THE MOTOR TO GO BACK TO WHAT IT WAS DOING WHEN IT WAS INTERRUPTED BUT TO START THE void loop() from the BEGINNING!!

//
}

After browsing for a couple of hours and still not finding a way to jump back to the beginning of the loop() after an interrupt I would be very glad if someone could point me in the right direction.

So, you are cooking dinner. The doorbell rings. After you answer to door, you want to resume watching TV.

The reason that you can't figure out how to return to the start of loop() after an interrupt is because that is not the way interrupts work.

Mmh. That does sound silly in a normal life situation but it kind of is what I want the motors to do.

Is there a better way than using interrupt if I want to stop the motor from doing what it is doing immediately when an input pin rises to HIGH and after that go back to the start of the loop()?

When an interrupt finishes it returns to the instruction immediately after the one that was executing when the interrupt happened.

if you want the code to do something else you need to set a flag variable (eg myInterrupt = true) in the interrupt and in your loop() code check if the flag variable has been set.

It is important to think of the interrupt code and the code in loop() running in parallel but without you being able to know at which point in loop() the interrupt will trigger.

...R

ChristinaB:
if I want to stop the motor from doing what it is doing immediately

"Immediately" for a motor is a very long time for a microcontroller.

If you consistently use blink-without-delay then polling for the motor-stop event will work perfectly. You will not need interrupts. Which will make the restart-loop problem trivial to solve.

ChristinaB:
Mmh. That does sound silly in a normal life situation but it kind of is what I want the motors to do.

Is there a better way than using interrupt if I want to stop the motor from doing what it is doing immediately when an input pin rises to HIGH and after that go back to the start of the loop()?

Like Robin suggested:

volatile bool gotInterrupt = false;

void setup() 

{
  attachInterrupt(1, myISR, RISING);

}

void loop() 
{
  gotInterrupt = false;
  if(!gotInterrupt) myFunction1();
  if(!gotInterrupt) myFunction1();
  if(!gotInterrupt) myFunction2();
}

void myISR()
{
  gotInterrupt = true;
}

I think what you really want is a State Machine, though

Many thanks for your replies!

@Robin2 and BulldogLowell
I can see how the flag variable would work but as far as I understood, it means I can only stop the motor in between the functions - whenever I check for the flag variable. But I want the motor do stop doing what it is doing while it is in the middle of performing what a function is telling him to do. Unless I break down what the motor is doing into mini-steps and check at the beginning of each mini-step it wouldnt do what I want, right?

@CodingBadly:
The BlinkWithouthDelay code is very elegant. However, I don't know when the motor will be interrupted. Could you tell me how exactly I would use this code to run a serious of functions AND be able to interrupt them at any point in time?

ChristinaB:
Could you tell me how exactly I would use this code to run a serious of functions AND be able to interrupt them at any point in time?

You don't. That's the point.

"At any point in time" for a motor is typically somewhere between thousands and millions of instructions to a microcontroller. The goal is to make one pass through loop fast enough that you can capture "at any point in time" for a motor. And it is generally an easy goal to reach. In my experience, that is how most motor control loops are structured.

The best path is to get a bit of code working then return to the forum for guidance. Repeat until finished.

What is the maximum motor RPM?

I agree with @Coding Badly.

Have a look at how the code is organized in Planning and Implementing a Program

With that sort of program structure it is easy to stop a motor within a few milliseconds or less.

...R

Hi guys!
First of all! Many many thanks for all the helpful replies - this is a really great forum!

I am using a flag now in the loop for the microsteps driving the motor and that works fine. Many thanks for that!

Also, I realised that if I wrote the code again, I would definitely do it differently - go for a state machine approach most likely or if possible use a blink-without-delay kind of approach!

So thanks for helping me out to fix this particular bug and help me make better programming choices next time!

I am interrested here too. I want to control boiler's air intake by servo. A blackbox, with few buttons, 2potentiometers, LCD and servo.

My idea is as follows, unfortunatelly it doesn't work as intended, so it seems, that I should in the code check for button pressed by digitalRead(pin); or in Interruptroutine set flag and check the flag, which seems to be the same. :-/ Is there a way, how to go to watch TV, after door ring, and not to return to kitchen?

void setup: shows values from potentiometer on LCD and reads calibration values from EEPROM.

void loop: if Startbuttonpressed==1, then {Startroutine();}
if Menubuttonpressed==1, then {Menuroutine();}

void Startroutine: Control air intake flap (opening/closing depending on boiler temperature)

void Menuroutine:
close air intake to not to overheat the boiler; //security feature
calibrate opening values for each temperature; //63°C=100%, 64°C=90% etc.

void InterruptbyStartbutton:{
Startbuttonpressed=1;
loop(); //(means forget where you were and start controling the flap)
}

void InterruptbyMenubutton:{
Menubuttonpressed=1;
loop(); //(means forget where you were and enter calibration menu)
}

Never ever call loop() from an interrupt service routine. Even better, never ever call loop(), period

Please post your real code.

My real code is almost done, by polling buttons. But theoretically: is it possible to run void someting(); after interrupt, which occured for example in void loop() ?

I know that should be set flag and that flag tested... ...but for me looks like a waste of code.

If you call a function from an interrupt that can also be called from loop() what happens if the interrupt occurs while the Arduino is already in the middle of that function? Most probably everything will be screwed up. Think of two people trying to eat the same slice of toast.

...R

pedrokv:
My real code is almost done, by polling buttons. But theoretically: is it possible to run void someting(); after interrupt, which occured for example in void loop() ?

I know that should be set flag and that flag tested... ...but for me looks like a waste of code.

You can theoretically go anywhere in your code after the ISR finishes by modifying the stack from inside the ISR.

You will end up wasting more code on getting it absolutely right than the usual approach with a volatile variable.

"Waste of code" is not important. Code is cheap. You could probably store all the code ever posted on this forum for its entire existence on a single SD card. Millions of different sketches.

What is expensive is the programmer's time. If you can make something easily understood to the next programmer to look at the code then you should do so. Note that the next programmer is usually yourself, but a few weeks or months later so that you've totally forgotten what the heck the interrupt is doing to massacre the stack.