Pinouts, pullups and logic errors have been addressed elsewhere, so I will focus on switch debouncing. Debouncing, in my opinion, is best handled in software (rather than hardware) for large volume production costs and lazy programmers (like me). For small projects a simple pullup / cap circuit offers better reliability and improved speed, but I'm just lazy in my old age. Also keep in mind that switch bounce worsens significantly over the life of a switch. I've seen new PB's with bounce < 20 ms worsen to over 300 ms with reasonable usage, so keep that in mind with projects that become semi-permanent.
Here's what I use for a software solution on a fairly bouncy SPST NO pushbutton. In this case, I'm using NO PB to GND with 1K external pullups, since I personally don't want to depend on whether or not the internal pullup still works on older devices I may have abused in a former life.... Of course, arguments could be made for various areas still needing cleanup, improved encapsulation, quicker response, higher quality, etc., but this works for me for now.
inSw.h:
class inSw
{
private:
volatile boolean swState; // current state ( 0 / 1 ) of switch
public:
uint8_t pinNum;
volatile unsigned long lastPush; // Time (millis() ) when last switch push detected
unsigned long debTime = 30; // Time (micros() ) required to debounce switch
void init(uint8_t sw);
boolean readState(void);
} ;
inSw.cpp:
void inSw::init(uint8_t sw) {
pinNum = sw;
pinMode(sw, INPUT);
swState = 0;
lastPush = millis();
};
boolean inSw::readState() {
// swState = digitalRead(pinNum);
return swState;
}
void setupSwitches(void) {
swS1.init(I2C_SOA); // pin D20
attachInterrupt(digitalPinToInterrupt(swS1.pinNum), swS1Press, FALLING);
}
Interrupt Service Routines are placed outside Setup() and Loop(), with the attachInterrupt (above) called from inside Setup(). This allows the switch to break long-running routines, such as Stepper.step(10000) which bangs against the limit switch on step 14....
void swS1Press() {
unsigned long now = millis();
if (swS1.lastPush < (now - swS1.debTime)) { // if newly pushed
RunStop.toggle();
swS1.lastPush = millis(); // sw last pushed now
if (RunStop.val == RS_RUN)
digitalWrite(LED_PIN, HIGH); // set the LED on
else
digitalWrite(LED_PIN, LOW); // set the LED off
}
}
Lastly, just remember to check the switch state at various points inside loop(). I use this switch as an emergency stop switch, and the onboard LED to ensure it triggers.
ledPinbut you are changingmotorPinin your loop.