Using external interrupt for controlling push button (as abort function)

Hello,
I'm trying something simple (in my eyes), but did not get the expected result. My sketch is much longer, but I have separated needed code, for this problem.

My equipment:
Arduino MEGA 2560
Breadboard with some LEDs and Res'

My goal:
push button shortly: start procedure in the loop (here e.g. light up LED_Start).
push button longer than 2sec: --> interrupt, (var_stopp) --> stop procedure at a specific position of code and light up LED_Interrupt

My problem:
The LED_Interrupt lights up same time (more or less) as LED_Start. It seems if interrupt was set once, program does not care I'm checking the actual state of push button (see void STOPP () function).

Why?

I have tried to work with noInterrupts() and interrupts() --> . No effect at all. (see "Debug" lines)

Thanks for help in advance!

Here the sketch:

#include <SPI.h>  // Arduino SPI library
#include <Wire.h>  // Arduino I2C library
#include <SD.h>
#include "TimerOne.h"
#include <FlexiTimer2.h>

volatile int StartButton = 28; // PIN28 of Arduino MEGA
int LED_Start = 38;
int LED_Interrupt = 39;

int button = LOW;
int var_stopp = 0;
unsigned long timerStart;

void setup() {
  
  pinMode (StartButton, INPUT);
  pinMode (LED_Interrupt, OUTPUT);
  pinMode (LED_Start, OUTPUT);
  attachInterrupt(0, STOPP, HIGH);  // external interrupt 0 (PIN2 of Arduino MEGA)
  }  // end void setup


void loop() {
  
  if (button == LOW){        
    // do something
    while(button == LOW) {
        button = digitalRead(StartButton);
        timerStart = millis();
      }
    digitalWrite(LED_Start, HIGH);  // LED HIGH if push button was pressed
    }
 
// interrupts();  // Debug !

  if ((millis()-timerStart) > 1200000 || var_stopp==1) {    // Stopp loop after 2min or if push button was pressed for longer then 2 sec
    digitalWrite(LED_Interrupt, HIGH);
    button = LOW;
    var_stopp = 0;
    //do something
    }
  }  // end void loop

// -------------------------

void STOPP() {
  delay(1000);      // after Interrupt wait 1sekc to be sure, push button will be pushed longer than for usual start procedure
  if (digitalRead(StartButton) == HIGH) {
    delay(1000);    // again be sure push button will be pushed for longer then 2sec
    if (digitalRead(StartButton) == HIGH) {
      var_stopp = 1;    // now set variable var_stopp to 1 (as marker)  
      }
    }
  }

One immediately obvious problem is that delay() does not work in an ISR because it uses interrupts which are automatically disabled when the ISR is triggered. Also all variables changed within an ISR should be declared as volatile.

ISRs should have as little code in as possible and should return as soon as possible. A common way to achieve this is to set a flag variable inside the ISR and return to the calling program. Then use the value of the flag variable within loop() to take the necessary actions.

volatile int StartButton = 28; // PIN28 of Arduino MEGA

The volatile keyword is needed for variables that are used in non-ISR code and set in ISR code. Your pin number is hardly likely to change. It should be declared const, not volatile.

var_stopp is used in loop() and in STOPP(). It is not declared volatile. It should be.

As UKHeliBob points out, delay() in an ISR is not allowed. The fact that you are trying to use it means that you haven't a clue about interrupts. I'd suggest that you stop before you hurt someone.

If you want a short press to start something and a long press to stop it there doesn't seem to be any need to use interrupts. Interrupts are for things that need to be dealt with immediately - and by definition a long press is not immediate.

Just poll the switch button - much simpler.

...R

Since you were not born with the ability, it may a good occasion to learn about interrupts, however dangerous they may be. (Lon Chaney lurking in the shadows).

But, if all you want to do is make your Arduino count the time your button is pressed and behave in a certain manner when that happens, you may reserve the horrors for another time. ]:smiley:

look at something like this to do what you want...

boolean timerExpired;
unsigned long startTime;
int buttonPin = 4;// is this 28 right now on your MEGA?
int lastButtonState;
boolean myFlag;

void setup(void) 
{
  Serial.begin(9600);
  pinMode(buttonPin, INPUT);
  pinMode(13,OUTPUT);
}

void loop(void) 
{
  int buttonState = digitalRead(buttonPin);
  if (buttonState == HIGH)
  {
    if (lastButtonState == LOW)
    {
      Serial.print(F("Button Pressed!!!"));
      startTime = millis();
    }
    else
    {
       if (millis() - startTime >= 2000UL)
       {
         myFlag = true;
       }
    }
  }
  lastButtonState = buttonState;
  //
  if (myFlag)
  {
    //place your stuff to to here like kiting the on-board LED
    digitalWrite(13,HIGH);
    delay(2000);
    digitalWrite(13,LOW);
    myFlag == false;
  }
}