# Grand Central USB MIDI Controller in CircuitPython

## Overview

https://www.youtube.com/watch?v=L39JoeQulvw

![](https://cdn-learn.adafruit.com/assets/assets/000/069/616/medium800/micropython___circuitpython_IMG_3571_2k.jpg?1547842045)

You can build your own **16-knob USB MIDI CC controller**! Music software is great, but don't you miss having real knobs to turn? Harness the massive amounts of **Grand Central M4 Express** I/O by using **CircuitPython** to create a MIDI controller of your dreams to dial in sequencer values, DJ software mixes and effects, and any other value you like in your DAW, synthesizer, sequencer, or DJ tools!

The Grand Central can send USB MIDI messages, such as Note On and Note Off, as well as CC (continuous controller) numbers and values. This means you can adjust virtual knobs in your music software using real, physical knobs!

In this guide, we'll wire up 16 potentiometers and program the Grand Central MIDI Controller to do your knobby bidding!

Primary: 

## Parts
### Part: Adafruit Grand Central M4 Express
quantity: 1
featuring the SAMD51
[Adafruit Grand Central M4 Express](https://www.adafruit.com/product/4064)

### Part: Potentiometer with Built In Knob
quantity: 16
10K ohm
[Potentiometer with Built In Knob](https://www.adafruit.com/product/4133)

Alternatively, you can use these trim pots, but they are harder to turn:

### Part: Breadboard trim potentiometer
quantity: 16
10K Ohm
[Breadboard trim potentiometer](https://www.adafruit.com/product/356)

### Part: USB Patterned Fabric Cable 
quantity: 1
A/MicroB - 3ft
[USB Patterned Fabric Cable ](https://www.adafruit.com/product/2008)

### Part: Premium Male/Male Jumper Wires
quantity: 1
40 x 6" (150mm)
[Premium Male/Male Jumper Wires](https://www.adafruit.com/product/758)

### Part: Full sized breadboard
quantity: 1
Gluten free
[Full sized breadboard](https://www.adafruit.com/product/239)

## Optional
### Part: Mega protoshield
quantity: 1
for Grand Central or Arduino Mega
[Mega protoshield](https://www.adafruit.com/product/192)

### Part: iOS Lightning to USB OTG Cable
quantity: 1
Adapt!
[iOS Lightning to USB OTG Cable](https://www.adafruit.com/product/3940)

### Part: Adafruit Perma-Proto Full-sized Breadboard
quantity: 1
Single
[Adafruit Perma-Proto Full-sized Breadboard](https://www.adafruit.com/product/1606)

### Part: Hook-up Wire Spool Set - 22AWG Solid Core
quantity: 1
10 x 25ft
[Hook-up Wire Spool Set - 22AWG Solid Core](https://www.adafruit.com/product/3174)

For the MEGA proto shield version, I used some vertical PC mount 9mm 100k linear pots with 6mm knobless shafts. [You can them here](https://www.allelectronics.com/item/pt-b104/100k-linear-taper-pot-pc-mount/1.html).

One note, I cut off their mounting tabs for the tight fit.

Info: 

# Grand Central USB MIDI Controller in CircuitPython

## Build the MIDI CC Controller

![](https://cdn-learn.adafruit.com/assets/assets/000/069/464/medium800/micropython___circuitpython_Grand_Central_MIDI_CC_fritz.png?1547661159)

Here's how you'll wire up the board. It's simple, really, it just needs to be repeated a bunch of times!

To read a potentiometer, we'll connect the left leg to ground and the right leg to 3.3V. The middle leg is connected to the pot's wiper, which is a variable resistor. The entire arrangement acts as a variable voltage divider.

By connecting the middle leg to an analog input pin on the Grand Central, we can read the varying voltage level.

![](https://cdn-learn.adafruit.com/assets/assets/000/069/617/medium800/micropython___circuitpython_IMG_3561_2k.jpg?1547842086)

First add a potentiometer to the breadboard with the legs at the bottom of the switch.

&nbsp;

Wire a **black** jumper from the **left leg** to **ground**.

&nbsp;

Wire a **red** jumper from the **right leg** to **power**.

&nbsp;

This leaves the **center leg** to be wired to the **an analog input** on the Grand central.

&nbsp;

Repeat this for a total of eight pots on the top half of the breadboard.

![micropython___circuitpython_IMG_3562_2k.jpg](https://cdn-learn.adafruit.com/assets/assets/000/069/618/medium640/micropython___circuitpython_IMG_3562_2k.jpg?1547842101)

![micropython___circuitpython_IMG_3563_2k.jpg](https://cdn-learn.adafruit.com/assets/assets/000/069/619/medium640/micropython___circuitpython_IMG_3563_2k.jpg?1547842201)

![micropython___circuitpython_IMG_3564_2k.jpg](https://cdn-learn.adafruit.com/assets/assets/000/069/620/medium640/micropython___circuitpython_IMG_3564_2k.jpg?1547842250)

![micropython___circuitpython_IMG_3566_2k.jpg](https://cdn-learn.adafruit.com/assets/assets/000/069/621/medium640/micropython___circuitpython_IMG_3566_2k.jpg?1547842261)

![micropython___circuitpython_IMG_3567_2k.jpg](https://cdn-learn.adafruit.com/assets/assets/000/069/622/medium640/micropython___circuitpython_IMG_3567_2k.jpg?1547842269)

![micropython___circuitpython_IMG_3568_2k.jpg](https://cdn-learn.adafruit.com/assets/assets/000/069/623/medium640/micropython___circuitpython_IMG_3568_2k.jpg?1547842299)

Now, you can wire the center legs of each pot to the first eight analog inputs on the Grand Central. You will also run a black wire from the breadboard ground rail to Grand Central **GND** pin and a red wire from breadboard power rail to Grand Central **3.3V** pin. **Do not use** 5V **!**

Warning: 

![](https://cdn-learn.adafruit.com/assets/assets/000/069/630/medium800/micropython___circuitpython_IMG_3569_2k.jpg?1547842353)

Be sure to jumper the ground and power rails on the lower half of the breadboard to their respective rails on the top half, then add the other eight pots as shown here.

![](https://cdn-learn.adafruit.com/assets/assets/000/069/635/medium800/micropython___circuitpython_IMG_3571_2k.jpg?1547842431)

You're ready now to prep the board and code it for use!

## Go Beyond the Breadboard

For a more advanced build, you can go beyond the breadboard and onto a Perma Proto board, or even a [MEGA Shield](https://www.adafruit.com/product/192) as seen here!

![](https://cdn-learn.adafruit.com/assets/assets/000/069/638/medium800/micropython___circuitpython_IMG_3553_2k.jpg?1547842571)

![](https://cdn-learn.adafruit.com/assets/assets/000/069/639/medium800/micropython___circuitpython_IMG_3548_2k.jpg?1547842581)

# Grand Central USB MIDI Controller in CircuitPython

## Code USB MIDI in CircuitPython

## Prepare the Grand Central

We'll be using CircuitPython for this project. Are you new to using CircuitPython? No worries,&nbsp;[there is a full getting started guide here](https://learn.adafruit.com/welcome-to-circuitpython).

Adafruit suggests using the Mu editor to edit your code and have an interactive REPL in CircuitPython.&nbsp;[You can learn about Mu and its installation in this tutorial](https://learn.adafruit.com/welcome-to-circuitpython/installing-mu-editor). Mu 1.0.2 has support for detecting the Adafruit Grand Central as a valid board - if you have an older version, please upgrade.

[Follow this guide](https://learn.adafruit.com/welcome-to-circuitpython/installing-circuitpython) for instructions on installing the latest release version of CircuitPython for the Grand Central.

You'll also need to add the following libraries for this project. [Follow this guide](https://learn.adafruit.com/adafruit-hallowing/circuitpython-libraries) on adding libraries. The ones you'll need are:

- **neopixel**
- **simpleio**
- **adafruit\_midi**

Download the latest adafruit-circuitpython-bundle .zip file as instructed in the guide linked below. Unzip the file and drag those libraries to the **lib** folder on your Grand Central M4 **CIRCUITPY** drive (create the **lib** directory if it does not already exist).

![directory](https://adafruit.github.io/Adafruit_Learning_System_Guides/Grand_Central_MIDI_Knobs.png )

[Adding CircuitPython Libraries](https://learn.adafruit.com/welcome-to-circuitpython/circuitpython-libraries)
## Code

You can now upload the code to your Grand Central so it will read the pots and send USB MIDI commands.

Here is the code we'll use. Copy it and then paste it into the Mu editor. Save it to your Grand Central M4 as **code.py**

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

Before we test it out, let's have a closer look at how it works.

## Using Adafruit USB MIDI

The **adafruit\_midi** library code for CircuitPython allows you to easily send the most commonly used MIDI messages.

### Create the MIDI Object

The MIDI object can be instantiated this way:

`usb_midi = adafruit_midi.MIDI(midi_out=usb_midi.ports[1], out_channel=USB_MIDI_channel - 1)`

This allows us to refer to it in the code with the nice, short name `midi` And we're also using the `out_channel` argument (which is zero indexed) to set the outgoing MIDI channel through which messages will be sent -- in this case, MIDI channel 1. The possible range is 0-15, which correlates to MIDI channels 1-16.

Then, to send messages, we can use four types:

- Note On
- Note Off
- Control Chage (a.k.a., Continuous Controller or CC)
- Pitch bend

### Note On

`note_on` is used to send a MIDI Note On message. First argument is the note number, `0-127`. Second argument is the velocity, `0-127`. Typical 88-key piano note range is 36-108 which correlate to pitches C2 to C8.

Example:

- `usb_midi.send(NoteOn(60, 64))`sends a MIDI message of Note On number **60** (C3 on the keyboard) at a velocity of **64**

### Note Off

`note_off` is used to send a MIDI Note Off message. First argument is the note number, `0-127`. Second argument is the velocity, `0-127`.

Example:

- `usb_midi.send(NoteOff(60, 64))`sends a MIDI message of Note Off number **60** , at a velocity of **64**. (The velocity doesn't actually matter in most cases, but can be used for interesting effects with harpsichords and other plucked instruments.)

### Pitch Bend

`pitch_bend` sends a MIDI Pitch Wheel message. Range is `0-16383`. A value of 8192 equates to no pitch bend. A value \> `8192` is an upward bend, while a value \< `8192` is a negative pitch bend.

Example:

- `usb_midi.send(PitchBend(10000))` sends and increasing pitch bend, in this case a value of `10000`

### Control Change (CC)

`control_change` sends a MIDI CC ('control change' or 'continuous controller’) message. First argument is the controller number, `0-15`. Second argument is the control value, `0-127`.&nbsp;

Example:

- `usb_midi.send(ControlChange(4, 100))`sends a MIDI control change on control number `4` with a value of `100`.

[This is a good resource](https://ccrma.stanford.edu/~craig/articles/linuxmidi/misc/essenmidi.html) for greater details on the MIDI protocol.

Each MIDI channel can use up to sixteen CC controller numbers. In software, these are usually assignable to anything you like. Here's a table of typical uses, particularly on hardware synthesizers and other MIDI gear:

- 0 Bank Select
- 1 Modulation Wheel
- 2 Breath Controller
- 3 Undefined
- 4 Foot Controller
- 5 Portamento time
- 6 Data Entry Most Significant Bits
- 7 Volume
- 8 Balance
- 9 Undefined
- 10 Pan
- 11 Expression
- 12 Effect Controller 1
- 13 Effect Controller 2
- 14 Undefined
- 15 Undefined

The good news is, you can pretty much ignore these crusty old standards in your software and map any knob to any function! So, once you're inside your favorite software, you'll pick a software knob, enter MIDI learn mode, and assign one of your sixteen Grand Central knobs to do the job!

## Code Walkthrough
## Libraries

First, we'll import the libraries:

```import timeimport boardimport busiofrom simpleio import map_rangefrom analogio import AnalogInfrom digitalio import DigitalInOut, Directionimport usb_midiimport adafruit_midifrom adafruit_midi.control_change import ControlChange`

## MIDI Instance

### USB MIDI

Then, we'll define the adafruit\_midi instance and tell it which MIDI channel to use. MIDI channel number 1 is a good default, unless you have something else plugged into your computer already using it.

`usb_midi = adafruit_midi.MIDI(midi_out=usb_midi.ports[1], out_channel=USB_MIDI_channel - 1)` (Remember, this is zero indexed, so a 1 is subtracted)

### Classic MIDI

With a similar setup, we'll use the TX/RX UART serial port with a TRS jack or DIN-5 connector to send classic MIDI:

`uart = busio.UART(board.TX, board.RX, baudrate=31250, timeout=0.001)  # initialize UART`  
`classic_midi = adafruit_midi.MIDI(`  
`    midi_out=uart, midi_in=uart, out_channel=CLASSIC_MIDI_channel - 1, debug=False`  
`)`

## Knob Setup

Next, we'll set up the knob inputs. We'll use a variable to define the number of knobs used, which makes it simple to go with fewer than the max of 16 if needed.

`knob_count = 16`

We'll then define the list of knobs with easy to use names that are actually pointing at the AnalogIn pins. We could do something like this 16 times:

`knob0 = AnalogIn(board.A0)`

but it's neater to wrap it up into a loop like this:

```auto
knob = []
for k in range(knob_count):
    knobs = AnalogIn(getattr(board, "A{}".format(k)))
    knob.append(knobs)
```

## CC Ranges

While the MIDI CC value range runs from 0 to 127, in some cases we'll want to output only a subset of that range when we turn a knob fully. For example, 0 to 127 is great if you're controlling a mixer knob, but it's too huge of a range if you're sending out chromatic pitch values. Typical 88-key MIDI keyboards range from 21 (a very low A0) to 108 (a super high C8).

When using a knob for sequencing melodies, you'll probably want an even tighter range, such as 36 (C2) to 84 (B5) or smaller.

So, we will create a list of ranges that can be adjusted in code per knob:

```auto
cc_range = [
    (36, 84),  # knob 0: C2 to B5: 49-note keyboard
    (36, 84),  # knob 1
    (36, 84),  # knob 2
    (36, 84),  # knob 3
    (36, 84),  # knob 4
    (36, 84),  # knob 5
    (36, 84),  # knob 6
    (36, 84),  # knob 7
    (0, 127),  # knob 8: 0 to 127: full range MIDI CC/control voltage for VCV Rack
    (0, 127),  # knob 9
    (0, 127),  # knob 10
    (0, 127),  # knob 11
    (0, 127),  # knob 12
    (0, 127),  # knob 13
    (0, 127),  # knob 14
    (0, 127)   # knob 15
]
```

## CC Value

We will create a variable list to store the value of each knob:

```auto
cc_value = []
for c in range(knob_count):
    cc_value.append((0,0))
```

## Hysteresis

This helper function, created by Jan Goolsbey, is used to reduce value jitter when a potentiometer is right on the edge between two values:

```auto
def range_index(ctl, ctrl_max, old_idx, offset):
    if (ctl + offset > 65535) or (ctl + offset < 0):
        offset = 0
    idx = int(map_range((ctl + offset) & 0xFF00, 1200, 65500, 0, ctrl_max))
    if idx != old_idx:  # if index changed, adjust hysteresis offset and set flag
        # offset is 25% of the control slice (65536/ctrl_max)
        offset = int(0.25 * sign(idx - old_idx) * (65535 / ctrl_max))  # edit 0.25 to adjust slices
    return idx, offset
```

![](https://cdn-learn.adafruit.com/assets/assets/000/069/592/medium800/micropython___circuitpython_hysteresis_helper_diagram.png?1547789685)

The next function is a helper used along with the range\_index function to determine the direction of the potentiometer's movement:

```auto
def sign(x):  # determine the sign of x
    if x >= 0:
        return 1
    else:
        return -1
```

## Main Loop

Now, in the main loop of the program we'll do these things:

- Read the knobs
- Adjust their values to conform to the range table and reduce jitter
- Send their values out as the properly formed USB MIDI messages

Here is the loop that checks and adjust the knob values:

```auto
while True:
    # read all the knob values
    for i in range(knob_count):
        cc_value[i] = range_index(knob[i].value,
                                  (cc_range[i][1] - cc_range[i][0] + 1),
                                  cc_value[i][0], cc_value[i][1])
```

## MIDI Message Send

And finally, the thing we've been waiting for -- sending the message, but only if it has changed since the last check.

```python
for i in range(knob_count):
        cc_value[i] = range_index(
            knob[i].value,
            (cc_range[i][1] - cc_range[i][0] + 1),
            cc_value[i][0],
            cc_value[i][1],
        )
        if cc_value[i] != last_cc_value[i]:  # only send if it changed
            # Form a MIDI CC message and send it:
            usb_midi.send(ControlChange(cc_number[i], cc_value[i][0] + cc_range[i][0]))
            classic_midi.send(
                ControlChange(cc_number[i], cc_value[i][0] + cc_range[i][0])
            )
            last_cc_value[i] = cc_value[i]
            led.value = True
```

## In Use

Now, it's time to use your Grand Central USB MIDI Knob Controller! With it plugged into your computer over USB, launch a DAW, software synthesizer/sequencer, or DJ tool. Here are some examples of free, open source synths for Linux, Windows, and mac os: &nbsp;

- [Helm](https://tytel.org/helm/) &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;
- [VCV Rack](https://vcvrack.com/)
- [Pure Data](https://puredata.info/)
- [Ardour](https://ardour.org/)

[This page](https://learn.adafruit.com/trellis-m4-midi-keypad-and-tilt-controller/play-music-with-helm-synthesizer) shows more details on using a MIDI controller with Helm.

![](https://cdn-learn.adafruit.com/assets/assets/000/069/605/medium800/micropython___circuitpython_helm_gcCC.png?1547827584)

## MIDI Monitor

You can use this [handy Chrome browser MIDI Monitor web app](https://www.midimonitor.com/#) to simply read the values of your Grand Central controller.

![](https://cdn-learn.adafruit.com/assets/assets/000/069/606/medium800/micropython___circuitpython_midimonChrome.png?1547827675)

https://www.youtube.com/watch?v=6p1Hm9aAfOg

## Rack Patch

This is an example of a patch made in VCV Rack, the open source modular software synthesizer:

![](https://cdn-learn.adafruit.com/assets/assets/000/069/607/medium800/micropython___circuitpython_rack_GC_patch.png?1547830407)

The module in the upper left corner, MIDI-CC, is used to connect the Grand Central MIDI Knob controller to the rest of the modules. You can see 16 patch cable running from it to an 8-step pitch sequencer, as well as various other modules to control the envelope and filter of the sound. All with your real, physical knobs!

## Get Mobile
The Grand Central USB MIDI Knob Controller also works great for controlling many iOS apps that have tiny virtual knobs, for example [AudioKit Synth One](https://audiokitpro.com/synth/) (iPad only).

You'll need to check if your app supports MIDI controller assignments and us an [OTG cable](https://www.adafruit.com/product/3940) to plug in the Grand Central.

Of course, you can also use the Grand Central with Ableton Live, Propellerhead Reason, FL Studio, Logic, Traktor, Max/MSP, and other professional apps!


## Featured Products

### Adafruit Grand Central M4 Express featuring the SAMD51

[Adafruit Grand Central M4 Express featuring the SAMD51](https://www.adafruit.com/product/4064)
Are you ready? Really ready? Cause here comes the **Adafruit Grand Central** featuring the **Microchip ATSAMD51**. This dev board is so big, it's not named after a Metro train, it's a whole freakin' _station_!

This board is like a freight...

In Stock
[Buy Now](https://www.adafruit.com/product/4064)
[Related Guides to the Product](https://learn.adafruit.com/products/4064/guides)
### Potentiometer with Built In Knob - 10K ohm

[Potentiometer with Built In Knob - 10K ohm](https://www.adafruit.com/product/4133)
_Oh say can you see_  
_By the knob's early light..._

Sorry - we thought that was clever. &nbsp;And while it wasn't really, this potentiometer definitely is! We've seen these in miniature synthesizers. They're bigger than a trim-pot but smaller than a...

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

[Breadboard trim potentiometer](https://www.adafruit.com/product/356)
These are our favorite trim pots, perfect for breadboarding and prototyping. They have a long grippy adjustment knob and with 0.1" spacing, they plug into breadboards or perfboards with ease.

This is the same pot that comes with our character LCDs and tutorial...

In Stock
[Buy Now](https://www.adafruit.com/product/356)
[Related Guides to the Product](https://learn.adafruit.com/products/356/guides)
### Full Sized Premium Breadboard - 830 Tie Points

[Full Sized Premium Breadboard - 830 Tie Points](https://www.adafruit.com/product/239)
This is a 'full-size' premium quality breadboard, 830 tie points. Good for small and medium projects. It's 2.2" x 7" (5.5 cm x 17 cm) with a standard double-strip in the middle and two power rails on both sides. You can pull the power rails off easily to make the...

In Stock
[Buy Now](https://www.adafruit.com/product/239)
[Related Guides to the Product](https://learn.adafruit.com/products/239/guides)
### Mega protoshield for Arduino

[Mega protoshield for Arduino](https://www.adafruit.com/product/192)
This is an extra large proto-shield, specifically designed for the Mega! It comes with PCB, two buttons and a full set of stacking headers. You can stack this shield easily since it comes with extra long female headers  
  
The kit includes:  
&nbsp;

- 1 x MEGAshield...

No Longer Stocked
[Buy Now](https://www.adafruit.com/product/192)
[Related Guides to the Product](https://learn.adafruit.com/products/192/guides)
### USB Patterned Fabric Cable - A/MicroB

[USB Patterned Fabric Cable - A/MicroB](https://www.adafruit.com/product/2008)
Oooh it's so soft! And that beautiful&nbsp;pattern! If you have to have visible cables&nbsp;then you might as well have the nicest fabric bound cable with a eye-catching snake-like pattern. &nbsp;That's why we now carry this standard A to micro-B USB cable&nbsp;for USB 1.1 or 2.0....

No Longer Stocked
[Buy Now](https://www.adafruit.com/product/2008)
[Related Guides to the Product](https://learn.adafruit.com/products/2008/guides)
### Hook-up Wire Spool Set - 22AWG Solid Core - 10 x 25ft

[Hook-up Wire Spool Set - 22AWG Solid Core - 10 x 25ft](https://www.adafruit.com/product/3174)
This is a box of **ten** &nbsp;25ft&nbsp;spools of **solid-core** wire. The wire is easy to solder to, and when bent it keeps its shape pretty well. We like to have a few spools of this stuff around which is why this set is quite nice! We suggest picking up some wire...

Out of Stock
[Buy Now](https://www.adafruit.com/product/3174)
[Related Guides to the Product](https://learn.adafruit.com/products/3174/guides)
### Premium Male/Male Jumper Wires - 40 x 6" (150mm)

[Premium Male/Male Jumper Wires - 40 x 6" (150mm)](https://www.adafruit.com/product/758)
Handy for making wire harnesses or jumpering between headers on PCB's. These premium jumper wires are 6" (150mm) long and come in a 'strip' of 40 (4 pieces of each of ten rainbow colors). They have 0.1" male header contacts on either end and fit cleanly next to each other...

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

## Related Guides

- [Introducing the Adafruit Grand Central M4 Express](https://learn.adafruit.com/adafruit-grand-central.md)
- [Breadboards for Beginners](https://learn.adafruit.com/breadboards-for-beginners.md)
- [CircuitPython 101: State Machines, Two Ways](https://learn.adafruit.com/circuitpython-101-state-machines.md)
- [Robotic Xylophone with Adafruit Grand Central](https://learn.adafruit.com/robotic-xylophone-with-circuit-python.md)
- [Using Python on Windows 10](https://learn.adafruit.com/using-python-on-windows-10.md)
- [Currying in CircuitPython](https://learn.adafruit.com/partials-in-circuitpython.md)
- [Adafruit OV5640 Camera Breakouts](https://learn.adafruit.com/adafruit-ov5640-camera-breakout.md)
- [CircuitScheme - Lisp on CircuitPython](https://learn.adafruit.com/scheme-in-circuitpython.md)
- [Adafruit OV7670 Camera Library For SAMD51 Processors](https://learn.adafruit.com/adafruit-ov7670-camera-library-samd51.md)
- [A Z80 CP/M emulator for the SAMD51](https://learn.adafruit.com/z80-cpm-emulator-for-the-samd51-grand-central.md)
- [A CLI in CircuitPython](https://learn.adafruit.com/a-cli-in-circuitpython.md)
- [Grand Central Soundboard in Ten Minutes](https://learn.adafruit.com/grand-central-soundboard-in-ten-minutes.md)
- [How to Choose a Microcontroller](https://learn.adafruit.com/how-to-choose-a-microcontroller.md)
- [Use circup to easily keep your CircuitPython libraries up to date](https://learn.adafruit.com/keep-your-circuitpython-libraries-on-devices-up-to-date-with-circup.md)
- [Customizing USB Devices in CircuitPython](https://learn.adafruit.com/customizing-usb-devices-in-circuitpython.md)
