# Multi-tasking with CircuitPython

## Overview

![](https://cdn-learn.adafruit.com/assets/assets/000/095/495/medium800thumb/feather_circuitpython_all_together_3.jpg?1602179598)

Once you've learned the basics of how to blink lights, move servos, and handle inputs, it often comes naturally to want make a larger project that does more than one thing -- more LEDs, more servos, and more buttons and other inputs.

One thing you'll quickly find is that as you add more things to your circuit and code, they are each delaying each other. So one blinking LED works fine, but when you add the second, their blinking patterns are always affecting each other. If you slow one down, the other slows as well.

If you add multiple servos, you might notice that you can't get them to move at the same time. One completes its full sweeping motion, and then the other completes its full sweep. They move sequentially, but never at the same time.&nbsp;

This guide will teach you a technique that you can use to manage multiple things happening at once in your CircuitPython project.

Info: 

## Parts
### Circuit Playground Bluefruit - Bluetooth® Low Energy

[Circuit Playground Bluefruit - Bluetooth® Low Energy](https://www.adafruit.com/product/4333)
 **Circuit Playground Bluefruit** is our third board in the Circuit Playground series, another step towards a perfect introduction to electronics and programming. We've taken the popular Circuit Playground Express and made it even better! Now the main chip is an nRF52840...

Out of Stock
[Buy Now](https://www.adafruit.com/product/4333)
[Related Guides to the Product](https://learn.adafruit.com/products/4333/guides)
![shot of a Black woman's neon-green manicured hand holding up a Circuit Playground Bluefruit glowing rainbow LEDs.](https://cdn-shop.adafruit.com/640x480/4333-11.jpg)

### Adafruit Feather M4 Express - Featuring ATSAMD51

[Adafruit Feather M4 Express - Featuring ATSAMD51](https://www.adafruit.com/product/3857)
It's what you've been waiting for, the Feather M4 Express featuring ATSAMD51. This Feather is fast like a swift, smart like an owl, strong like a ox-bird (it's half ox, half bird, OK?) This feather is powered by our new favorite chip, the **ATSAMD51J19** -&nbsp; with...

Out of Stock
[Buy Now](https://www.adafruit.com/product/3857)
[Related Guides to the Product](https://learn.adafruit.com/products/3857/guides)
![Angled shot of a Adafruit Feather M4 Express. ](https://cdn-shop.adafruit.com/640x480/3857-10.jpg)

### Adafruit Feather nRF52840 Sense

[Adafruit Feather nRF52840 Sense](https://www.adafruit.com/product/4516)
The **Adafruit Feather Bluefruit Sense** takes our popular [Feather nRF52840 Express](https://www.adafruit.com/product/4062) and adds a smorgasbord of sensors to make a great wireless sensor platform. This Feather microcontroller comes with Bluetooth® Low Energy and...

Out of Stock
[Buy Now](https://www.adafruit.com/product/4516)
[Related Guides to the Product](https://learn.adafruit.com/products/4516/guides)
![Angled shot of blue, rectangular, microcontroller.](https://cdn-shop.adafruit.com/640x480/4516-06.jpg)

### 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)
![A plastic storage box full of various electrical components.](https://cdn-shop.adafruit.com/640x480/2975-00.jpg)

### Micro servo

[Micro servo](https://www.adafruit.com/product/169)
Tiny little servo can rotate approximately 180 degrees (90 in each direction) and works just like the standard kinds you're used to but _smaller_. You can use any servo code, hardware, or library to control these servos. Good for beginners who want to make stuff move without...

Out of Stock
[Buy Now](https://www.adafruit.com/product/169)
[Related Guides to the Product](https://learn.adafruit.com/products/169/guides)
![Micro servo with three pin cable](https://cdn-shop.adafruit.com/640x480/169-06.jpg)

### Sub-micro Servo - SG51R

[Sub-micro Servo - SG51R](https://www.adafruit.com/product/2201)
This is just about the cutest, tiniest little micro servo we could find, even smaller than the 9-gram micro servos we love so much. &nbsp;It can rotate approximately 180 degrees (90 in each direction) and works just like the standard kind you're used to but&nbsp;_much smaller_....

Out of Stock
[Buy Now](https://www.adafruit.com/product/2201)
[Related Guides to the Product](https://learn.adafruit.com/products/2201/guides)
![Sub-micro Servo with three pin cable ](https://cdn-shop.adafruit.com/640x480/2201-01.jpg)

### USB cable - USB A to Micro-B

[USB cable - USB A to Micro-B](https://www.adafruit.com/product/592)
This here is your standard A to micro-B USB cable, for USB 1.1 or 2.0. Perfect for connecting a PC to your Metro, Feather, Raspberry Pi or other dev-board or microcontroller

Approximately 3 feet / 1 meter long

Out of Stock
[Buy Now](https://www.adafruit.com/product/592)
[Related Guides to the Product](https://learn.adafruit.com/products/592/guides)
![USB cable - USB A to Micro-B - 3 foot long](https://cdn-shop.adafruit.com/640x480/592-01.jpg)

# Multi-tasking with CircuitPython

## No Sleeping

## Blink

For many of us, the first program we see or run on a new platform is some variation of "Blink" to turn an LED on and off at some rate. It has become like the "Hello World" of microcontroller programming.

Here is a CircuitPython implementation:

```python
import time
import digitalio
import board

# Setup the LED pin.
led = digitalio.DigitalInOut(board.D13)
led.direction = digitalio.Direction.OUTPUT

while True:
    led.value = True
    time.sleep(0.5) # Wait until we want to turn LED on.
    led.value = False
    time.sleep(0.5) # Wait until we want to turn LED off.
```

This will turn the LED on and then wait, or in other words, `time.sleep()` for some time and then turn the LED back off. We can even use different values for the on and off times by changing the `time.sleep()` parameters.

## So what's the problem?

`time.sleep()` blocks the program while it is running. Nothing else can occur. In the basic blink example, this doesn't matter so much because we aren't trying to do anything else. But let's say we wanted to add a second LED and blink it at a different rate while still continuing to blink the first. Using `time.sleep()` will cause trouble because each LED will have no choice but to wait for the sleep calls that are blinking the other. Their blink rates won't ever be truly independent.

How can we work around this problem?

## Is it time yet?

So we know that sleeping until it's time to act is causing trouble, but what can we do to fix it? One possible solution is to change from sleeping to asking "is it time yet" over and over, just like an annoying sibling on a long car ride.&nbsp;

Our program already has a "main loop" that will execute over and over very fast, or at least it would if we allow it to by not taking up time with long-running blocking things like `time.sleep()`.&nbsp;

We can make use of `time.monotonic()` to check what time it is, then compare that against the last time we changed the LED to decide "is it time yet" to change the LED again.

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Multitasking_with_CircuitPython/code_blink_without_sleep/code.py

By avoiding the use of `time.sleep()`, we've made it so that our main loop can complete each iteration _very quickly._ Now we check each time through the loop whether it's time to change the LED state or not. To determine this, we check the current time against a variable storing the last time we acted, along with a duration variable.&nbsp;

Once it is time to act, we change the LED state and update the variable, storing the last time we acted.&nbsp;

By using multiple duration variables, we can achieve different lengths of time for the various states. In this case we have the LED staying on for twice as long as it is off — `0.5` seconds ON and `0.25` seconds OFF.

# Multi-tasking with CircuitPython

## Multiple LEDs

![](https://cdn-learn.adafruit.com/assets/assets/000/094/652/medium800thumb/circuitpython_multi-blink-feather.jpg?1599691427)

Okay, we've learned how to make our blink script without relying on `time.sleep()`, but if we only use one LED, then it hardly makes any difference to us really. Let's add some more LEDs into the mix so we can see the the major advantage of ditching the `time.sleep()` calls.

This script is made to run on a Feather M4 Express, Feather nRF52840, or Feather Bluefruit Sense. With minimal tweaking, it could be adjusted to work with the Metro M4 or ItsyBitsy M4 devices.

All of the pins and other information we need to manage the blinking schedule is packed into a list of dictionaries. This makes it easy for us to iterate over them and check each one, taking action as needed to turn LEDs ON or OFF.

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Multitasking_with_CircuitPython/code_multiple_leds/code.py

## Circuit Playground Bluefruit
![](https://cdn-learn.adafruit.com/assets/assets/000/094/653/medium800thumb/circuitpython_playground_multi_blink.jpg?1599696804)

In this script, we pack all of the blinking rules into a dictionary that we can iterate over to carry out the correct blink actions at the correct times and on the correct LEDs.&nbsp;

You can add more LEDs into the mix by adding new entries into the dictionary.

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Multitasking_with_CircuitPython/code_multiple_leds_cpb/code.py

If you want to do more advanced animations with NeoPixels, there is a library made especially for that check out this [NeoPixel LED Animation Guide](https://learn.adafruit.com/circuitpython-led-animations/) to learn all about it.&nbsp;

# Multi-tasking with CircuitPython

## Servos

Let's look at the most basic example from the [Servo guide](https://learn.adafruit.com/circuitpython-essentials/circuitpython-servo):

```python
import time
import board
import pulseio
from adafruit_motor import servo
 
# create a PWMOut object on Pin A2.
pwm = pwmio.PWMOut(board.A2, duty_cycle=2 ** 15, frequency=50)
 
# Create a servo object, my_servo.
my_servo = servo.Servo(pwm)
 
while True:
    for angle in range(0, 180, 5):  # 0 - 180 degrees, 5 degrees at a time.
        my_servo.angle = angle
        time.sleep(0.05)
    for angle in range(180, 0, -5): # 180 - 0 degrees, 5 degrees at a time.
        my_servo.angle = angle
        time.sleep(0.05)
```

![](https://cdn-learn.adafruit.com/assets/assets/000/094/949/medium800thumb/circuitpython_servo_running_smaller_2.jpg?1600736504)

This works fine for us if we only have one servo, and we don't have anything else that we want to happen at the same time. But once we add in another thing, we'd have the same trouble as before — `time.sleep()` delaying our other actions unintentionally.

In the next version we adopt the "is it time yet" approach in order to avoid the use of `time.sleep()`:

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Multitasking_with_CircuitPython/code_servo_without_sleep/code.py

This version also moves the configuration for the servo sweeping into a list of dictionaries so that additional servos with different sweeping effects can be added easily.

To add an additional servo, you would make a copy of the dictionary that is in `SERVO_LIST` and change any of the fields that we want to the new desired parameters:

```python
{
    "MAX_ANGLE": 90,
    "MIN_ANGLE": 45,
    "PREV_TIME": -1,
    "PIN": board.A2,
    "DELAY_BETWEEN": 0.03,
    "SERVO": None,
    "MOVE_BY": 5
}
```

`SERVO` and `PREV_TIME` should be left as their default values. The rest of the code will fill them in when needed.&nbsp;  
  
`MAX_ANGLE` and `MIN_ANGLE` are the degrees at which the servo will turn around to move the opposite direction.

` PIN` is the IO pin that the servo is connected to.

`DELAY_BETWEEN` is how long it will wait between each servo step. This is in seconds, and you likely want to keep it pretty small in most situations.&nbsp;

`MOVE_BY` is how many steps the servo will take each time it moves.&nbsp;

Here is an example of a list with two servos in it. You could continue adding more if you wanted.

```python
SERVO_LIST = [
    {
        "MAX_ANGLE": 180,
        "MIN_ANGLE": 0,
        "PREV_TIME": -1,
        "PIN": board.A1,
        "DELAY_BETWEEN": 0.05,
        "SERVO": None,
        "MOVE_BY": 5
    },
    {
        "MAX_ANGLE": 90,
        "MIN_ANGLE": 45,
        "PREV_TIME": -1,
        "PIN": board.A2,
        "DELAY_BETWEEN": 0.03,
        "SERVO": None,
        "MOVE_BY": 5
    }
]
```

# Multi-tasking with CircuitPython

## Buttons

Another place that we sometimes see `time.sleep()` used is for a sort of minimal "debouncing" effect with push buttons. Some code for that might look like this:

```python
import time
import board
from digitalio import DigitalInOut, Direction, Pull

btn = DigitalInOut(board.SWITCH)
btn.direction = Direction.INPUT
btn.pull = Pull.UP

while True:
    if not btn.value:
        print("BTN is down")
    else:
        #print("BTN is up")
        pass

    time.sleep(0.1) # sleep for debounce
```

In this situation, the `time.sleep()` aims to reduce the speed at which the button will continue registering more actions if the button is held down.&nbsp;  
  
Instead, we could store a variable containing the state of the button from the previous iteration, and then compare against it each time. That way, the button will only trigger a single action when it's pressed, or when it's released if we want that instead.

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Multitasking_with_CircuitPython/code_buttons_without_sleep/code.py

Now that this code no longer relies on `time.sleep()`, it can play nicely without interrupting LED animations, servos, and other tasks that your Circuit Python device is handling. If we do it this way, we get a single action when the button is pressed, and another single action when the button is released.

This process of looking for for the change in button state is known as debouncing, and there is a CircuitPython library created&nbsp; to help make it easier called `adafruit_debouncer`. If you stick to using this library, you won't have to worry about the debouncing logic interfering with other tasks. This guide covers its usage: [Python Debouncer Library for Buttons and Sensors](https://learn.adafruit.com/debouncer-library-python-circuitpython-buttons-sensors/ "Python Debouncer Library for Buttons and Sensors")

# Multi-tasking with CircuitPython

## All Together Now

![](https://cdn-learn.adafruit.com/assets/assets/000/095/021/medium800thumb/circuitpython_all_together_3.jpg?1600911836)

This example brings together LEDs, button input, and a servo all operating at the same time without interfering with one another.

When you press the button it will switch to blinking the opposite pair of LEDs by swapping the dictionaries into and out of the `BLINK_LIST` using the `pop()` and `append()` functions.

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Multitasking_with_CircuitPython/code_all_together/code.py


## Featured Products

### Circuit Playground Bluefruit - Bluetooth® Low Energy

[Circuit Playground Bluefruit - Bluetooth® Low Energy](https://www.adafruit.com/product/4333)
 **Circuit Playground Bluefruit** is our third board in the Circuit Playground series, another step towards a perfect introduction to electronics and programming. We've taken the popular Circuit Playground Express and made it even better! Now the main chip is an nRF52840...

Out of Stock
[Buy Now](https://www.adafruit.com/product/4333)
[Related Guides to the Product](https://learn.adafruit.com/products/4333/guides)
### Adafruit Feather nRF52840 Express

[Adafruit Feather nRF52840 Express](https://www.adafruit.com/product/4062)
The **Adafruit Feather nRF52840 Express** is the new Feather family member with Bluetooth® Low Energy and _native USB support_ featuring the nRF52840!&nbsp; It's our take on an 'all-in-one' Arduino-compatible + Bluetooth® Low Energy with built-in USB...

Out of Stock
[Buy Now](https://www.adafruit.com/product/4062)
[Related Guides to the Product](https://learn.adafruit.com/products/4062/guides)
### Adafruit Feather M4 Express - Featuring ATSAMD51

[Adafruit Feather M4 Express - Featuring ATSAMD51](https://www.adafruit.com/product/3857)
It's what you've been waiting for, the Feather M4 Express featuring ATSAMD51. This Feather is fast like a swift, smart like an owl, strong like a ox-bird (it's half ox, half bird, OK?) This feather is powered by our new favorite chip, the **ATSAMD51J19** -&nbsp; with...

Out of Stock
[Buy Now](https://www.adafruit.com/product/3857)
[Related Guides to the Product](https://learn.adafruit.com/products/3857/guides)
### Adafruit ItsyBitsy M4 Express featuring ATSAMD51

[Adafruit ItsyBitsy M4 Express featuring ATSAMD51](https://www.adafruit.com/product/3800)
What's smaller than a Feather but larger than a Trinket? It's an **Adafruit ItsyBitsy M4 Express** featuring the **Microchip ATSAMD51**! Small, powerful, with a ultra fast ATSAMD51 Cortex M4 processor running at 120 MHz - this microcontroller board is perfect...

In Stock
[Buy Now](https://www.adafruit.com/product/3800)
[Related Guides to the Product](https://learn.adafruit.com/products/3800/guides)
### 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)
### Micro servo

[Micro servo](https://www.adafruit.com/product/169)
Tiny little servo can rotate approximately 180 degrees (90 in each direction) and works just like the standard kinds you're used to but _smaller_. You can use any servo code, hardware, or library to control these servos. Good for beginners who want to make stuff move without...

Out of Stock
[Buy Now](https://www.adafruit.com/product/169)
[Related Guides to the Product](https://learn.adafruit.com/products/169/guides)
### USB cable - USB A to Micro-B

[USB cable - USB A to Micro-B](https://www.adafruit.com/product/592)
This here is your standard A to micro-B USB cable, for USB 1.1 or 2.0. Perfect for connecting a PC to your Metro, Feather, Raspberry Pi or other dev-board or microcontroller

Approximately 3 feet / 1 meter long

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

## Related Guides

- [Adafruit Feather M4 Express](https://learn.adafruit.com/adafruit-feather-m4-express-atsamd51.md)
- [Introducing the Adafruit nRF52840 Feather](https://learn.adafruit.com/introducing-the-adafruit-nrf52840-feather.md)
- [Adafruit Circuit Playground Bluefruit](https://learn.adafruit.com/adafruit-circuit-playground-bluefruit.md)
- [Introducing Adafruit Feather](https://learn.adafruit.com/adafruit-feather.md)
- [LED Reactive Light-Up Hockey Puck in MakeCode](https://learn.adafruit.com/led-hockey-puck.md)
- [Lego Neon NeoPixel Sign with CircuitPython](https://learn.adafruit.com/lego-neon-sign.md)
- [MIDI Laser Harp with Time of Flight Distance Sensors](https://learn.adafruit.com/midi-laser-harp-time-of-flight-sensors.md)
- [Sketch Drawing Toy with CircuitPython](https://learn.adafruit.com/sketch-drawing-toy.md)
- [LED Protest Sign](https://learn.adafruit.com/led-protest-sign.md)
- [Touch Deck: DIY Customizable TFT Control Pad](https://learn.adafruit.com/touch-deck-diy-tft-customized-control-pad.md)
- [ Memory-saving tips for CircuitPython](https://learn.adafruit.com/memory-saving-tips-for-circuitpython.md)
- [PyLeap Tone Piano for Circuit Playground Bluefruit](https://learn.adafruit.com/pyleap-tone-piano-for-cpb.md)
- [CircuitPython TFT Candy Hearts](https://learn.adafruit.com/circuit-python-tft-gizmo-candy-hearts.md)
- [Adafruit VCNL4040 Proximity Sensor](https://learn.adafruit.com/adafruit-vcnl4040-proximity-sensor.md)
- [Adding a WiFi Co-Processor to CircuitPython](https://learn.adafruit.com/adding-a-wifi-co-processor-to-circuitpython-esp8266-esp32.md)
- [New Years Eve Ball Drop](https://learn.adafruit.com/new-years-eve-ball-drop.md)
- [Which CircuitPython Board is Right for You?](https://learn.adafruit.com/choose-your-circuitpython-board.md)
- [How to train new TensorFlow Lite micro speech models](https://learn.adafruit.com/how-to-train-new-tensorflow-lite-micro-speech-models.md)
