loading...
Cover image for Arduino Buttons Made Simple(r)!

Arduino Buttons Made Simple(r)!

j4s0nc profile image Jason C ・2 min read

Ok, wiring a button to an Arduino isn't really that hard.. But what if you're low on resistors? What if you only want to run logic once per press? Let's make that stuff simple too!

Why Use Resistors?

If you don't add a resistor to your circuit, you will see a lot of noise and your readings will be all over the place! In the Arduino tutorial linked above they use a 10 K ohm pull down to ground to reduce noise.

Circuit

I'm not going to go too deep in to Ohm's law, just know the higher the value less power is wasted, but the noise pickup will be greater.

Use A Built-in Pull Up Resistor!

Arduino has built in Pull Up Resistors, you just need to turn them on! There are internal 20K-ohm resistors used to pulled up 5V. But note, this configuration causes the input to read HIGH when the switch is open, and LOW when it is closed.

//setting Pinmode to INPUT_PULLUP, instead of basic INPUT
pinMode(BUTTON_PIN, INPUT_PULLUP);

Pull Up

Sweet, our circuit just got a little simpler!

Handling Button Presses

If you read the button pin in your loop, you'll get a flood of readings when you are pressing it. This can be great if you want to do something while the button is pressed. But what about running only one action per "press"?

I have three buttons wired up, we'll just track if one was pressed, and clear the settings after about two seconds.

#define RED_BTN 10
#define YLW_BTN 11
#define GRN_BTN 12

unsigned long lastRead = 0;
unsigned int readOffset = 1000; //max MS between resets
int lastButtonPressed = 0;
int buttonTimeout = 0;

void setup()
{
  Serial.begin(9600);
  pinMode(RED_BTN, INPUT_PULLUP);
  pinMode(YLW_BTN, INPUT_PULLUP);
  pinMode(GRN_BTN, INPUT_PULLUP);
}

void loop()
{

  buttonLogic(); //check for a press event every loop

  if (millis() - lastRead > readOffset) //run this part every 1000 milliseconds 
  {
    // Record read time
    lastRead = millis();

    if (--buttonTimeout < 0) {
      lastButtonPressed = 0; // reset button press after button timeout is hit
      buttonTimeout = 0;
    }

  }
}

void buttonLogic() {
  if (buttonPressed(RED_BTN)) {
    Serial.println("Red, Stop!");
  }
  if (buttonPressed(YLW_BTN)) {
    Serial.println("Yellow, hurry up!");
  }
  if (buttonPressed(GRN_BTN)) {
    Serial.println("Green, Go time!");
  }
}

const int PRESSED = LOW; // LOW means pressed when using INPUT_PULLUP
bool buttonPressed(int btn) {
  //Check if button is being pressed
  int state = digitalRead(btn);
  if (state == PRESSED) {
    // Check if first time pressed or different button
    if (lastButtonPressed != btn) {
      // Track which button was last pressed, set timeout cycles and return true
      lastButtonPressed = btn;
      buttonTimeout = 2;
      return true;
    }
  }
  // when button is not being pressed, 
  // or the same button has already been pressed, return false
  return false;
}

This logic will only print to serial once per press (or every two seconds if you hold it in).


Looking for more cool stuff? Check out the Pool Bot Series I'm writing

Discussion

markdown guide