# MicroPython Hardware: Digital I/O

## Overview

Warning: Note this guide was written for MicroPython.org firmware and not Adafruit CircuitPython firmware.

Info: This guide was written for older MicroPython versions. Please see current MicroPython documentation for the latest usage.

![](https://cdn-learn.adafruit.com/assets/assets/000/035/373/medium800/microcontrollers_IMG_5147.jpg?1472803814)

https://www.youtube.com/watch?v=-kVW8yffe0c

Digital I/O, or input/output, is one of the most basic ways to talk to hardware. &nbsp;We say 'digital' because it only deals with **on** or&nbsp; **off** values and nothing in-between. &nbsp;For example with digital I/O a LED can be turned completely on and completely off repeatedly to blink. &nbsp;Or using digital I/O you can read when a switch or button is moved&nbsp;on or off. &nbsp;With just a few lines of MicroPython code you'll be a master of digital I/O in no time.

This guide explores how to use digital I/O pins with MicroPython. &nbsp;You'll see how to control a LED using a digital output pin, and read a pushbutton using a digital input pin. &nbsp;These basic digital I/O examples can serve as the starting point for more complex and interesting projects that use hardware like LEDs, buttons, switches, relays, transistors, and even simple digital sensors!

Before you get started you'll want to be familiar with the basics of using MicroPython by reading these guides:

- [MicroPython Basics: What is MicroPython?](../../../../micropython-basics-what-is-micropython/overview)
- [MicroPython Basics: How to Load MicroPython on a Board](../../../../micropython-basics-how-to-load-micropython-on-a-board)
- [MicroPython Basics: Blink a LED](../../../../micropython-basics-blink-a-led/overview)
- [MicroPython Basics: Load Files & Run Code](../../../../micropython-basics-load-files-and-run-code/overview)

# MicroPython Hardware: Digital I/O

## Digital Outputs

A digital output is a simple&nbsp;high ( **on** ) or low ( **off** ) signal from a board's pin that you can control with MicroPython. &nbsp;Using a digital output you can turn something on or off, like a LED, a relay, a transistor, or more.

Let's walk through how to turn a LED on and off with a digital output from a MicroPython board. &nbsp;There's an entire&nbsp;[guide just on blinking a LED with MicroPython](../../../../micropython-basics-blink-a-led/overview) that you'll want to read and follow&nbsp;first. &nbsp;In that guide you'll see how to [wire a LED to a MicroPython board](../../../../micropython-basics-blink-a-led/hardware), for example like with the [Feather Huzzah ESP8266](https://www.adafruit.com/product/2821), a red LED, and a 560 ohm resistor as below:

![](https://cdn-learn.adafruit.com/assets/assets/000/035/356/medium800/microcontrollers_esp8266_blink_led_bb.png?1472787270)

- **Digital GPIO 15** is connected to the **anode, or longer leg, of the LED**. &nbsp;It's very important to use the correct leg of the LED otherwise it won't light up as expected!
- **The cathode, or shorter leg, of the LED** is connected to **one side of the resistor&nbsp;** (unlike the LED it doesn't matter which way you orient the resistor).
- **The other side of the resistor** is connected to the board's **ground or GND pin**.

Once the LED is wired to the board&nbsp;connect to the serial or other MicroPython REPL and create a digital output pin by running the following code:

```
import machine
pin = machine.Pin(15, machine.Pin.OUT)
```

The **import machine** line will import the machine module which provides much of the hardware access API for MicroPython. &nbsp;In particular the machine module has a Pin class that allows you to create pin objects for all of the digital I/O pins on a board.

In this case the second line will create an object called **pin** and set it as an instance of the machine module Pin class. &nbsp;The initializer for the Pin class takes two important parameters:

- **The number or name of the board pin.** [Check your board's documentation](../../../../micropython-basics-what-is-micropython/overview?view=all#faq-10) for details on the pin values--some boards like the pyboard use a string identifier (like 'X1') while other boards like the ESP8266 use simple numbers (like 15, 14, etc.).
- **The type of digital I/O pin, in this case a digital output.** &nbsp;The **machine.Pin.OUT** value is a special constant value&nbsp;that tells MicroPython we intend to use this pin as an output we can control.

Now control the output level of the pin by calling the **value** function on the pin object in different ways:

```
pin.value(0)
pin.value(1)
pin.value(True)
pin.value(False)
```

The value function takes a single parameter which indicates if the output should be high or low (on or off). &nbsp;Notice when the pin value is set to 0 or False the LED turns off, and when set to 1 or True the LED turns on! &nbsp;The LED turns on and off because the digital output connected to it changes from high to low voltage levels.

There's also a handy shortcut for&nbsp;setting a pin to a high or low level directly with the **high** and **low** functions:

```
pin.high()
pin.low()
```

The high function will set the pin to a high level, and the low function will set the pin to a low level. &nbsp;Notice again the LED turns on and off as the level from the pin changes.

That's all there is to using digital outputs with MicroPython! &nbsp;Although they're simple digital outputs are very handy for talking to devices that expect an on or off signal like a LED, [a relay](https://www.adafruit.com/products/2895) or [power tail](https://www.adafruit.com/product/268), or a [transistor](https://www.adafruit.com/products/756) controlling high power&nbsp;devices like a [solenoid](https://www.adafruit.com/products/412), [laser](https://www.adafruit.com/products/1054), [super bright LED](https://www.adafruit.com/products/754)&nbsp;and more.

# MicroPython Hardware: Digital I/O

## Digital Inputs

A digital input is a board pin which can read if it sees a high ( **on** ) or low ( **off** ) logic level connected to it. &nbsp;For example if you connect a button to a digital input you can detect when it's pressed and released.&nbsp; 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. &nbsp;You'll need the following hardware for this example:

- **A board running MicroPython** , for this example we'll use the [Feather HUZZAH ESP8266](https://www.adafruit.com/product/2821) but any MicroPython board should work.
- **A momentary push button** , like one of these [breadboard friendly buttons](https://www.adafruit.com/products/367).
- **A [breadboard](https://www.adafruit.com/products/64) and [hookup wires](https://www.adafruit.com/products/153).**

All of the necessary parts except the MicroPython board are available in the [Adafruit Parts Pal pack](https://www.adafruit.com/products/2975).

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

![](https://cdn-learn.adafruit.com/assets/assets/000/035/367/medium800/microcontrollers_micropython_huzzah_button.png?1472798079)

![](https://cdn-learn.adafruit.com/assets/assets/000/035/376/medium800/microcontrollers_IMG_5143.jpg?1472840147)

- **Board pin 12** to **one corner of the button**. &nbsp;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. &nbsp;When the button is released it won't be connected to ground anymore and will actually 'float' or fluctuate between random high & low values. &nbsp;Floating at random values&nbsp;isn't a problem though because you can enable an internal pull-up resistor on the pin. &nbsp;The pull-up resistor will pull the input to read a high level&nbsp;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](../../../../micropython-basics-what-is-micropython/overview?view=all#faq-10) for more details. &nbsp;

If the board doesn't support an internal pull-up resistor on the pin you can add an external one easily. &nbsp;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. &nbsp;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. &nbsp;Remember if you've already imported the machine module earlier in a script you don't need to import it again.

Next&nbsp;a **button** object is created as an instance of the machine module Pin class. However notice the parameters are a little bit different&nbsp;when creating this input as compared to creating an output. &nbsp;The parameters&nbsp;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**. &nbsp;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.** &nbsp;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&nbsp;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:

```
button.value()
```

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

![](https://cdn-learn.adafruit.com/assets/assets/000/035/369/medium800/microcontrollers_Screen_Shot_2016-09-02_at_12.28.31_AM.png?1472801335)

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

![](https://cdn-learn.adafruit.com/assets/assets/000/035/370/medium800/microcontrollers_Screen_Shot_2016-09-02_at_12.29.43_AM.png?1472801410)

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. &nbsp;Notice how the button is at a high level (value returns 1) when it's not pressed. &nbsp;This is because the pull-up resistor keeps the pin at a high level when it's not connected to ground through the button. &nbsp;When the button is pressed then the input pin&nbsp;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. &nbsp;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. &nbsp;Remember the value function returns 0 (or false) when the button is pressed&nbsp;so the if statement&nbsp;uses the **not** operator to invert the button value&nbsp;and detect when it's a 0 or false value.

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

![](https://cdn-learn.adafruit.com/assets/assets/000/035/371/medium800/microcontrollers_Screen_Shot_2016-09-02_at_12.37.44_AM.png?1472801916)

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. &nbsp;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. &nbsp;

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()
    time.sleep(0.01)
    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. &nbsp;You should see a&nbsp;message printed only once!

![](https://cdn-learn.adafruit.com/assets/assets/000/035/372/medium800/microcontrollers_Screen_Shot_2016-09-02_at_12.50.53_AM.png?1472802707)

This code is a little more complex but still easy&nbsp;to explain. &nbsp;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). &nbsp;By looking for this change instead of a constant pressed or not pressed value the code can&nbsp;print a message once instead of repeatedly.

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

Next&nbsp;the **time.sleep** function is called to pause the program for a small time (10 milliseconds in this case). &nbsp;This very short pause is there&nbsp;to 'debounce' the button press. &nbsp;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. &nbsp;By delaying a bit between the two readings it gives time for the button to stabilize and not bounce around randomly. &nbsp;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**. &nbsp;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. &nbsp;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). &nbsp;Likewise if&nbsp;the button was released it would first read false/0 (button pressed) and then read true/1 (button released). &nbsp;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. &nbsp;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&nbsp;MicroPython! &nbsp;Digital inputs are great for reading&nbsp;[buttons, switches](https://www.adafruit.com/categories/155), and&nbsp;simple digital devices like a [PIR motion sensor](https://www.adafruit.com/products/189) or [magnetic door open sensor](https://www.adafruit.com/products/375).


## Featured Products

### Adafruit Parts Pal

[Adafruit Parts Pal](https://www.adafruit.com/product/2975)
[LEDs](https://www.adafruit.com/categories/90) and [passives](https://www.adafruit.com/categories/156) and [transistors](https://www.adafruit.com/categories/153) and [switches](https://www.adafruit.com/categories/155) and op-amps oh my!&nbsp;The...

Out of Stock
[Buy Now](https://www.adafruit.com/product/2975)
[Related Guides to the Product](https://learn.adafruit.com/products/2975/guides)
### MicroPython pyboard

[MicroPython pyboard](https://www.adafruit.com/product/2390)
The **pyboard** is a compact and powerful electronics development board that runs MicroPython. It connects to your PC over USB, giving you a USB flash drive to save your Python scripts, and a serial Python prompt (a REPL) for instant programming. Requires a micro USB cable, and...

In Stock
[Buy Now](https://www.adafruit.com/product/2390)
[Related Guides to the Product](https://learn.adafruit.com/products/2390/guides)
### Adafruit Feather HUZZAH with ESP8266 - Loose Headers

[Adafruit Feather HUZZAH with ESP8266 - Loose Headers](https://www.adafruit.com/product/2821)
Feather is the new development board from Adafruit, and like its namesake, it is thin, light, and lets you fly! We designed Feather to be a new standard for portable microcontroller cores.

This is the&nbsp; **Adafruit Feather HUZZAH ESP8266** &nbsp;- our take on an...

Out of Stock
[Buy Now](https://www.adafruit.com/product/2821)
[Related Guides to the Product](https://learn.adafruit.com/products/2821/guides)
### Adafruit HUZZAH ESP8266 Breakout

[Adafruit HUZZAH ESP8266 Breakout](https://www.adafruit.com/product/2471)
Add Internet to your next project with an adorable, bite-sized WiFi microcontroller, at a price you like! The ESP8266 processor from Espressif is an 80 MHz microcontroller with a full WiFi front-end (both as client and access point) and TCP/IP stack with DNS support as well. While this chip...

In Stock
[Buy Now](https://www.adafruit.com/product/2471)
[Related Guides to the Product](https://learn.adafruit.com/products/2471/guides)
### ESP8266 WiFi Module

[ESP8266 WiFi Module](https://www.adafruit.com/product/2282)
This interesting module is a lot of fun for hobbyists and students who are interested in experimenting with the ESP8266 WiFi chipset. We bought a bunch of these modules, updated the firmware to the much-easier-to-use v0.924 and wrote some Arduino code to grab a webpage.

We do not...

No Longer Stocked
[Buy Now](https://www.adafruit.com/product/2282)
[Related Guides to the Product](https://learn.adafruit.com/products/2282/guides)
### WiPy 1.0 - IoT Development Platform

[WiPy 1.0 - IoT Development Platform](https://www.adafruit.com/product/3184)
The **WiPy** is an enterprise grade IOT development platform &nbsp;that runs Python in real time with the perfect blend of power, speed, friendliness, and flexibility. Within a few minutes you can wirelessly connect to it and get a Python REPL command line.

In addition to...

No Longer Stocked
[Buy Now](https://www.adafruit.com/product/3184)
[Related Guides to the Product](https://learn.adafruit.com/products/3184/guides)
### Teensy 3.2 + header

[Teensy 3.2 + header](https://www.adafruit.com/product/2756)
[Teensy](http://www.pjrc.com/teensy/index.html) 3.2&nbsp;is a small, breadboard-friendly development board designed by Paul Stoffregen and PJRC. Teensy 3.2&nbsp;brings a low-cost 32 bit ARM Cortex-M4 platform to hobbyists, students and engineers, using an adapted version of the...

No Longer Stocked
[Buy Now](https://www.adafruit.com/product/2756)
[Related Guides to the Product](https://learn.adafruit.com/products/2756/guides)
### Tactile Button switch (6mm) x 20 pack

[Tactile Button switch (6mm) x 20 pack](https://www.adafruit.com/product/367)
Little clicky switches are standard input "buttons" on electronic projects. These work best in a PCB but [can be used on a solderless breadboard as shown in this tutorial](https://learn.adafruit.com/adafruit-arduino-lesson-6-digital-inputs?view=all). The pins are normally...

In Stock
[Buy Now](https://www.adafruit.com/product/367)
[Related Guides to the Product](https://learn.adafruit.com/products/367/guides)

## Related Guides

- [Adafruit Feather HUZZAH ESP8266](https://learn.adafruit.com/adafruit-feather-huzzah-esp8266.md)
- [Level Shifting 3.3V microcontrollers and NeoPixels](https://learn.adafruit.com/neopixel-levelshifter.md)
- [micro:bit Lesson 2. Controlling LEDs on Breadboard](https://learn.adafruit.com/micro-bit-lesson-2-controlling-leds-on-breadboard.md)
- [Adafruit IO Home: Security ](https://learn.adafruit.com/adafruit-io-home-security.md)
- [3D Printed IoT On Air Sign for Twitch](https://learn.adafruit.com/3d-printed-iot-on-air-sign-for-twitch.md)
- [Remote Control with the Huzzah + Adafruit.io](https://learn.adafruit.com/remote-control-with-the-huzzah-plus-adafruit-io.md)
- [Ladyada's Toolkit](https://learn.adafruit.com/ladyadas-toolkit.md)
- [CircuitPython Hardware: MPR121 Capacitive Touch Breakout](https://learn.adafruit.com/circuitpython-hardware-mpr121-capacitive-touch-breakout.md)
- [MicroPython Basics: Loading Modules](https://learn.adafruit.com/micropython-basics-loading-modules.md)
- [MicroPython Basics: How to Load MicroPython on a Board](https://learn.adafruit.com/micropython-basics-how-to-load-micropython-on-a-board.md)
- [MicroPython Basics: Load Files & Run Code](https://learn.adafruit.com/micropython-basics-load-files-and-run-code.md)
- [Gmailbox](https://learn.adafruit.com/gmailbox.md)
- [CircuitPython Powered AT Hand-Raiser](https://learn.adafruit.com/at-hand-raiser.md)
- [MicroPython Displays: Drawing Shapes](https://learn.adafruit.com/micropython-displays-drawing-shapes.md)
- [CircuitPython Basics: Analog Inputs & Outputs](https://learn.adafruit.com/circuitpython-basics-analog-inputs-and-outputs.md)
- [Adafruit HUZZAH ESP8266 breakout](https://learn.adafruit.com/adafruit-huzzah-esp8266-breakout.md)
