Go Down

Topic: goto statement in ISR? (Read 2 times) previous topic - next topic

Nick Gammon

What does this "long" function do? Can you post it? Is it long in physical lines of code, or long in that it does something that takes a long time?
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

z_e_u_s

yes it takes long time
i want to explain my code but i'm working autonomous robot, when collosion detect, robot stop motors 100ms then goback very short distance and turnleft ===> this is my long function
robot use switch sensor to detect collisons, some of my tests show that sometimes more than one crash happen in long function ends, i used interrupt, but this time i'm get stuck in ISR,
i want to when switch interrupts, start long function again.

PaulS

Quote
i want to when switch interrupts, start long function again.

What long function? I think it is time you told us about this long function.

It is also likely that you need to re-write this long function so that it doesn't take so long.

Udo Klein

Then you would need to rewind the stack and ensure that all non atomic variable accesses are either cleaned up or do not cause any strange side effects. Rewinding the stack is never achieved with goto.
Check out my experiments http://blog.blinkenlight.net

z_e_u_s

Code: [Select]
 
void ISR() {
  goStop();
  delay(100);
  goBackward();   
  delay(100);
  goStop();
  delay(100);
  goLeft();
  delay(100);
  goStop();
  delay(100);
  digitalWrite(redledPin,HIGH);
  delay(100);
}

this my ISR code...

PaulS

Quote
this my ISR code...

Of course, you are aware that delay() doesn't work in an interrupt handler.

Senso

You NEVER use delays inside an ISR.
An ISR must be short and clean!
And delay relies on interrupts and when you are inside and ISR all the other interrupts are disabled so delay, and milis doesn't works.
If you want to do that, just set a flag in your ISR and then read that flag in the main and do what you want.

Nick Gammon

#22
Aug 14, 2011, 11:07 pm Last Edit: Aug 14, 2011, 11:12 pm by Nick Gammon Reason: 1

this my ISR code...


Words elude me a little bit, but I suppose I see what you are doing...

When the button is pressed you want to do all that stuff, and if it is pressed again, do it again from the start?

Time for a restructure:

Code: [Select]

volatile boolean pressed;

void ISR ()
{
pressed = true;
}  // end of ISR


void loop ()
 {
 if (pressed)
   move_the_robot ();
 }  // end of loop

void move_the_robot ()
 {
 pressed = false;

 goStop();

 if (pressed)
   return;
 else
   delay(100);

 goBackward();    

 if (pressed)
   return;
 else
   delay(100);

 goStop();

 if (pressed)
   return;
 else
   delay(100);

 goLeft();

 if (pressed)
   return;
 else
   delay(100);

 goStop();

 if (pressed)
   return;
 else
   delay(100);

 digitalWrite(redledPin,HIGH);

 if (pressed)
   return;
 else
   delay(100);

 }  // end of move_the_robot

Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

AWOL

@OP:
I think you have the concept of interrupts a bit confused.
Interrupts are signals to the processor that something has happened, and if you don't do something about it pretty soon, bad things will occur.
Such an event might signal the arrival of a character in the UART receive buffer, and if you don't read it within the next few hundred microseconds, it will be overwritten by the next character.
It would be inconvenient to litter your code with tests for "serial-in available", so an interrupt can divert the processor after every single machine instruction (not line of C code) to go off and handle that event.

As far as just about anything mechanical is concerned, this is not operating on the same sort of timescales as the processor.
A "bump" event is quite different to the actions that must occur to respond to the event, and you must handle them separately.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

primate

I think the problem lies in the architecture of the long function, and the fact that a long-running, linear function is at odds with the asynchronously-resettable requirement of the external stimuus (i.e an interrupt in this case).

I would break down the long function into smaller, faster states and build a resettable state machine that can always start from the initial state. Something like this:

Code: [Select]

int state = 0;

void ISR()
{
  state = 0;
}

void loop()
{
  switch (state)
  {
    case 0:
      calcuateThis();
      state = 1;
      break;
    case 1:
      calcuateThat();
      state = 2;
    case 2:
      computeResults();
      state = 0;
      break;
  }
}


You get the idea. Of course, it makes the system harder to build and debug, and the system must survive the state reset in any previous state, but it sure beats trying to unwind the program stack and stuff.

Just my 2 cents' worth from a backseat programmer.   :-)

Nick Gammon

I agree with primate that a state machine would be even neater. I was trying to show the original code revamped a bit. But something like this would be nicer:

Code: [Select]
volatile boolean pressed;
int state = 0;

void isr ()
{
pressed = true;
}  // end of isr

void loop ()
  {

  // when button pressed start doing things
  if (pressed)
    {
    pressed = false;
    state = 1;
    }
   
  switch (state)
    {
    case 0:   return;  // no action on state 0
    case 1:   goStop(); break;
    case 2:   goBackward(); break;
    case 3:   goStop(); break;
    case 4:   goLeft(); break;
    case 5:   goStop(); break;
    case 6:   digitalWrite(redledPin,HIGH); break;
    default:  state = 0; return;
    }  // end of switch
 
  // onto next state
  state++;
  delay(100);

  }  // end of loop
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

z_e_u_s

Thanks everyone it works...

Go Up