Arduino Internal Pull-Up

When hooking up switches or buttons to an Arduino I/O pin, sometimes the results might appear completely random. Sometimes it will appear as though there is a delay from when the button is pressed until the state of the pin actually changes. Other times the pin’s value will seem to randomly fluctuate from HIGH to LOW. Even more maddening might be as your finger gets closer to the switch, the pin’s state changes!

The fix to these problems is simple: use pull-up resistors. Here’s how they can fix this problem and how you can use them with an Arduino board.

Detailed explanation…

Why doesn’t my button work!?

Consider the following circuit, which is a simple normally-open push-button on a breadboard. It has been wired so that one side is tied to +5V and the other side is connected to Pin 12 of an Arduino Uno. (Make you check with a multimeter to determine which pins are connected together and which are not.)

Floating Push Button Example

Picture 1: Floating Pushbutton on Breadboard

The code for this switch is very simple. The LED on Pin 13 should light up when Pin 12 is HIGH and be off when Pin 12 is LOW. The expected behavior is that the LED will be OFF whenever the button is not pushed and ON when the button is pushed.

/*
InputPinBlog
Test code to show what happens when a pin is floating (or not floating).
 */

void setup() {
  pinMode(13, OUTPUT); // Use Built-In LED for Indication
  pinMode(12, INPUT);   // Push-Button On Bread Board
}

void loop() {
  bool buttonState = digitalRead(12);  // store current state of pin 12
  digitalWrite(13, buttonState);
}

Take a look at this video to see what happens as the button is pushed. The LED’s behavior is not at all predictable! Sometimes it lights up, sometimes it stays on, sometimes it changes just when a finger gets close to it!

The pin is “Floating.” This schematic shows how the button is wired on the breadboard. What is PIN 12 connected to, when the button is unpressed? Nothing!

Floating Pin Schematic Version

Schematic 1: Schematic of Floating Pin

This means that any signals in the air, such as from nearby electronics, can cause the pin to “float” to either a HIGH or LOW. For example, this waveform from an oscilloscope shows what the pin is doing when nothing is connected.

Floating Pin Oscilloscope Screenshot

Picture 2: Oscilloscope Screenshot of Floating Pin

This video is the same breadboard circuit but with the oscilloscope waveform visible. As a human finger comes close to the pin, the waveform changes. 60Hz noise from the environment is being coupled into the circuit through the finger, which is what causes the “random” behavior of the input pin.

Great! Now that we understand why the pin randomly changes, how does it get fixed? Easy! Just make your Arduino do exercises… pull-ups in fact!

Using Pull-Ups to fix Floating

The fix for floating pins is to “pull them up” to a known value when the switch is unpressed. This is done with a Pull-Up resistor, as illustrated in the following schematic:

Pull-Up Resistor of an I/O Pin

Schematic 2: Pull-Up Resistor of an I/O Pin

Now when nothing is connected, current cannot flow through the resistor. So the Voltage on both legs will be the same. This means the same point where the resistor connects to the switch and Pin 12 will be forced to sit at 5V.

When the button is pressed, that same point will drop to 0V as current starts flowing through the resistor (ohm’s law). Since the resistor is there, you don’t have to worry about a short circuit. In this case, 10Kohms was picked as a relatively large value. The exact value of the resistor does not matter. You want something big enough to limit the amount of current wasted when the button is pressed, but not so big (like 10Mohm that you start having noise problems again.)

A really cool feature of the ATmega chips used by the Arduino platform is that they have these resistors already built into them! All that needs to be done is turn the resistor on and you get the previous schematic, for free! Here is the new breadboard circuit. Notice that the red jumper wire has changed to yellow. Also, it is no longer connected to 5V but now is connected to GND. That’s the [i]only[/i] difference in the hardware.

Button Wired with Internal Pull-Up

Picture 3: Button Wired with Internal Pull-Up (Blue wire connects to Pin 12 of the Arduino)

It only takes a single line of code to turn on these incredibly useful internal pull-up resistors. When a Pin has been configured for INPUT with pinMode(), simply use digitalWrite() to write a HIGH to that pin. Here is the same code with a single line added:

/*
InputPinBlog

Test code to show what happens when a pin is floating (or not floating).
 */

void setup() {
  pinMode(13, OUTPUT);    // Use Built-In LED for Indication
  pinMode(12, INPUT);      // Push-Button On Bread Board
  /* this next line is the new one */
  digitalWrite(12, HIGH);  // Turn on internal Pull-Up Resistor
}

void loop() {
  bool buttonState = digitalRead(12);  // store current state of pin 12
  digitalWrite(13, buttonState);
}

The combined video of the button working by using the internal pull-up and along with the waveforms on the oscilloscope is shown here.

Conclusion

When using any kind of “open” inputs with an Arduino such as switches, push buttons, reed relays, and some sensors a pull-up resistor is needed for reliable operation. These resistors hold the I/O pin at a known value until the switch forces the I/O pin to a different known value. The Arduino has these resistors built-in, they just need to be turned on in the sketch, usually in setup().

Feel free to contact me by leaving comments below.

Cheers!

9 Responses to "Arduino Internal Pull-Up"

  1. alexis says:

    you can also use pinMode(2,INPUT_PULLUP);
    as described here http://arduino.cc/en/Tutorial/InputPullupSerial

    Reply
    • James says:

      Yes. INPUT_PULLUP was added in the 1.x branch, after I made these videos. Probably won’t go back to fix them. I’ve converted over to just using INPUT_PULLUP. Less typing. ;)

      Reply
  2. Nainain says:

    The polarity of the pin is VCC with this ?
    What is the default polarity in the Input pin mode ?
    Nice tuto, thx

    Reply
    • James says:

      Polarity isn’t the right word. 5V and 0V are not polarities, they are voltages. The value of a pin is whatever voltage is applied to it. The default for the pin is to be floating. That’s the whole point of using the pull-up resistor, to force it to a known voltage / state.

      Reply
  3. James Blake says:

    Very useful info, thanks.

    One quick question, if you don’t mind – I’m going to use the Leonardo for a project of mine. Using the internal pullup resistors as you described above, how many buttons could I attach, and which pins can I attach them to? I want to avoid frying the board, if I can! :-)

    I presume each of the buttons would be connected between the pin and 5v, although I understand that pin 13 would need an extra resistor as it’s also connected to the LED.

    Thanks for any advice,

    (another) James

    Reply
    • baldadmin says:

      You can use any of the digital or analog pins for a button. Just remember if you are using an analog pin, to refer to it as A0 or A1 in your code. As far as connections go, you want one side of the button to your pin and the other to ground. You DO NOT need to do anything special for Pin 13. The board is decided to reduce the impedance effects of having the LED there.

      Reply
  4. James Blake says:

    Thanks very much for your help, and for clearing up the confusion about pin13.

    The Leonardo arrived yesterday. I love it!

    Reply
  5. Derek says:

    Great video, very understandable. The oscilloscope(?) was a helpful addition to see what was going on.

    One question though: is pinMode(2, HIGH) and pinMode(2, INPUT_PULLUP) the same thing? I was a little confused reading through the arduino.cc stuff as they kept saying to use a pull up resister but the code only showed pinMode(…, HIGH)

    Thanks,
    Derek

    Reply
    • baldadmin says:

      Hi Derek, yes they are the same. INPUT_PULLUP was introduced in 1.0.3, which was long after I made the videos. One correction, you use digitialWrite() to send the HIGH, not pinMode(). Many tutorials (even on arduino.cc’s site) will mention the digitalWrite() method.

      Reply

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

©2014 Baldengineer Productions, Inc.