A digital input is a board pin which can read if it sees a high (on) or low (off) logic level connected to it.  For example if you connect a button to a digital input you can detect when it's pressed and released.  MicroPython makes it just as easy to use a pin digital inputs as it does outputs.

To learn about digital inputs we'll wire a button to a MicroPython board and detect when it's pressed.  You'll need the following hardware for this example:

All of the necessary parts except the MicroPython board are available in the Adafruit Parts Pal pack.

Connect the button to the board ground and a GPIO pin as follows:

  • Board pin 12 to one corner of the button.  Note you don't want to use pin 15 on the ESP8266 because it's connected to a pull-down resistor internally that will conflict with reading other signals.
  • Board ground to the opposite corner of the button.

With this setup when the button is pressed it will connect pin 12 to ground and read a low signal on the pin.  When the button is released it won't be connected to ground anymore and will actually 'float' or fluctuate between random high & low values.  Floating at random values isn't a problem though because you can enable an internal pull-up resistor on the pin.  The pull-up resistor will pull the input to read a high level instead of floating when the button is released.

Be aware that on some boards not all the pins support an internal pull-up resistor. Check your board's documentation for more details.  

If the board doesn't support an internal pull-up resistor on the pin you can add an external one easily.  Just connect a 10 kilo ohm or higher resistor from the input pin to a high logic level like the 3.3V output of the board.

Once the hardware is wired up connect to a serial or other MicroPython REPL on the board.  Run the following commands to create a digital input pin with an internal pull-up resistor enabled:

import machine
button = machine.Pin(12, machine.Pin.IN, machine.Pin.PULL_UP)

Just like with creating a digital output on the previous page, you first need to import the machine module.  Remember if you've already imported the machine module earlier in a script you don't need to import it again.

Next a button object is created as an instance of the machine module Pin class. However notice the parameters are a little bit different when creating this input as compared to creating an output.  The parameters are:

  • The board pin name or number, just like with creating a digital output pin.
  • The type of pin, in this case a digital input with the value machine.Pin.IN.  This means the pin will be set as an input that can read high or low levels.
  • The third parameter is the constant value machine.Pin.PULL_UP to enable an internal pull-up resistor on the pin.  This parameter isn't actually required and if it's not specified then the pin will still be an input but it won't have any internal pull-up resistor set.

Note: If you're using an external pull-up resistor or reading something other than a button that might not require the internal pull-up be sure to omit the third machine.Pin.PULL_UP parameter!

Now read the value of the pin by calling the value function without any parameters:


Without the button being pressed you should see the value 1 returned:

Now press the button and run the same command again while the button is being pressed, you should see a value 0 returned:

If you see different values double check your wiring and check that the board pin doesn't have something else connected to it.

The value function returns the current level of the pin, either 1 for a high logic level or 0 for a low logic level.  Notice how the button is at a high level (value returns 1) when it's not pressed.  This is because the pull-up resistor keeps the pin at a high level when it's not connected to ground through the button.  When the button is pressed then the input pin connects to ground and reads a low level (value returns 0).

Reading a digital input is as easy as calling the value function!

One common task when reading a digital input like a button is detecting when the button is pressed or released.  For example try running the following code which prints a message when the button is pressed:

import machine
button = machine.Pin(12, machine.Pin.IN, machine.Pin.PULL_UP)
while True:
    if not button.value():
        print('Button pressed!')

This code uses an infinite loop (the while True loop) to continually check if the button is pressed.  Remember the value function returns 0 (or false) when the button is pressed so the if statement uses the not operator to invert the button value and detect when it's a 0 or false value.

Press the button quickly and notice the screen is immediately filled with button pressed messages:

Press Ctrl-c to stop the loop and get back to the REPL.

You might wonder if something went wrong to cause all button pressed messages.  Nothing is wrong, however the code needs to be a little smarter if it wants to only print the message once when the button is pressed.  

Now try the following code which prints a message only once when the button is pressed or released:

import machine
import time
button = machine.Pin(12, machine.Pin.IN, machine.Pin.PULL_UP)
while True:
    first = button.value()
    second = button.value()
    if first and not second:
        print('Button pressed!')
    elif not first and second:
        print('Button released!')

Try pressing and releasing the button a few times.  You should see a message printed only once!

This code is a little more complex but still easy to explain.  The way it works is the code looks for only when the input pin changes from a high to low level (the button was just pressed) or a low to high level (the button was just released).  By looking for this change instead of a constant pressed or not pressed value the code can print a message once instead of repeatedly.

To check for this change in level the code reads the button twice.  Notice the first call inside the loop is to the button value function.  This gets an initial button value and saves it in the variable called first.  

Next the time.sleep function is called to pause the program for a small time (10 milliseconds in this case).  This very short pause is there to 'debounce' the button press.  When a button is physically pressed it can randomly jump from low to high values for a small time as metal contacts inside the button start to touch.  By delaying a bit between the two readings it gives time for the button to stabilize and not bounce around randomly.  You don't want to delay for too long though or you might miss the change in button state!

Finally the button is read again and its value stored in the variable called second.  The first and second variables hold the two button readings.

Once the code has two button readings it can check if there was a change between those readings.  For example if the button was pressed it would have a first reading that was true/1 (button not pressed) and a second reading that was false/0 (button pressed).  Likewise if the button was released it would first read false/0 (button pressed) and then read true/1 (button released).  The if statement checks for both these cases and prints out a message!

Try combining both of the examples in this guide to light up a LED when a button is pressed.  As a hint look at the button code above and think about how you might add extra code to turn a LED on or off along with printing messages.

That's all there is to reading a pushbutton with a digital input using MicroPython!  Digital inputs are great for reading buttons, switches, and simple digital devices like a PIR motion sensor or magnetic door open sensor.

This guide was first published on Sep 02, 2016. It was last updated on Apr 23, 2024.

This page (Digital Inputs) was last updated on Sep 01, 2016.

Text editor powered by tinymce.