Raspberry Pi Pico I2C MIDI Interface

I thought it was time to see if I could add a Raspberry Pi Pico to my Arduino I2C MIDI setup.  This is the first step to getting them talking MIDI over I2C using Circuitpython.

  • In part 1, I’m testing the concept of a Pico I2C MIDI interface.
  • In part 2, I wrote an I2C MIDI “driver” for the Adafruit MIDI library.
  • In part 3, I looked at measuring the latency of the links.
  • In part 4, I’m talking to eight Arduino’s!

Warning! I strongly recommend using old or second hand equipment for your experiments.  I am not responsible for any damage to expensive instruments!

These are the key tutorials for the main concepts used in this project:

If you are new to microcontrollers, see the Getting Started pages.

Parts list

  • Arduino Uno, Nano, or similar
  • Raspberry Pi Pico
  • 3.3V to 5V level shifter
  • 2x 10kΩ resistors
  • Optional: old 8Ω loudspeaker
  • Optional: 220Ω resistor (for the loudspeaker)

The Circuit

RaspberryPiPicoI2CMIDITest_bb

The Pico and the Arduino need to have their I2C bus linked up.  But the Pico runs on 3.3V logic and the Arduino on 5V.  Whilst you can drive 3.3V into a 5V input, you can’t go the other way without damaging your input, so we need to use a level shifter which takes a low (3.3V) voltage on one side and a high (5V) voltage on the other.

So this requires the following connections:

  • Pico pin 16 (GP12) to LV1; HV1 to Arduino A4 (SDA)
  • Pico pin 17 (GP13) to LV2; HV2 to Arduino A5 (CLK)
  • Pico VBUS (5V) to HV
  • Pico 3V3_OUT to LV
  • GND to GND

Note that it is also necessary to use two resistors to PULL the I2C bus HIGH on the Pico side.  This involves connected a 10kΩ resistor between the Pico pins being used for I2C and the 3V3 line.  Many I2C Peripherals have pullup resistors built in, but in this case I’m just connecting the Pico directly to the level shifter, so this has to be added explicitly.

The Arduino which is act as the MIDI receiver can optionally have a loudspeaker connected to D8 via a 220Ω resistor.

Both boards need power, e.g. over their USB connections.

The Code

The Arduino is running the I2CMIDIReceive example from my I2CMIDI library, so it will act as a PERIPHERAL on I2C address 0x40.

Ideally I want to get to the point where I have an I2C interface to the Adafruit MIDI library for CircuitPython, but I’m not there yet.  For this first test, I’m just using I2C directly to write MIDI data out over the bus, acting as the I2C CONTROLLER.

By the way, to ensure that the level shifting seems to be working ok, it is worth running the “i2cscan” example code from the Adafruit CircuitPython I2C tutorial.  Note that for this to work though, the line “i2c = board.I2C()” has to be changed to use busio as mentioned in the comments.  To run this on the Pico for my setup, using pins 16/17 (GP12/13) therefore, it needs the following:

import busio
i2c = busio.I2C(board.GP13, board.GP12)

I’ve created two simple functions, one for NoteOn and one for NoteOff.  These both have to do the following:

Grab the I2C bus ready to start writing out to the PERIPHERAL
Format a MIDI message (NoteOn or NoteOff)
Write the three bytes of the MIDI message out to the bus
Release the I2C bus

Then I’m just running an infinite loop sending out a MIDI NoteOn for note 60 (middle C – one of the notes that the I2CMIDIReceive example “knows” how to “play”), followed by a NoteOff shortly afterwards.

The entire test code is shown below.

import time
import board
import busio

addr = 0x40
i2c = busio.I2C(board.GP13, board.GP12)

def midiNoteOn (c, n, v):
    while not i2c.try_lock():
        pass
    try:
        buf = bytes([0x90|(c-1), n, v])
        i2c.writeto(addr, buf)
    finally:
        i2c.unlock()

def midiNoteOff (c, n, v):
    while not i2c.try_lock():
        pass
    try:
        buf = bytes([0x80|(c-1), n, v])
        i2c.writeto(addr, buf)
    finally:
        i2c.unlock()

while True:
    midiNoteOn (1, 60, 64)
    time.sleep(.2)
    midiNoteOff (1, 60, 0)
    time.sleep(.8)

This is pretty much the simplest example I could think of just to test the idea.

IMG_5703

Closing Thoughts

Phase one of I2C MIDI on the Pico appears complete!

The next step is to create a proper library to provide I2CMIDI for the Adafruit MIDI library which ideally would support acting as a CONTROLLER and PERIPHERAL as well as both MIDI IN and OUT functionality.

Kevin

Leave a comment