ESE101: Schematics, Buttons, and Pullups
Last week ended with a cliffhanger: the code didn’t work, our button assumptions were wrong, and I asked you to look at a schematic. Can we read a schematic and figure out how the button works?
Yes we can!
Let’s start by reviewing: A schematic is a picture of what a circuit board looks like. It shows all the chips, connections, and other components that make up a circuit board. If you’re ever confused about something hardware-related, start with the schematic. Schematics can be overwhelming at first glance, but if you focus on one part of a schematic at a time they start to make more sense.
Open the MSP430 LaunchPad schematic, here’s the first page:
Note that this is a slightly different pdf than the one currently hosted on TI's website. The pdf on TI's website isn't searchable, but Adrian Fernandez, TI microcontroller customer experience manager and all-around nice guy, got a searchable one for us - thanks Adrian! He said it's making its way to their website soon.
TI has done a nice job of labeling the schematic with what each part of the picture is for. The big square in the middle is the MSP430F552x microcontroller. The ‘x’ means that any number can go in place of the ‘x’ - our chip is an MSP430F5529, but TI also makes a 5521, 5522, 5524, and others: this schematic can be used for all of them. TI has drawn dashed-line boxes around the parts of the schematic that are for reset, clocking (“LFXTCLK” and “XT2”), power (“Analog VCC”), and so on.
Remember that we’re trying to figure out how the button connected to GPIO P1.1 works. Each pin of the microcontroller is labeled, so let’s find P1.1 on the schematic:
Usually schematic pdfs contain text so you can use your pdf viewing software to find whatever text you’re looking for. Sometimes, though, schematics are not searchable, and you'll have to search with your eyes. Schematics are usually arranged in functional blocks, so you should be able to find related components/chips/functionality if you have to manually search a schematic.
I've circled P1.1 in that image: it doesn’t appear to be connected to anything, but trust me, it is. You need to go to the second page of the schematic pdf and you’ll find “P1.1” referenced there:
The two P1.1 labels refer to the same connection even though they are on different pages of the schematic. Looking closer you see that the chip pin P1.1 is connected to something called S2:
S2 is a push button switch. When the button is not pushed, the switch is open and the two contacts in the switch are not connected. When the button is pushed, the switch is closed and the two contacts in the switch are connected. The switch’s schematic symbol tries to show you how it works: you can see that the two sides of the switch are not connected in the schematic. But if you imagine the button being pushed, the little hat right under the text “S2” is pushed down which forces the horizontal-ish line down, which connects the switch’s contact.
I’ve redrawn the circuit here:
This drawing shows the P1.1 pin connected to the push button switch S2. The button is not pushed, so the switch is open: there is no electrical connection from one side of the switch to the the other side.
Remember that we’re trying to use the input voltage on GPIO P1.1 to know if the button is pushed or not, so that we can turn on an LED when the button is pushed.
As a first step we’ll try to answer the question: “what is the voltage on pin P1.1 when the switch is open and closed?” I’ve drawn a question mark pointing to the spot where we want to know the voltage - let’s figure it out.
When the button is not pushed, the switch is open, and P1.1 is not connected to anything outside the MSP430 chip. So, what is the voltage at the question mark? The answer is: we don’t know! In fact, we can’t know the voltage. We call an unconnected signal or wire floating: it’s just hanging (floating) there. The voltage on a floating signal is undefined. We have no idea what the voltage is, and we can’t depend on it or use it.
This should make you a bit nervous, or curious, or both. Hold that thought while we look at what happens when the button is pushed:
When the button is pushed the switch S2 is closed: the switch connects P1.1 directly to ground. This means that the voltage at GPIO pin P1.1 is zero volts (0V).
Here’s a summary of what we’ve just learned:
- Button pushed: P1.1 input voltage is 0V
- Button not pushed: P1.1 input voltage is undefined (it might be 0V, it might be some other value, we can’t know)
Our microcontroller code will need to figure out whether the button is pushed by reading P1.1’s input voltage. The undefined voltage when the button is not pushed is a problem. That pesky floating signal needs to change. But how?
Well, we know that when the button is pushed P1.1 sees 0V. And we know that a digital GPIO input pin can only see two values: low voltage (0V) and high voltage (3V for the MSP430; this can vary for different chips). Since the low voltage (0V) is seen when the button is pushed, can we change something so that a high voltage (3V) is seen when the button is not pushed?
Yes we can!
Let’s consider an incorrect but instructive solution: connect the P1.1 wire to a 3V power supply like this:
High voltage is commonly drawn with a triangle pointing up with the actual voltage written above it, as I’ve done here.
Now when the button isn’t pushed and the switch is open, GPIO P1.1’s input voltage is 3V (high voltage). This seems like an improvement over the undefined voltage we had before. But what happens when the switch is closed:
Uh-oh. The button is pushed, the switch connects P1.1 directly to ground… and P1.1 is also connected directly to high voltage. It is NEVER a good idea to connect a high voltage directly to ground - this is called a short circuit.
Not to be confused with this short circuit:
In the bad kind of short circuit, current will start flowing between the high voltage source and ground. Hopefully your circuit will just stop working; less hopefully components or power supplies might start smoking and die. So we need to figure something else out.
I said that this was an incorrect yet instructive solution: we fixed the undefined voltage when the button is not pushed by connecting the P1.1 wire to a high voltage, but our solution broke horribly when the button is pushed because we created a short circuit.
Is there a way to connect P1.1 to high voltage so that when the button is not pushed the GPIO P1.1 is at high voltage, but when the button is pushed the GPIO is at ground, and also avoid a short circuit?
Yes we can!
We can use a resistor to connect P1.1 to a high voltage so when the button isn’t pressed and the switch is open, like this:
This resistor “R” is called a pull-up resistor: it pulls the signal it’s attached to up to a high voltage when nothing else is connected to the signal. Wikipedia says it well:
“A pull-up resistor pulls the voltage of the signal it is connected to towards its voltage source level. When the other components associated with the signal are inactive, the voltage supplied by the pull up prevails and brings the signal up to a logical high level. When another component on the line goes active, it overrides the pull-up resistor. The pull-up resistor ensures that the wire is at a defined logic level even if no active devices are connected to it.”
When the button is pushed and the switch is closed:
P1.1 is connected to ground and so it reads as a low voltage, but unlike in our previous incorrect yet instructive example, there is no short circuit! There’s no short circuit because the pull-up resistor is there - the high and low voltages are not directly connected.
Let me recap what we’ve learned today:
- The button isn’t useful as-is because when the button isn’t pushed, the input voltage on P1.1 is undefined.
- We can use a pull-up resistor on the P1.1 wire so that when the button isn’t pushed the input voltage on P1.1 is high, and when the button is pushed the input voltage on P1.1 is low. This means we can tell when the button is pushed or not by reading the value on P1.1.
But we don’t have a pull-up resistor on P1.1 on the LaunchPad board, so how can we add one? We could break out a soldering iron and add a resistor to the LaunchPad: sometimes fixing problems in hardware is your only option. But fixing problems in software is almost always easier than fixing problems in hardware, and today we’re in luck.
It turns out that this is a very common problem when using microcontroller pins as inputs. Because it’s so common, the MSP430 (and pretty much every other modern microcontroller) has internal pull-up and pull-down resistors on each GPIO pin. Each GPIO pin can be configured with a pull-up resistor, a pull-down resistor, or no resistor with a couple of GPIO configuration register settings.
Next week we’ll learn how to configure P1.1 with a pull-up resistor, and then make the button pushes light up our LED. See you next week!
Note: Sparkfun has a good tutorial on pull-up resistors, where they cover pretty much the same button example we just went through. Check them out for a slightly different take on this problem.
This post is part of a series. Check out the complete Embedded Software Engineering 101 series here.