Circuit Protection
Pull Up Your Pins: How to Size Pull-up Resistors
One of the first lessons many people learn when starting off learning practical, hands-on electronics is the need for pull-up resistors. Whether to prevent floating I/O pins on a microcontroller or interfacing two circuits via an open-drain design; pull-up resistors are an often necessary but rarely appreciated component. So why do we use pull-up resistors, can’t we just connect a wire to the Vcc supply of our device? What size resistor should you use?
So why do we even need to bother with pull-up resistors to begin with? Let’s assume we have a momentary normally open pushbutton and we don’t want the I/O pin to float. Why not just connect a wire to the Vcc between the I/O pin and the lead of the pushbutton? This would work to prevent the microcontroller’s I/O pin from floating—it would need a Vcc or a solid HIGH—while the button is not pressed. However, as soon as the button is pressed, a short circuit would occur between the Vcc and ground (Figure 1). This will create a lot of heat, and if the device is battery-powered, it will drain the battery quickly. In addition to thwarting problems associated with floating microcontroller I/O pins, pull-up resistors are a necessity when using an open-drain topology. We discussed open drains at length in this Bench Talk post.
Figure 1: Just running a wire allows for a short circuit (Left). A pull-up resistor prevents floating inputs while as preventing an unwanted short circuit (Right). (Source: Author)
So how do we select the right sized resistor? As is true with most good engineering questions, the answer depends on your application. Let’s start by thinking about the extreme options 0Ω and let’s say 1mΩ. The 0Ω option (small value resistors are referred to as strong pull-ups as they allow a lot of current to flow) we already discussed. Too small of a resistance value and we get too much current flow which can either be unsafe or at the very least energy inefficient. What if we go with a huge 1mΩ resistor? Won’t that be safe? Large resistor values are referred to as weak pull-ups as they prevent too much current from flowing. The answer is yes but it comes at a cost. In this case, it’s a trade-off between speed and power.
Think of the microcontroller’s I/O pin as a capacitor. Recall that the voltage across a capacitor cannot change instantaneously. Rather it charges up based on what is known as the timing constant (T) and is mathematically expressed as T=RC where R is the value of the resistor and C is the value of the capacitor. When we add a very large resistor, we are increasing the time it takes the capacitor to charge by limiting the current flow. Practically speaking that means the microcontroller will not immediately detect the pressed button as it will take some amount of time for the microcontroller to see the voltage change from what it considers a LOW/OFF state to the HIGH/ON state. This might result in unacceptable circuit performance from a user perspective. The system would appear to not respond in a timely fashion. In open-drain applications such as the I2C serial communication protocol, the large timing constant would have a negative impact on the I2C bus to achieve the desired baud rate on its Serial Data Line (SDA) and Serial Clock Line (SCL) lines.
Mathematically speaking this is how you compute the resistor values:
Rp(min) is the smallest resistor value that is acceptable and is given by the equation:
Rp(min) = (Vcc - VOL(max) ) / IOL whereby:
- Vcc is the supply voltage.
- VOL(max) is the maximum voltage that is registered as a low by the microcontroller’s I2C pins.
- IOL is the current draw at VOL
Rp(max) is the largest resistor value that is acceptable and is given by the equation:
Rp(max) = tr / (0.8473 x Cb) whereby:
- tr is the acceptable rise time of SDA and SCL lines for the desired baud rate. Check the datasheets of the devices used in your design.
- Cb is the anticipated capacitive load that will be driven. A quick side note, the number of devices that can share an I2C bus is limited by the sum of the Printed Circuit Board (PCB) and device input capacitances. Per the I2C specification for standard and fast operating modes, this limit is 400pF. After which an I2C buffer chip is required. This usually occurs well before the theoretical addressing limit of 112 devices for 7-bit addressable I2C implementations.
Now for a practical rule of thumb, here are the resistor values you should consider testing in your circuit to see if you get the desired performance:
- 1kΩ to 10kΩ for general purposes.
- 10kΩ to 100kΩ if you have a low-power use case such as a device that is battery powered.
The last thing to consider is that many microcontrollers have internal pull-up resistors that can be turned on via code. Be sure to check the data sheets to see if the internal resistor value is appropriately sized for your application. If not, you will have to use external pull-up resistors.