Start/Stop Button Interrupt

Hey, I'm currently working on a mini project. Essentially with this code, when the run/stop button is pressed it will ramp up/down a motor to a to a set speed/off. I am struggling with the intterupt for this. Also I have an emergency stop button which seems to work but I am trying to cut out the debouncing of the button, what would be the best way of going about that?

#define DEBUG_MODE
#define MOTOR_DRIVE 11 // Motor output PWM on Pin 11
#define E_STOP 2 // Emergency Stop on Pin 2
#define RUN_STOP 3 // Start/Stop on Pin 3
#define PMAX 255 // MAX Power 100%
#define RAMP_DELAY int(10000/PMAX) // Ten Second Ramp Time

int state = 0;
volatile int stop = 0;

void setup() {
#ifdef DEBUG_MODE
  Serial.begin(9600);
  Serial.println("Setup initiated");
#endif
  pinMode(MOTOR_DRIVE, OUTPUT);
  pinMode(E_STOP, INPUT_PULLUP);
  pinMode(RUN_STOP, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(E_STOP), emerStop, FALLING);
  attachInterrupt(digitalPinToInterrupt(RUN_STOP), runStop, FALLING);
#ifdef DEBUG_MODE
  Serial.println("Setup complete");
#endif
}

void loop() {
  if (digitalRead(RUN_STOP) == 0) {
#ifdef DEBUG_MODE
    Serial.println("Run/Stop button pressed");
#endif
    for (int i = 0; (i <= PMAX-1) && (i >= 1) ; i+=state)
    {
      if (stop)
      {
#ifdef DEBUG_MODE
        Serial.println("Emergency stop interrupt - shutting off motor");
#endif
        digitalWrite(MOTOR_DRIVE, 0);
        state = 0;
        break;
      }
      if (state == 1)
      {
        analogWrite(MOTOR_DRIVE, i);
      }
      else
      {
        analogWrite(MOTOR_DRIVE, PMAX - i);
      }
      delay(RAMP_DELAY);
    }
#ifdef DEBUG_MODE
    Serial.println("Ramp up/down finished");
#endif
  }
}

void runStop()
{
  if (state == 1)
  {
    state = -1;
  }
  else
  {
    state = 1;
  }
}

void emerStop()
{
#ifdef DEBUG_MODE
  Serial.println("Debouncing test");
#endif

  stop = 1;
}

A typical approach and the basis of some debouncing algorithms is to

 note the time of the contact closure that you did reacted to 

and then

 ignore any contact closures that come too soon thereafter.

You are using interrupts, ok, so right there see if

  it’s too soon to react and do nothing

or

 if it has been awhile, react and note the time for next time.

Use millis() to determine and save the time, and millis - that time to see if it’s been long enough.

how long, up to you. 25 milliseconds covers most switches, 50 def woukd or get new switches.
a7

1 Like

Hello magix_jazr
Why do you use an ISR?
There is enougth time to scan the buttons avaiable.
Have a nice day and enjoy coding in C++.

1 Like

Agree. The same idea I outlined can be deployed w/o using interrupts, and since the interrupt itself isn’t cutting power to the bomb, or whatever, reaction can be just as rapid.

a7

1 Like

Hi @paulpaulson I have an ISR as my lecturer in college requested for me to use it in my project

For the "debounce", consider something like:

void runStop()
{
    //static so it lingers even when ISR finishes
    static uint32_t lastInt = 0ul;

    //get millis count now
    uint32_t tNow = millis();

    //if less than 20mS since last handled interrupt, just leave (i.e. ignore bouncing)
    if( (tNow - lastInt) <= 20ul )
        return;

    //your logic is unchanged 
    if (state == 1)
    {
        state = -1;
    }
    else
    {
        state = 1;
    }

    //save the time of this handled interrupt for next debounce check
    lastInt = tNow;

}//runStop
1 Like

Haha, took me awhile to parse that.

Some might suggest that s/he is going about stuffing your brain with items of knowledge in a suboptimal order.

A very high percentage of projects can be done without interrupts. I think they are best learned in the context of being essential to achieving success, and only used when they are. Indispensable.

But never mind, we go with the requirements of your assignment.

a7

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.