Interrupt code not working as supposed to.....

Hello,
I got this stepper motor running code and it works fine. However I am trying to write a code to enable me to pause it and turn on led on pin 13, when I press a button and then have it continue running where it left off when I release the button.
I tried by attaching an interrupt but it didn’t work. The modifications I made are in bold. Anyone know what I did wrong?
I’m using an Arduino mega 2560.
Here is the code below. Any help will be appreciated.

//////////////////////////////////////////////////////////////////
//©2011 bildr
//Released under the MIT License - Please reuse change and share
//Using the easy stepper with your arduino
//use rotate and/or rotateDeg to controll stepper motor
//speed is any number from .01 → 1 with 1 being fastest -
//Slower Speed == Stronger movement
/////////////////////////////////////////////////////////////////
#include <avr/interrupt.h>
# define LED_PIN 13

define SWITCH_PIN 5 // pin 18 for interrupt on Arduino mega 2560[/b]

#define DIR_PIN 2
#define STEP_PIN 3

void setup() {
pinMode(DIR_PIN, OUTPUT);
pinMode(STEP_PIN, OUTPUT);
pinMode(LED_PIN, OUTPUT);
** // switch input**
** pinMode(18, INPUT);**
** // attach the interrupt on pin 18**
** attachInterrupt(SWITCH_PIN, light, LOW);**
}
void light() {
** digitalWrite(LED_PIN, HIGH);**
}

void loop(){

//rotate a specific number of degrees
rotateDeg(360, 1);
delay(1000);

rotateDeg(-360, .1); //reverse
delay(1000);

//rotate a specific number of microsteps (8 microsteps per step)
//a 200 step stepper would take 1600 micro steps for one full revolution
rotate(1600, .5);
delay(1000);

rotate(-1600, .25); //reverse
delay(1000);
}

void rotate(int steps, float speed){
//rotate a specific number of microsteps (8 microsteps per step) - (negitive for reverse movement)
//speed is any number from .01 → 1 with 1 being fastest - Slower is stronger
int dir = (steps > 0)? HIGH:LOW;
steps = abs(steps);

digitalWrite(DIR_PIN,dir);

float usDelay = (1/speed) * 70;

for(int i=0; i < steps; i++){
digitalWrite(STEP_PIN, HIGH);
delayMicroseconds(usDelay);

digitalWrite(STEP_PIN, LOW);
delayMicroseconds(usDelay);
}
}

void rotateDeg(float deg, float speed){
//rotate a specific number of degrees (negitive for reverse movement)
//speed is any number from .01 → 1 with 1 being fastest - Slower is stronger
int dir = (deg > 0)? HIGH:LOW;
digitalWrite(DIR_PIN,dir);

int steps = abs(deg)*(1/0.225);
float usDelay = (1/speed) * 70;

for(int i=0; i < steps; i++){
digitalWrite(STEP_PIN, HIGH);
delayMicroseconds(usDelay);

digitalWrite(STEP_PIN, LOW);
delayMicroseconds(usDelay);
}
}

columbus1231: I tried by attaching an interrupt

...

Anyone know what I did wrong?

Trying to use interrupts for this was your main mistake. It's not a problem that calls for interrupts. f you adopt a non-blocking approach to your motor control code then you can handle button presses and serial I/O and so on at the same time as moving the stepper, and use these to control the stepper movement. A much cruder approach, but one that you could implement without refactoring your sketch, would be to poll the button input in your stepper control loops and block the loop when the button is held down. This is a very limited approach though and makes it difficult to add in any additional logic. The non-blocking approach would be far better.

PeterH:
Trying to use interrupts for this was your main mistake. It’s not a problem that calls for interrupts.

Even if interrupts are needed, do you need to #include <avr/interrupt.h> when using interrupts? It seems to compile without doing that include.

My sarcastic - and thus less than helpful - comment to the original subject heading is "They rarely do " and then add i a low voice "and the 'supposition' is all wrong, too". ]:)

The only valid reason I have seen in this forum for using interrupts is catching encoder pulses or generating PWM/Stepper pulses when above 50Khz. Button pushes do NOT qualify :stuck_out_tongue_closed_eyes:

@Columbus1231: Why are some lines in your code example bold and some not? ANd why is the code not in a nice box......like this?

...but if you INSIST on using an interrupt, please notice that attachInterrupt(...) takes an interrupt number and NOT a pin number (except on the Arduino Due).

Also, you did not tell us how your switch is wired.

Interrupts can be very useful but are not trivial. Good Luck!

Ignore all the bafflegab about not using interrupts. The fact is that the logic for using interrupts is not that much different than reading the state of the pin in the loop() function and if you get the logic wrong it ain't gonna work for either of them. In fact it can be easier using an interrupt because you don't need any logic to figure out whether the button state has changed and, if so, whether it has been pushed or released. But, first you need to sort out which pin you are really using:

# define SWITCH_PIN 5      // pin 18 for interrupt on Arduino mega 2560
.
.
.
  pinMode(18, INPUT);
  // attach the interrupt on pin 18
  attachInterrupt(SWITCH_PIN, light, LOW);

Which is it, Pin 18 or Pin 5? You don't want an interrupt on LOW. You only need to handle the button when it is pushed (FALLING) and when it is released (RISING). Sometimes you are only interested in the FALLING event when the button has been pushed. If you need to handle both events, you can use CHANGE which causes an interrupt when the button is pushed and when it is released. In the interrupt routine just read the pin to see what its value is now. If it is LOW, then the button was just pushed; if it is HIGH then it has just been released.

Pete

el_supremo: Ignore all the bafflegab about not using interrupts.

It's not bafflegab (new word to me).

I have a simple view of this. Interrupts are perfectly sensible if you know how to use and debug them without needing advice from the Forum.

If you haven't yet mastered them it is best to avoid them altogether.

The only exception is if you are working on a demo sketch just to learn about interrupts.

...R

Interrupts are perfectly sensible if you know how to use and debug them without needing advice from the Forum.

Try replacing “Interrupts” in that statement with “for loops” or “switch statements” - doesn’t make sense does it?
Interrupts are a useful feature of the processor and there’s absolutely no reason to avoid them. If you find them hard to use by all means avoid them, but don’t tell everybody else they have to avoid them just because you find them difficult.

Pete

el_supremo wrote:

"Which is it, Pin 18 or Pin 5?"

which still misses the point that attachinterrupt(..) takes an interrupt number, NOT a pin number. The pin had better be the appropriate one for that interrupt on that processor, but attachinterrupt itself doesn't care about that.

Good Luck!

Actually the code the OP has is (almost) correct. On the Mega 2560, interrupt 5 is on Pin 18. The problem is using the name SWITCH_PIN for what is actually the interrupt number. It would be better to use a less confusing name.

Pete

el_supremo: Ignore all the bafflegab about not using interrupts. The fact is that the logic for using interrupts is not that much different than

...

Designing reentrant and multithreaded code is substantially different to designing code that only runs in a single context. Using interrupts introduces some significant issues and should IMO be done only when necessary, and then reluctantly and to the minimum extent possible. Encouraging novice programmers to use interrupts when they aren't needed is IMO bad advice. They certainly aren't needed here and so should be avoided. To compare the complexity of interrupt handling with basic control structures such as for loops and switch/case statements is completely spurious.

Designing reentrant and multithreaded code

Utterly spurious. We're talking about a Mega 2560 with a stepper motor and a button, not a flight control computer.

To compare the complexity of interrupt handling with basic control structures such as for loops and switch/case statements is completely spurious.

Bull. Interrupt handling isn't "complex". That's like telling someone not to take calculus because "it's hard". If you can't do it, don't. But don't assume that "novice programmers" are incapable of grasping it.

Pete

But don't assume that "novice programmers" are incapable of grasping it.

If the "novice programmer" is capable, he/she wouldn't be here, would he/she?

el_supremo: Bull. Interrupt handling isn't "complex". That's like telling someone not to take calculus because "it's hard".

Of course is it complex. Any time you have an interrupt handler interacting with code outside the interrupt context you have to deal with atomicity of access to shared data, whether any shared code is reentrant, and possible race conditions and unforeseen sequences of events between the two. Designing code to run in multiple execution contexts is inherently [u]much[/u] harder than writing code that runs in a single context.

I'm not saying don't take calculus because it's hard. I'm saying don't use calculus to work out your cab fare, because it's hard and not necessary to solve the problem at hand.

You are dragging in complexities which either don't exist on a Mega (after all, it only has one level of interrupt), or are easy to avoid, such as using a character variable as a flag to signal to the loop() function, which avoids "atomicity". Nothing about interrupts on a Mega is so hard that they shouldn't be used.

If the "novice programmer" is capable, he/she wouldn't be here, would he/she?

Are you saying that the only people who ever post here are novice programmers? I'm saying "capable" in the sense of "capable of learning', not "capable" in the sense of "accomplished/experienced"

Pete

el_supremo:
You are dragging in complexities which either don’t exist on a Mega (after all, it only has one level of interrupt), or are easy to avoid, such as using a character variable as a flag to signal to the loop() function, which avoids “atomicity”. Nothing about interrupts on a Mega is so hard that they shouldn’t be used.

So now interrupts are only easy so long as the only data they share with the main context is just a single byte? Any other restrictions you’re going to assume that your novice coders will stick to about when they use interrupts?

The complexities I ‘dragged in’ exist in any Arduino, whether you recognise them or not. Even experienced developers fall foul of them from time to time, in fact only recently I was reading about a bug in the Arduino runtime caused by an unrecognised race condition between accessing registers in main and interrupt contexts. Sure it’s possible to use interrupts correctly. But using interrupts introduces issues that simply don’t exist in code that only executes in a single context, and these issues make the code inherently more complex to understand. There is no reason to incur that extra complexity unless you have a compelling reason to use interrupts. In the case this thread is about, where the OP wants to read button states and modify the behaviour of code in the main loop accordingly, interrupts do nothing whatsoever to help solve the problem and there is no reason to use them.

PeterH: Sure it's possible to use interrupts correctly. But using interrupts introduces issues that simply don't exist in code that only executes in a single context, and these issues make the code inherently more complex to understand.

+10

It is entirely possible that el_supremo is very significantly better at coding than most other people (and I'm saying this seriously). There are such people, just as there are gold medal Olympic athletes. If so, it is no service to others to pretend that difference doesn't exist by assuming everyone can function at the gold medal standard.

...R

It is entirely possible that el_supremo is very significantly better at coding than most other people (and I'm saying this seriously). There are such people, just as there are gold medal Olympic athletes. If so, it is no service to others to pretend that difference doesn't exist by assuming everyone can function at the gold medal standard.

You can't imagine how much I do agree with you.

(By the way: he IS; he is "el_supremo") ;)