In this post we continue working on Pico MIDI – a Raspberry Pi Pico based MIDI pedal, and this time I’ll be covering Neopixels and RGB LEDs. How fun! 👌
In my previous posts I covered how to send MIDI commands, how to support footswitch and LED, support external expression pedal and external footswitch pedal.
I know I covered LEDs already, but they are kind of boring 🙂. Neopixels add that glitz, pizzazz to our creations … but I’m getting ahead of myself. Keep on reading or, as usual – you can skip directly to the video and come back later for more details if you wish so.
Here’s the ToC:
Neopixels
I got a few Neopixels from Adafruit:

The neopixel is fantastic, it requires only 3 wires to be hoked up – power (positive & negative) and a data pin. And the neopixels can be chained, and the micropython supports them out-of-the-box.
In this post I’ll cover just basic stuff, but if you want to see more … well there’s an uberguide for it.
Schematic
Here’s updated schematic for our pedal with added Neopixel:

Finally a more complex hardware change 🙂. You see how neopixel is connected to just one GPIO – GPIO8. The other two connections are to 3.3V power supply and GND. Also, the pin number 1 is disconnected but you could daisy chain there another neopixel if you wanted to.
Neopixels are best driven by 5V supply, but then you also need to use 5V levels for data input. That won’t work for my Raspberry Pi Pico, so I decided to use 3.3V. You could try with level shifters and what not, but why bother when this will work just fine. The neopixel won’t be as bright as it possibly can be, but that baby is super bright anyway!
The schematic also supports RGB LED but I’ll come to that part later.
Coding Neopixel
The first example is straight from the micropython documentation or :
from machine import Pin
from neopixel import NeoPixel
pin = Pin(8, Pin.OUT) # set GPIO8 to output to drive NeoPixels
np = NeoPixel(pin, 8) # create NeoPixel driver for 8 pixels
np[0] = (255, 255, 255) # set the first pixel to white
np.write() # write data to all pixels
This is super simple – we’re using GPIO8 to connect to Neopixel. I created a driver for 8 pixels (copy/pasted from the docs) but I only have 1 pixel, so I could done this: np = NeoPixel(pin, 1). That would’ve generated driver for just one pixel. Won’t matter much.
Finally I set the colour to be eye singeing white, and write the data so it actually applies the colour and that’s it.

In the demo I did Red and Green colour, but you can do any colour imaginable. And the image doesn’t do it justice how bright the pixel is.
Adding Expression Pedal
Once you have the neopixel wired up, you can control it pretty easily. Here’s how to control it with external expression pedal:
from machine import UART, Pin, ADC
import uasyncio as asyncio
from primitives import Pushbutton, AADC
from neopixel import NeoPixel
# Whammy 2 octaves up ON/OFF
pc_1 = b'\xc0\x00'
pc_22 = b'\xc0\x15'
# CC#11 - toe up/down
cc_toe_up = b'\xb0\x0b\x00'
cc_toe_down = b'\xb0\x0b\x7f'
cc_partial = b'\xb0\x0b'
#linear
def translate_pot_value(val):
(x2, y2) = (65_535.0, 65_535.0)
taper = [(0.0,0.0)]
for (x1, y1) in taper:
if val >= x1: #detect piecewise linear function
piecewise_portion = (val-x1)/(x2-x1) #portion of that piecewise function
piecewise_value = (y2-y1)*piecewise_portion + y1
return piecewise_value
(x2, y2) = (x1, y1)
return 0.0
def toggle(led, midi):
led.toggle()
if led.value():
midi.write(bytearray(pc_1))
else:
midi.write(bytearray(pc_22))
def express(aadc, midi, np):
while True:
value = await aadc(512)
cmd = bytearray(cc_partial)
adc_value = int(translate_pot_value(value)/512)
cmd.append(adc_value)
print(adc_value)
out_len = midi.write(cmd) #setting out_len so count is not printed out
np[0] = (adc_value * 2, 0, 0)
np.write()
async def my_app():
pin = Pin(14, Pin.IN, Pin.PULL_UP)
red = Pin(15, Pin.OUT)
midi = UART(0, baudrate=31250, bits=8, parity=None, stop=1, tx=Pin(16), rx=Pin(17), invert=0)
aadc = AADC(ADC(Pin(27)))
driver = Pin(26, Pin.OUT)
driver.on()
pb = Pushbutton(pin)
pb.press_func(toggle, (red, midi, ))
pin = Pin(8, Pin.OUT) # set GPIO8 to output to drive NeoPixels
np = NeoPixel(pin, 1) # create NeoPixel driver for 1 pixel
asyncio.create_task(express(aadc, midi, np))
while True:
await asyncio.sleep(60)
asyncio.run(my_app()) # Run main application code
See the video for longer explanation of the code, I copied most of this from previous posts. The only difference here is that in express function, along with controllig possibly Digitech Whammy you get a light show as well 😁.
I hope this demonstrate how easy it is to use neopixel in action. Now, I wasn’t too inspired for this demo but you should be able to do pretty amazing stuff if you set your mind to it.
Why Not Using Neopixel?
Neopixel is pretty amazing, no two ways about it. There is a teensy-weensy issue with it though. It might be drawing too much current. Adafruit website says about 60mA if I’m not mistaken.
Now, that’s not too much and using 3.3V drops that consumption a bit. If we put this into perspective that traditional pedals are consuming less than 10mA, then this might be an issue. Say we use 4 of these, at maximum intensity, that might easily exceed output capacity of some of the smaller pedal power supplies.
Again, this might or might not be an issue, but more importantly, we need to be careful of what Pico’s power supply can support too (I think this is about 300mA).
In order to overcome this problem (if it ever becomes one), we could resort to more pedestrian way of doing things. Let’s talk about RGB LEDs.
Controlling RGB LED
One of the reasons for using RGB LED for our visual indicators instead of Neopixel is power consumption. You could get away with less than 5mA and you get pretty decent brightness. To control RGB light, we need to mix R, G and B components varying their brightness, that way we can get any colour we like.
Luck would have it that basic examples from Raspberry Pi Pico website do exactly that:
from machine import Pin, PWM
from time import sleep
pwm = PWM(Pin(15))
pwm.freq(1000)
while True:
for duty in range(65025):
pwm.duty_u16(duty)
sleep(0.0001)
for duty in range(65025, 0, -1):
pwm.duty_u16(duty)
sleep(0.0001)
That’s a very simple way to control brightness of an LED using PWM. Of course, Micropython makes this easy to do. Suffice to say that Puls Width Modulation controls how long LED is on and how long it is turned off, but it does it very quickly so our eye just sees it as a difference in brightness.
Controlling an RGB LED is pretty much the same, except there are 3 LEDs in the same housing. If you look at the schematic above, I attached R, G and B pins to GPIOs 20, 19 and 18 respectively. The 4th pin of the diode is common anode.
I suppose at this point it’s worth mentioning that these multicoloured LEDs have all sorts of various configurations so the one you might have might not match mine exactly. If that’s the case, just have a look at the datasheet of your LED and try to match how I wired things up.
Here’s the code to control my RGB LED:
from machine import Pin, PWM
from time import sleep
pwmR = PWM(Pin(20))
pwmG = PWM(Pin(19))
pwmB = PWM(Pin(18))
pwmR.freq(1000)
pwmG.freq(1000)
pwmB.freq(1000)
#pwmG = Pin(19, Pin.OUT)
#pwmG.on() #turn off green colour
#pwmB = Pin(18, Pin.OUT)
#pwmB.on() #turn off blue colour
while True:
for duty in range(65025):
pwmR.duty_u16(duty)
pwmG.duty_u16(duty)
pwmB.duty_u16(duty)
sleep(0.0001)
for duty in range(65025, 0, -1):
pwmR.duty_u16(duty)
pwmG.duty_u16(duty)
pwmB.duty_u16(duty)
sleep(0.0001)
That’s pretty much it, way more complex (but still not too much) than using Neopixel.
Action
Here’s another not so quick demo of what I covered here:
We covered Neopixels and RGB LEDs, ideally, I’d prefer using Neopixel, but that might not be the best solution if I want to keep power consumption in check.
Next on my list is, and this is to finally complete all the necessary bits for the pedal: external power supply. Why? Because we don’t want our pedal to be connected to USB port all the time. Subscribe so you don’t miss out 😉