Arduino Buttons Made Simple(r)!
Tags: arduino, c, automation
Published: 2020-05-10 23:54:32

Ok, [wiring a button to an Arduino](https://www.arduino.cc/en/tutorial/button) 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](https://dev-to-uploads.s3.amazonaws.com/i/ovci8bxensqqlkk27fjp.png)

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](https://www.arduino.cc/en/Tutorial/DigitalInputPullup), 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. 

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

![Pull Up](https://dev-to-uploads.s3.amazonaws.com/i/m01dngy5i151p5fby67r.png)

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. 

```c
#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](https://dev.to/j4s0nc/a-deep-dive-into-building-a-pool-bot-44ib)