End Switch with attachInterrupt and Edge Detection

Hey Everyone!

I got an endstop switch on amazon:

and I am using it as an interrupt for my motors as well as setting home, which is working great but each time I click the switch it stops the command 3 times, once from when I press it, and twice from when I let go. The goal is to have the interrupt work only when the switch is pressed, and completely ignore being held down or released. Any ideas how I might make this work?

#include <AccelStepper.h>
#include <MultiStepper.h>

AccelStepper stepper1(1,8,9); // stepper1, Pulse Pin 8, Direction Pin 9

bool newData, runallowed = false;
char receivedCommand;
long CoordinateX = 0;
long CoordinateY = 0;
const byte endSwitchPin = 2; //pin for the end stop switch

void setup() 
{
 pinMode(endSwitchPin, INPUT_PULLUP); //internal pullup resistor
 attachInterrupt(digitalPinToInterrupt(endSwitchPin), stopMotor, FALLING); //When the endSwitchPin sees ground, it will interrup the progam with stopMotor()
  
 Serial.begin(9600); //baud rate for serial monitor
 Serial.println("Motor Position Testing"); //print this message on open
 Serial.println("Positions available: 1-9"); // ^

 stepper1.setMaxSpeed(1600); //Max speed steps/second
 stepper1.setAcceleration(800); //Acceleration steps/second/second
 stepper1.disableOutputs(); //Keeps outputs disabled when not in use
}

void loop() 
{
  checkSerial(); //check for recieved commands on the serial monitor
  runMotor(); //enables or disables motor outputs
  
}

void runMotor() //enables or disable motor outputs
{
    if (runallowed == true)
    {
      stepper1.enableOutputs(); //enable output pins if run is allowed
      stepper1.run();
    }
    else
    {
      stepper1.disableOutputs(); //disable output pins if run is not allowed
      
      return;
    }
}


void checkSerial() //check for recieved commands on the serial 
{  
    if (Serial.available() > 0) //if something comes from the computer
    {
        receivedCommand = Serial.read(); // pass the value to the receivedCommand variable
        newData = true; //indicate that there is a new data by setting this bool to true
 
        if (newData == true) //we only enter this long switch-case statement if there is a new command from the computer
        {
            switch (receivedCommand) //we check what is the command
            {

              case '1': //Position 1 for the motors

                Serial.println("Moving to Position 1"); //print text before moving
                CoordinateX = 1000;
                CoordinateY = 1000;
                MovePosition(); //run the command for moving to a position
                break;

             case '2': //Position 2 for the motors

                Serial.println("Moving to Position 2"); //print text before moving
                CoordinateX = 2000;
                CoordinateY = 1000;
                MovePosition(); //run the command for moving to a position
                break;

            case '3': //Position 3 for the motors

                Serial.println("Moving to Position 3"); //print text before moving
                CoordinateX = 3000;
                CoordinateY = 1000;
                MovePosition(); //run the command for moving to a position
                break;

            case '4': //Position 4 for the motors

                Serial.println("Moving to Position 4"); //print text before moving
                CoordinateX = 1000;
                CoordinateY = 2000;
                MovePosition(); //run the command for moving to a position
                break;

            case '5': //Position 5 for the motors

                Serial.println("Moving to Position 5"); //print text before moving
                CoordinateX = 2000;
                CoordinateY = 2000;
                MovePosition(); //run the command for moving to a position
                break;

            case '6': //Position 6 for the motors

                Serial.println("Moving to Position 6"); //print text before moving
                CoordinateX = 3000;
                CoordinateY = 2000;
                MovePosition(); //run the command for moving to a position
                break; 

            case '7': //Position 7 for the motors

                Serial.println("Moving to Position 7"); //print text before moving
                CoordinateX = 1000;
                CoordinateY = 3000;
                MovePosition(); //run the command for moving to a position
                break;  

            case '8': //Position 8 for the motors

                Serial.println("Moving to Position 8"); //print text before moving
                CoordinateX = 2000;
                CoordinateY = 3000;
                MovePosition(); //run the command for moving to a position
                break;   

            case '9': //Position 9 for the motors

                Serial.println("Moving to Position 9"); //print text before moving
                CoordinateX = 3000;
                CoordinateY = 3000;
                MovePosition(); //run the command for moving to a position
                break;                                                          
                
            case '0': //Position Home for the motors

               Serial.println("Moving to Home"); //print text before moving
               CoordinateX = 0;
               CoordinateY = 0;
               MovePosition(); //run the command for moving to a position
               break;

            default:

               break;
          
            }
        }

        newData = false;

    }
}
            
void MovePosition()
{
  runallowed = true; //enable outputs
  stepper1.moveTo(CoordinateX); //move large motor to coordinates defined in the serial cases
}

//============

void stopMotor()//function activated by the pressed microswitch
{
  runallowed = false; //disable running
       
      stepper1.setCurrentPosition(0); // reset position
      Serial.println("STOP "); //print action
      stepper1.stop(); //stop motor
      stepper1.disableOutputs(); //disable power
      
}

Thanks in advance!

Don’t use interrupts with switches.

Scan the switch every ~50ms, look for a change in state, act appropriately.

What larryd said and if the switch(es) are far from the processor (> a few inches) the internal pullups may not be strong enough. Try lower values. Don't go lower than about 1K. Also a 0.1uF cap from the switch input to ground can help to filter noise from longer lines.

Use the state change detection method to check for a changing state on the switch.

And my update tutorial for state change detection on an active low switch.

groundFungus thats a really good point and I like the idea with the capacitor! I have no idea how far away the switches will sit yet, but it will certainly be over a few inches.

larryd or groundFungus, in the tutorial I watched the guy used an interrupt with a switch to stop his motor from running past the end of the rail and breaking things, so I copied him. I will switch to your method but can I ask why that is the better option? I have no idea

Thanks

Switches are slow and noisy on closing and opening.

Interrupts are meant for fast events.

Read these two discussions:

https://forum.arduino.cc/index.php?topic=719995.0

https://forum.arduino.cc/index.php?topic=720016.0

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