#forbiddenplanet — Public Fediverse posts
Live and recent posts from across the Fediverse tagged #forbiddenplanet, aggregated by home.social.
-
@cogdog 🧵Extrapolated Future Archives
Thanks! This is so great — and well designed. I’ve always wanted to navigate #scfi themes and connections like this.
The only downside — no #ForbiddenPlanet (social media + god like power)
-
Mono Junk (a.k.a. Kim Rapatti) - Suomen Moroderit Theme (FP-008, Forbidden Planet/CAN, 20 April 2015).
https://www.youtube.com/watch?v=9ZCaO31CMJE
#MonoJunk #electro #techno #IDM #synthwave #electronic #KimRapatti #KimmoRapatti #SuomenMoroderit #Dum #DumRecords #ForbiddenPlanet #ForbiddenPlanetRecords #Montreal #Canada #Imatra #Finland
-
Mono Junk (a.k.a. Kim Rapatti) - Suomen Moroderit Theme (FP-008, Forbidden Planet/CAN, 20 April 2015).
https://www.youtube.com/watch?v=9ZCaO31CMJE
#MonoJunk #electro #techno #IDM #synthwave #electronic #KimRapatti #KimmoRapatti #SuomenMoroderit #Dum #DumRecords #ForbiddenPlanet #ForbiddenPlanetRecords #Montreal #Canada #Imatra #Finland
-
Mono Junk (a.k.a. Kim Rapatti) - Suomen Moroderit Theme (FP-008, Forbidden Planet/CAN, 20 April 2015).
https://www.youtube.com/watch?v=9ZCaO31CMJE
#MonoJunk #electro #techno #IDM #synthwave #electronic #KimRapatti #KimmoRapatti #SuomenMoroderit #Dum #DumRecords #ForbiddenPlanet #ForbiddenPlanetRecords #Montreal #Canada #Imatra #Finland
-
Mono Junk (a.k.a. Kim Rapatti) - Suomen Moroderit Theme (FP-008, Forbidden Planet/CAN, 20 April 2015).
https://www.youtube.com/watch?v=9ZCaO31CMJE
#MonoJunk #electro #techno #IDM #synthwave #electronic #KimRapatti #KimmoRapatti #SuomenMoroderit #Dum #DumRecords #ForbiddenPlanet #ForbiddenPlanetRecords #Montreal #Canada #Imatra #Finland
-
Mono Junk (a.k.a. Kim Rapatti) - Suomen Moroderit Theme (FP-008, Forbidden Planet/CAN, 20 April 2015).
https://www.youtube.com/watch?v=9ZCaO31CMJE
#MonoJunk #electro #techno #IDM #synthwave #electronic #KimRapatti #KimmoRapatti #SuomenMoroderit #Dum #DumRecords #ForbiddenPlanet #ForbiddenPlanetRecords #Montreal #Canada #Imatra #Finland
-
Monster Mondays takes to the stars to discuss the 1956 sci-fi classic starring Leslie Nielsen, Anne Francis, and one of the most recognizable robots in movie history in Forbidden Planet!
Listen to the new episode at https://wp.me/p9Tw3k-1NB
#podcast #monstermondays #moviediscussion #forbiddenplanet #leslienielsen #annefrancis #robbytherobot #sciencefiction #50s
-
Cozzi inserted references/homage to lots of scifi/Monsterdon films & scifi books, inc:
Forbidden Planet (1954)
Invaders from Mars
Jason and the Argonauts (#Monsterdon 15 March 2026!)
2001 (1968)#LuigiCozzi #SciFi #Monsterdon #Starcrash #ForbiddenPlanet #JasonAndTheArgonauts
-
Twitter “…invites social creatures like us to build social norms and expectations over the public commons and specific affordances that Twitter created” Mar 2009
Like the Krell did before they turned off the lights and went to sleep, long ago on Altair IV.
-
Taken this day, 2013, Babylon 5 & Tron's Bruce Boxleitner visiting Forbidden Planet https://www.flickr.com/photos/woolamaloo_gazette/9701233231/
#Edinburgh #Edimbourg #photography #photographie #ScienceFiction #BruceBoxleitner #Actor #Acteur #Writer #Auteur #ForbiddenPlanet #Babylon5 #Tron
-
Forbidden Planet “Krell” Display – MIDI CC Controller – Part 2
This revisits my Forbidden Planet “Krell” Display – MIDI CC Controller using my Forbidden Planet “Krell” Display PCB with a Waveshare RP2040 to create more of a “all in one” device.
Warning! I strongly recommend using old or second hand equipment for your experiments. I am not responsible for any damage to expensive instruments!
If you are new to Arduino, see the Getting Started pages.
Parts list
- Updated Forbidden Planet “Krell” Display (see below).
- Completed Forbidden Planet “Krell” Display PCB Build
- Waveshare Zero format device (I’m using an RP2040)
- 4x 6mm brass spacers
- 4x 20mm nylon spacers
PCB
This requires a built of the Forbidden Planet “Krell” Display PCB with the following:
- 2 potentiometers
- MIDI IN and OUT
I’ve used potentiometers that are their own knob, as they only poke through the casing by around 5mm or so.
If it you are able to get longer shaft pots, then that would probably be worthwhile.
Updated 3D Printed Case
This requires the following from the Krell Display 3D Printed Case:
- 1x Frame
- 2x Inserts (with potentiometer holes)
- 1x EuroRack support
This requires the following options in the OpenSCAD code:
show_frame = 1;
show_quadframe = 0;
show_insert = 1;
show_support = 0;
show_quadsupport = 0;
show_eurorack = 0;
show_eurorack_support = 1;
alg_pot1 = 1;
alg_pot2 = 1;
alg_cv = 0;The frame does not really take into account the PCB at present, but I’ve reached the “good enough I want to do something else” stage, so I’ve just added a couple of small cut-outs (using a hacksaw) for the two MIDI sockets, and am content that the components stick out a bit from the back.
This cutout has to be 10.5mm from the end, 6mm wide, and 5mm deep.
At some point I might go back and design a deeper frame that has the cut-outs included and some kind of snap-on back to make it a self-contained box.
But for now, this is left as an exercise for, well, anyone else 🙂
Construction
I’ve used four brass 6mm spacers to screw into the mounting holes in the frame. Then the PCB can be inserted, taking care to squeeze in the 3D printed support around the LEDs and pots, and fixed with 20mm spacers which will also act as “legs”.
The Code
I’ve used a Waveshare Zero RP2040 and Circuitpython for this build. This is a combination of some of the test code used for the Forbidden Planet “Krell” Display PCB but with added MIDI.
The code supports both Serial and USB MIDI.
I wanted an equivalent of the Arduino map() and constrain() functions and didn’t immediate spot them in Circuitpython so wrote my own:
def algmap(val, minin, maxin, minout, maxout):
if (val < minin):
val = minin
if (val > maxin):
val = maxin
return minout + (((val - minin) * (maxout - minout)) / (maxin - minin))This allows me to map the analog read values (0 to 65535) down to MIDI CC values (0 to 127) whilst also allowing for some inaccuracies (I’ve treated anything below 256 as zero for example):
alg1cc = int(algmap(alg1_in.value,256,65530,0,127))
I’ve used the Adafruit MIDI library, which I’m still not really a fan of, but I wanted to include MIDI THRU functionality to allow the controller to sit inline with an existing MIDI stream. But it doesn’t seem to work very well.
I was already only updating the LEDs/MIDI CC if the pot values had changed, to cut down on the number of Neopixel writes required.
I experimented with changing the scheduling of the analog reads and MIDI but that didn’t seem to help very much. In the end I made sure that all MIDI messages queued up in the system would be read at the same time before going back to checking the pots.
msg = midiuart.receive()
while (msg is not None):
if (not isinstance(msg, MIDIUnknownEvent)):
midiuart.send(msg)
msg = midiuart.receive()It will do for now. Moving forward, I might try the Winterbloom SmolMIDI library. If that still doesn’t give me some useful performance then I might have to switch over to Arduino C.
Closing Thoughts
The MIDI throughput is disappointing, but then I’ve never really gotten on with the Adafruit MIDI library. I use it as USB MIDI on Circuitpython is so easy, so will need to do something about that.
I’m still deciding on the PCB-sized supports too. The original seemed to have nicer diffusion of the LEDs, but that could have been the difference between 5mm SMT neopixels and these THT APA106s which seem more directional in the first place.
And I really ought to finish the 3D printed case properly too.
So this is “that will do” for now, but I ought to come back and finish it off properly at some point.
Kevin
#APA106 #circuitpython #ForbiddenPlanet #Krell #midi #midiController #NeoPixel #potentiometer #rp2040 #WaveshareZero
-
Forbidden Planet “Krell” Display – MIDI CC Controller – Part 2
This revisits my Forbidden Planet “Krell” Display – MIDI CC Controller using my Forbidden Planet “Krell” Display PCB with a Waveshare RP2040 to create more of a “all in one” device.
Warning! I strongly recommend using old or second hand equipment for your experiments. I am not responsible for any damage to expensive instruments!
If you are new to Arduino, see the Getting Started pages.
Parts list
- Updated Forbidden Planet “Krell” Display (see below).
- Completed Forbidden Planet “Krell” Display PCB Build
- Waveshare Zero format device (I’m using an RP2040)
- 4x 6mm brass spacers
- 4x 20mm nylon spacers
PCB
This requires a built of the Forbidden Planet “Krell” Display PCB with the following:
- 2 potentiometers
- MIDI IN and OUT
I’ve used potentiometers that are their own knob, as they only poke through the casing by around 5mm or so.
If it you are able to get longer shaft pots, then that would probably be worthwhile.
Updated 3D Printed Case
This requires the following from the Krell Display 3D Printed Case:
- 1x Frame
- 2x Inserts (with potentiometer holes)
- 1x EuroRack support
This requires the following options in the OpenSCAD code:
show_frame = 1;
show_quadframe = 0;
show_insert = 1;
show_support = 0;
show_quadsupport = 0;
show_eurorack = 0;
show_eurorack_support = 1;
alg_pot1 = 1;
alg_pot2 = 1;
alg_cv = 0;The frame does not really take into account the PCB at present, but I’ve reached the “good enough I want to do something else” stage, so I’ve just added a couple of small cut-outs (using a hacksaw) for the two MIDI sockets, and am content that the components stick out a bit from the back.
This cutout has to be 10.5mm from the end, 6mm wide, and 5mm deep.
At some point I might go back and design a deeper frame that has the cut-outs included and some kind of snap-on back to make it a self-contained box.
But for now, this is left as an exercise for, well, anyone else 🙂
Construction
I’ve used four brass 6mm spacers to screw into the mounting holes in the frame. Then the PCB can be inserted, taking care to squeeze in the 3D printed support around the LEDs and pots, and fixed with 20mm spacers which will also act as “legs”.
The Code
I’ve used a Waveshare Zero RP2040 and Circuitpython for this build. This is a combination of some of the test code used for the Forbidden Planet “Krell” Display PCB but with added MIDI.
The code supports both Serial and USB MIDI.
I wanted an equivalent of the Arduino map() and constrain() functions and didn’t immediate spot them in Circuitpython so wrote my own:
def algmap(val, minin, maxin, minout, maxout):
if (val < minin):
val = minin
if (val > maxin):
val = maxin
return minout + (((val - minin) * (maxout - minout)) / (maxin - minin))This allows me to map the analog read values (0 to 65535) down to MIDI CC values (0 to 127) whilst also allowing for some inaccuracies (I’ve treated anything below 256 as zero for example):
alg1cc = int(algmap(alg1_in.value,256,65530,0,127))
I’ve used the Adafruit MIDI library, which I’m still not really a fan of, but I wanted to include MIDI THRU functionality to allow the controller to sit inline with an existing MIDI stream. But it doesn’t seem to work very well.
I was already only updating the LEDs/MIDI CC if the pot values had changed, to cut down on the number of Neopixel writes required.
I experimented with changing the scheduling of the analog reads and MIDI but that didn’t seem to help very much. In the end I made sure that all MIDI messages queued up in the system would be read at the same time before going back to checking the pots.
msg = midiuart.receive()
while (msg is not None):
if (not isinstance(msg, MIDIUnknownEvent)):
midiuart.send(msg)
msg = midiuart.receive()It will do for now. Moving forward, I might try the Winterbloom SmolMIDI library. If that still doesn’t give me some useful performance then I might have to switch over to Arduino C.
Closing Thoughts
The MIDI throughput is disappointing, but then I’ve never really gotten on with the Adafruit MIDI library. I use it as USB MIDI on Circuitpython is so easy, so will need to do something about that.
I’m still deciding on the PCB-sized supports too. The original seemed to have nicer diffusion of the LEDs, but that could have been the difference between 5mm SMT neopixels and these THT APA106s which seem more directional in the first place.
And I really ought to finish the 3D printed case properly too.
So this is “that will do” for now, but I ought to come back and finish it off properly at some point.
Kevin
#APA106 #circuitpython #ForbiddenPlanet #Krell #midi #midiController #NeoPixel #potentiometer #rp2040 #WaveshareZero
-
Forbidden Planet “Krell” Display – MIDI CC Controller – Part 2
This revisits my Forbidden Planet “Krell” Display – MIDI CC Controller using my Forbidden Planet “Krell” Display PCB with a Waveshare RP2040 to create more of a “all in one” device.
Warning! I strongly recommend using old or second hand equipment for your experiments. I am not responsible for any damage to expensive instruments!
If you are new to Arduino, see the Getting Started pages.
Parts list
- Updated Forbidden Planet “Krell” Display (see below).
- Completed Forbidden Planet “Krell” Display PCB Build
- Waveshare Zero format device (I’m using an RP2040)
- 4x 6mm brass spacers
- 4x 20mm nylon spacers
PCB
This requires a built of the Forbidden Planet “Krell” Display PCB with the following:
- 2 potentiometers
- MIDI IN and OUT
I’ve used potentiometers that are their own knob, as they only poke through the casing by around 5mm or so.
If it you are able to get longer shaft pots, then that would probably be worthwhile.
Updated 3D Printed Case
This requires the following from the Krell Display 3D Printed Case:
- 1x Frame
- 2x Inserts (with potentiometer holes)
- 1x EuroRack support
This requires the following options in the OpenSCAD code:
show_frame = 1;
show_quadframe = 0;
show_insert = 1;
show_support = 0;
show_quadsupport = 0;
show_eurorack = 0;
show_eurorack_support = 1;
alg_pot1 = 1;
alg_pot2 = 1;
alg_cv = 0;The frame does not really take into account the PCB at present, but I’ve reached the “good enough I want to do something else” stage, so I’ve just added a couple of small cut-outs (using a hacksaw) for the two MIDI sockets, and am content that the components stick out a bit from the back.
This cutout has to be 10.5mm from the end, 6mm wide, and 5mm deep.
At some point I might go back and design a deeper frame that has the cut-outs included and some kind of snap-on back to make it a self-contained box.
But for now, this is left as an exercise for, well, anyone else 🙂
Construction
I’ve used four brass 6mm spacers to screw into the mounting holes in the frame. Then the PCB can be inserted, taking care to squeeze in the 3D printed support around the LEDs and pots, and fixed with 20mm spacers which will also act as “legs”.
The Code
I’ve used a Waveshare Zero RP2040 and Circuitpython for this build. This is a combination of some of the test code used for the Forbidden Planet “Krell” Display PCB but with added MIDI.
The code supports both Serial and USB MIDI.
I wanted an equivalent of the Arduino map() and constrain() functions and didn’t immediate spot them in Circuitpython so wrote my own:
def algmap(val, minin, maxin, minout, maxout):
if (val < minin):
val = minin
if (val > maxin):
val = maxin
return minout + (((val - minin) * (maxout - minout)) / (maxin - minin))This allows me to map the analog read values (0 to 65535) down to MIDI CC values (0 to 127) whilst also allowing for some inaccuracies (I’ve treated anything below 256 as zero for example):
alg1cc = int(algmap(alg1_in.value,256,65530,0,127))
I’ve used the Adafruit MIDI library, which I’m still not really a fan of, but I wanted to include MIDI THRU functionality to allow the controller to sit inline with an existing MIDI stream. But it doesn’t seem to work very well.
I was already only updating the LEDs/MIDI CC if the pot values had changed, to cut down on the number of Neopixel writes required.
I experimented with changing the scheduling of the analog reads and MIDI but that didn’t seem to help very much. In the end I made sure that all MIDI messages queued up in the system would be read at the same time before going back to checking the pots.
msg = midiuart.receive()
while (msg is not None):
if (not isinstance(msg, MIDIUnknownEvent)):
midiuart.send(msg)
msg = midiuart.receive()It will do for now. Moving forward, I might try the Winterbloom SmolMIDI library. If that still doesn’t give me some useful performance then I might have to switch over to Arduino C.
Closing Thoughts
The MIDI throughput is disappointing, but then I’ve never really gotten on with the Adafruit MIDI library. I use it as USB MIDI on Circuitpython is so easy, so will need to do something about that.
I’m still deciding on the PCB-sized supports too. The original seemed to have nicer diffusion of the LEDs, but that could have been the difference between 5mm SMT neopixels and these THT APA106s which seem more directional in the first place.
And I really ought to finish the 3D printed case properly too.
So this is “that will do” for now, but I ought to come back and finish it off properly at some point.
Kevin
#APA106 #circuitpython #ForbiddenPlanet #Krell #midi #midiController #NeoPixel #potentiometer #rp2040 #WaveshareZero
-
Forbidden Planet “Krell” Display – MIDI CC Controller – Part 2
This revisits my Forbidden Planet “Krell” Display – MIDI CC Controller using my Forbidden Planet “Krell” Display PCB with a Waveshare RP2040 to create more of a “all in one” device.
Warning! I strongly recommend using old or second hand equipment for your experiments. I am not responsible for any damage to expensive instruments!
If you are new to Arduino, see the Getting Started pages.
Parts list
- Updated Forbidden Planet “Krell” Display (see below).
- Completed Forbidden Planet “Krell” Display PCB Build
- Waveshare Zero format device (I’m using an RP2040)
- 4x 6mm brass spacers
- 4x 20mm nylon spacers
PCB
This requires a built of the Forbidden Planet “Krell” Display PCB with the following:
- 2 potentiometers
- MIDI IN and OUT
I’ve used potentiometers that are their own knob, as they only poke through the casing by around 5mm or so.
If it you are able to get longer shaft pots, then that would probably be worthwhile.
Updated 3D Printed Case
This requires the following from the Krell Display 3D Printed Case:
- 1x Frame
- 2x Inserts (with potentiometer holes)
- 1x EuroRack support
This requires the following options in the OpenSCAD code:
show_frame = 1;
show_quadframe = 0;
show_insert = 1;
show_support = 0;
show_quadsupport = 0;
show_eurorack = 0;
show_eurorack_support = 1;
alg_pot1 = 1;
alg_pot2 = 1;
alg_cv = 0;The frame does not really take into account the PCB at present, but I’ve reached the “good enough I want to do something else” stage, so I’ve just added a couple of small cut-outs (using a hacksaw) for the two MIDI sockets, and am content that the components stick out a bit from the back.
This cutout has to be 10.5mm from the end, 6mm wide, and 5mm deep.
At some point I might go back and design a deeper frame that has the cut-outs included and some kind of snap-on back to make it a self-contained box.
But for now, this is left as an exercise for, well, anyone else 🙂
Construction
I’ve used four brass 6mm spacers to screw into the mounting holes in the frame. Then the PCB can be inserted, taking care to squeeze in the 3D printed support around the LEDs and pots, and fixed with 20mm spacers which will also act as “legs”.
The Code
I’ve used a Waveshare Zero RP2040 and Circuitpython for this build. This is a combination of some of the test code used for the Forbidden Planet “Krell” Display PCB but with added MIDI.
The code supports both Serial and USB MIDI.
I wanted an equivalent of the Arduino map() and constrain() functions and didn’t immediate spot them in Circuitpython so wrote my own:
def algmap(val, minin, maxin, minout, maxout):
if (val < minin):
val = minin
if (val > maxin):
val = maxin
return minout + (((val - minin) * (maxout - minout)) / (maxin - minin))This allows me to map the analog read values (0 to 65535) down to MIDI CC values (0 to 127) whilst also allowing for some inaccuracies (I’ve treated anything below 256 as zero for example):
alg1cc = int(algmap(alg1_in.value,256,65530,0,127))
I’ve used the Adafruit MIDI library, which I’m still not really a fan of, but I wanted to include MIDI THRU functionality to allow the controller to sit inline with an existing MIDI stream. But it doesn’t seem to work very well.
I was already only updating the LEDs/MIDI CC if the pot values had changed, to cut down on the number of Neopixel writes required.
I experimented with changing the scheduling of the analog reads and MIDI but that didn’t seem to help very much. In the end I made sure that all MIDI messages queued up in the system would be read at the same time before going back to checking the pots.
msg = midiuart.receive()
while (msg is not None):
if (not isinstance(msg, MIDIUnknownEvent)):
midiuart.send(msg)
msg = midiuart.receive()It will do for now. Moving forward, I might try the Winterbloom SmolMIDI library. If that still doesn’t give me some useful performance then I might have to switch over to Arduino C.
Closing Thoughts
The MIDI throughput is disappointing, but then I’ve never really gotten on with the Adafruit MIDI library. I use it as USB MIDI on Circuitpython is so easy, so will need to do something about that.
I’m still deciding on the PCB-sized supports too. The original seemed to have nicer diffusion of the LEDs, but that could have been the difference between 5mm SMT neopixels and these THT APA106s which seem more directional in the first place.
And I really ought to finish the 3D printed case properly too.
So this is “that will do” for now, but I ought to come back and finish it off properly at some point.
Kevin
#APA106 #circuitpython #ForbiddenPlanet #Krell #midi #midiController #NeoPixel #potentiometer #rp2040 #WaveshareZero
-
Forbidden Planet “Krell” Display – MIDI CC Controller – Part 2
This revisits my Forbidden Planet “Krell” Display – MIDI CC Controller using my Forbidden Planet “Krell” Display PCB with a Waveshare RP2040 to create more of a “all in one” device.
Warning! I strongly recommend using old or second hand equipment for your experiments. I am not responsible for any damage to expensive instruments!
If you are new to Arduino, see the Getting Started pages.
Parts list
- Updated Forbidden Planet “Krell” Display (see below).
- Completed Forbidden Planet “Krell” Display PCB Build
- Waveshare Zero format device (I’m using an RP2040)
- 4x 6mm brass spacers
- 4x 20mm nylon spacers
PCB
This requires a built of the Forbidden Planet “Krell” Display PCB with the following:
- 2 potentiometers
- MIDI IN and OUT
I’ve used potentiometers that are their own knob, as they only poke through the casing by around 5mm or so.
If it you are able to get longer shaft pots, then that would probably be worthwhile.
Updated 3D Printed Case
This requires the following from the Krell Display 3D Printed Case:
- 1x Frame
- 2x Inserts (with potentiometer holes)
- 1x EuroRack support
This requires the following options in the OpenSCAD code:
show_frame = 1;
show_quadframe = 0;
show_insert = 1;
show_support = 0;
show_quadsupport = 0;
show_eurorack = 0;
show_eurorack_support = 1;
alg_pot1 = 1;
alg_pot2 = 1;
alg_cv = 0;The frame does not really take into account the PCB at present, but I’ve reached the “good enough I want to do something else” stage, so I’ve just added a couple of small cut-outs (using a hacksaw) for the two MIDI sockets, and am content that the components stick out a bit from the back.
This cutout has to be 10.5mm from the end, 6mm wide, and 5mm deep.
At some point I might go back and design a deeper frame that has the cut-outs included and some kind of snap-on back to make it a self-contained box.
But for now, this is left as an exercise for, well, anyone else 🙂
Construction
I’ve used four brass 6mm spacers to screw into the mounting holes in the frame. Then the PCB can be inserted, taking care to squeeze in the 3D printed support around the LEDs and pots, and fixed with 20mm spacers which will also act as “legs”.
The Code
I’ve used a Waveshare Zero RP2040 and Circuitpython for this build. This is a combination of some of the test code used for the Forbidden Planet “Krell” Display PCB but with added MIDI.
The code supports both Serial and USB MIDI.
I wanted an equivalent of the Arduino map() and constrain() functions and didn’t immediate spot them in Circuitpython so wrote my own:
def algmap(val, minin, maxin, minout, maxout):
if (val < minin):
val = minin
if (val > maxin):
val = maxin
return minout + (((val - minin) * (maxout - minout)) / (maxin - minin))This allows me to map the analog read values (0 to 65535) down to MIDI CC values (0 to 127) whilst also allowing for some inaccuracies (I’ve treated anything below 256 as zero for example):
alg1cc = int(algmap(alg1_in.value,256,65530,0,127))
I’ve used the Adafruit MIDI library, which I’m still not really a fan of, but I wanted to include MIDI THRU functionality to allow the controller to sit inline with an existing MIDI stream. But it doesn’t seem to work very well.
I was already only updating the LEDs/MIDI CC if the pot values had changed, to cut down on the number of Neopixel writes required.
I experimented with changing the scheduling of the analog reads and MIDI but that didn’t seem to help very much. In the end I made sure that all MIDI messages queued up in the system would be read at the same time before going back to checking the pots.
msg = midiuart.receive()
while (msg is not None):
if (not isinstance(msg, MIDIUnknownEvent)):
midiuart.send(msg)
msg = midiuart.receive()It will do for now. Moving forward, I might try the Winterbloom SmolMIDI library. If that still doesn’t give me some useful performance then I might have to switch over to Arduino C.
Closing Thoughts
The MIDI throughput is disappointing, but then I’ve never really gotten on with the Adafruit MIDI library. I use it as USB MIDI on Circuitpython is so easy, so will need to do something about that.
I’m still deciding on the PCB-sized supports too. The original seemed to have nicer diffusion of the LEDs, but that could have been the difference between 5mm SMT neopixels and these THT APA106s which seem more directional in the first place.
And I really ought to finish the 3D printed case properly too.
So this is “that will do” for now, but I ought to come back and finish it off properly at some point.
Kevin
#APA106 #circuitpython #ForbiddenPlanet #Krell #midi #midiController #NeoPixel #potentiometer #rp2040 #WaveshareZero
-
And a short demo of it in action.
-
And a short demo of it in action.
-
And a short demo of it in action.
-
And a short demo of it in action.
-
And a short demo of it in action.
-
Here is a 12 HP EuroRack version of my Krell Display with a single CV input.
https://diyelectromusic.com/2025/04/03/forbidden-planet-krell-display-eurorack-module/
-
Here is a 12 HP EuroRack version of my Krell Display with a single CV input.
https://diyelectromusic.com/2025/04/03/forbidden-planet-krell-display-eurorack-module/
-
Here is a 12 HP EuroRack version of my Krell Display with a single CV input.
https://diyelectromusic.com/2025/04/03/forbidden-planet-krell-display-eurorack-module/
-
Here is a 12 HP EuroRack version of my Krell Display with a single CV input.
https://diyelectromusic.com/2025/04/03/forbidden-planet-krell-display-eurorack-module/
-
Here is a 12 HP EuroRack version of my Krell Display with a single CV input.
https://diyelectromusic.com/2025/04/03/forbidden-planet-krell-display-eurorack-module/
-
I've updated my Forbidden Planet Krell Display to allow me to produce a 12HP EuroRack panel version.
Looking promising so far...
-
I've updated my Forbidden Planet Krell Display to allow me to produce a 12HP EuroRack panel version.
Looking promising so far...
-
I've updated my Forbidden Planet Krell Display to allow me to produce a 12HP EuroRack panel version.
Looking promising so far...
-
I've updated my Forbidden Planet Krell Display to allow me to produce a 12HP EuroRack panel version.
Looking promising so far...
-
I've updated my Forbidden Planet Krell Display to allow me to produce a 12HP EuroRack panel version.
Looking promising so far...
-
I've added some pots and turned my Krell display into a simple MIDI controller.
https://diyelectromusic.com/2025/02/15/forbidden-planet-krell-display-midi-cc-controller/
-
I've added some pots and turned my Krell display into a simple MIDI controller.
https://diyelectromusic.com/2025/02/15/forbidden-planet-krell-display-midi-cc-controller/
-
I've added some pots and turned my Krell display into a simple MIDI controller.
https://diyelectromusic.com/2025/02/15/forbidden-planet-krell-display-midi-cc-controller/
-
I've added some pots and turned my Krell display into a simple MIDI controller.
https://diyelectromusic.com/2025/02/15/forbidden-planet-krell-display-midi-cc-controller/
-
I've added some pots and turned my Krell display into a simple MIDI controller.
https://diyelectromusic.com/2025/02/15/forbidden-planet-krell-display-midi-cc-controller/
-
Forbidden Planet “Krell” Display – MIDI Notes – Part 2
As I mentioned in Forbidden Planet “Krell” Display – MIDI Notes I’m building a simple (in function, not in execution it would seem) MIDI note display out of my Forbidden Planet “Krell” Display.
The first attempt showed there is potential, but I was rapidly reaching the limits of what an Arduino could do for me using the off-the-shelf common Adafruit_NeoPixel library.
In this part, I’ve taken forward one of the possible optimisations and I’ve split the display up into separate strips of LEDs. It seems to work a lot better.
https://makertube.net/w/tVb2dGqAFarS8mB14t9JSR
Warning! I strongly recommend using old or second hand equipment for your experiments. I am not responsible for any damage to expensive instruments!
If you are new to Arduino, see the Getting Started pages.
Parts list
- Completed Forbidden Planet “Krell” Display.
- Arduino Nano or Uno.
- MIDI Interface, e.g. DIY MIDI Interfaces, Ready-Made MIDI Modules, and so on.
- Breadboard and jumper wires.
The Circuit
As I mentioned in part 1, there is a significant limitation due to the time it takes to scan all of the LEDs in eight connected rings. For all 56 LEDs it takes almost 2mS and interrupts are completely disabled during that time meaning that MIDI data is getting lost.
But by splitting those rings up into groups of two, I can cut the scanning time down to less than 600uS. This compares favourably with the time it takes to process and store a single byte of MIDI data. At 31250 baud that is around 320uS and one character can be stored within the UART hardware while another character is being received.
Consequently, each pair of LED rings is now connected to its own Arduino GPIO pin. I’m using pins D8-D11 for my four rings.
The Code
A lot of the code is similar to the prevous post but I’ve had to add in an additional layer of abstraction to cope with the fact that the led array is now spread over four separate Adafruit NeoPixel controls.
#define LED_BLOCK 5
#define LED_RINGS 8
#define LED_COUNT (LED_BLOCK*LED_RINGS)
#define STRIP_BLOCK 7
int ledpattern[LED_BLOCK] = {1,0,5,4,3};
int leds[LED_COUNT];
int ledState[LED_COUNT];
bool ledUpdate;
#define NUM_STRIPS 4
int ledPins [NUM_STRIPS] = {8,9,10,11};
int stripCounts [NUM_STRIPS] = {2,2,2,2};
#define STRIP_FORMAT (NEO_GRB + NEO_KHZ800)
Adafruit_NeoPixel *strip[NUM_STRIPS];Now, I’m using an array of NeoPixel objects, which will be dynamically created as part of the startup routines. There is the ability to define the pin and number of rings per strip too. In the first version I had three strips defined of 2, 4 and 2 rings respectively, but the 4-ring strip was still causing lost notes. Eventually I settled on four pairs and that seems to work.
Initialising the real pin numbers is a little more complicated now as each strip has to restart from 0 when mapping my 5 LEDs over to the 7 physical LEDs per ring.
Each strip is initialised as follows:
int blockstart = 0;
for (int i=0; i<NUM_STRIPS; i++) {
strip[i] = new Adafruit_NeoPixel (STRIP_BLOCK*stripCounts[i], ledPins[i], STRIP_FORMAT);
strip[i]->begin();
strip[i]->show();
strip[i]->setBrightness(50);
if (i > 0) {
blockstart += stripCounts[i-1];
}
for (int j=0; j<stripCounts[i]; j++) {
for (int k=0; k<LED_BLOCK; k++) {
leds[LED_BLOCK*(blockstart+j) + k] = ledpattern[k] + STRIP_BLOCK*j;
}
}The leds[] array is still a single array with an entry for each “virtual” LED (i.e. one of each of my 5 in use LEDs per ring) and it still has to be initialised with the pattern of real LEDs. This has the benefit that the core interface to the LEDs still gives the impression of a single list of LEDs in a single virtual strip. The only slightly more complicated bit is when it comes to updating the strips from the internal record of which LEDs are on or off.
I know have a new function to scan a single strip
int startled;
void scanOneStrip (int ledStrip) {
if (ledStrip == 0) {
startled = 0;
} else {
startled += LED_BLOCK * stripCounts[ledStrip-1];
}
int numleds = LED_BLOCK * stripCounts[ledStrip];
strip[ledStrip]->clear();
for(int i=startled; i<startled+numleds; i++) {
if (ledState[i]>0) {
strip[ledStrip]->setPixelColor(leds[i], strip[ledStrip]->Color(80, 35, 0));
}
}
}The trick here is to calculate the correct starting LED in the virtual array for this strip and then act accordingly.
There is one dependency that it would be nice to get rid of though – this assumes that each strip will be scanned in order – it calculates the start LED based on the cumulative addition of the strip lengths so far. If this is called out of order, it will probably break.
The controlling function presents the same interface as before, but now allows for repeated calls to scan each strip in turn. Remember a key point of doing things this way was to allow the strip updating to return to allow more MIDI message processing inbetween scanning each strip.
int currentStrip;
void scanStrip () {
if (ledUpdate) {
if (currentStrip < NUM_STRIPS) {
scanOneStrip(currentStrip);
currentStrip++;
} else {
ledUpdate = false;
currentStrip = 0;
}
}
}Notice how the ledUpdate flag is only cleared once all strips have been scanned.
One indication of how much better this approach is, is that I’ve been able to implement a note count – I now keep track of the number of NoteOn vs NoteOff messages for each note, meaning that the lights won’t go out whilst a note is still hanging on. If there were any issues with stuck notes now, these counters would get out of sync very quickly (which they were doing when I tried to have one strip of four rings – hence going down to two).
I’ve kept the global inactivity timer though, just in case.
Closing Thoughts
Whilst obviously a fair bit more complicated both in code and wiring, I was surprised at how well this seems to work.
In the video you can see my Lo-Fi Orchestra arrangement of Sky’s Toccata and it is possible really start to see the shape of the music in the display.
Still completely impractical of course – I mean I’m attempting to map 12 musical “units” (of pitch) onto a display that has 10 display “units” (of LEDs) so it isn’t a natural fit.
But it does now seem to work, and I feel now that if required, and power limits not withstanding, several more pairs of rings could be added each with their own GPIO driver pin and performance ought to keep up fine.
So the question is – do I keep trying other solutions or move onto something else…
Kevin
-
Forbidden Planet “Krell” Display – MIDI Notes – Part 2
As I mentioned in Forbidden Planet “Krell” Display – MIDI Notes I’m building a simple (in function, not in execution it would seem) MIDI note display out of my Forbidden Planet “Krell” Display.
The first attempt showed there is potential, but I was rapidly reaching the limits of what an Arduino could do for me using the off-the-shelf common Adafruit_NeoPixel library.
In this part, I’ve taken forward one of the possible optimisations and I’ve split the display up into separate strips of LEDs. It seems to work a lot better.
https://makertube.net/w/tVb2dGqAFarS8mB14t9JSR
Warning! I strongly recommend using old or second hand equipment for your experiments. I am not responsible for any damage to expensive instruments!
If you are new to Arduino, see the Getting Started pages.
Parts list
- Completed Forbidden Planet “Krell” Display.
- Arduino Nano or Uno.
- MIDI Interface, e.g. DIY MIDI Interfaces, Ready-Made MIDI Modules, and so on.
- Breadboard and jumper wires.
The Circuit
As I mentioned in part 1, there is a significant limitation due to the time it takes to scan all of the LEDs in eight connected rings. For all 56 LEDs it takes almost 2mS and interrupts are completely disabled during that time meaning that MIDI data is getting lost.
But by splitting those rings up into groups of two, I can cut the scanning time down to less than 600uS. This compares favourably with the time it takes to process and store a single byte of MIDI data. At 31250 baud that is around 320uS and one character can be stored within the UART hardware while another character is being received.
Consequently, each pair of LED rings is now connected to its own Arduino GPIO pin. I’m using pins D8-D11 for my four rings.
The Code
A lot of the code is similar to the prevous post but I’ve had to add in an additional layer of abstraction to cope with the fact that the led array is now spread over four separate Adafruit NeoPixel controls.
#define LED_BLOCK 5
#define LED_RINGS 8
#define LED_COUNT (LED_BLOCK*LED_RINGS)
#define STRIP_BLOCK 7
int ledpattern[LED_BLOCK] = {1,0,5,4,3};
int leds[LED_COUNT];
int ledState[LED_COUNT];
bool ledUpdate;
#define NUM_STRIPS 4
int ledPins [NUM_STRIPS] = {8,9,10,11};
int stripCounts [NUM_STRIPS] = {2,2,2,2};
#define STRIP_FORMAT (NEO_GRB + NEO_KHZ800)
Adafruit_NeoPixel *strip[NUM_STRIPS];Now, I’m using an array of NeoPixel objects, which will be dynamically created as part of the startup routines. There is the ability to define the pin and number of rings per strip too. In the first version I had three strips defined of 2, 4 and 2 rings respectively, but the 4-ring strip was still causing lost notes. Eventually I settled on four pairs and that seems to work.
Initialising the real pin numbers is a little more complicated now as each strip has to restart from 0 when mapping my 5 LEDs over to the 7 physical LEDs per ring.
Each strip is initialised as follows:
int blockstart = 0;
for (int i=0; i<NUM_STRIPS; i++) {
strip[i] = new Adafruit_NeoPixel (STRIP_BLOCK*stripCounts[i], ledPins[i], STRIP_FORMAT);
strip[i]->begin();
strip[i]->show();
strip[i]->setBrightness(50);
if (i > 0) {
blockstart += stripCounts[i-1];
}
for (int j=0; j<stripCounts[i]; j++) {
for (int k=0; k<LED_BLOCK; k++) {
leds[LED_BLOCK*(blockstart+j) + k] = ledpattern[k] + STRIP_BLOCK*j;
}
}The leds[] array is still a single array with an entry for each “virtual” LED (i.e. one of each of my 5 in use LEDs per ring) and it still has to be initialised with the pattern of real LEDs. This has the benefit that the core interface to the LEDs still gives the impression of a single list of LEDs in a single virtual strip. The only slightly more complicated bit is when it comes to updating the strips from the internal record of which LEDs are on or off.
I know have a new function to scan a single strip
int startled;
void scanOneStrip (int ledStrip) {
if (ledStrip == 0) {
startled = 0;
} else {
startled += LED_BLOCK * stripCounts[ledStrip-1];
}
int numleds = LED_BLOCK * stripCounts[ledStrip];
strip[ledStrip]->clear();
for(int i=startled; i<startled+numleds; i++) {
if (ledState[i]>0) {
strip[ledStrip]->setPixelColor(leds[i], strip[ledStrip]->Color(80, 35, 0));
}
}
}The trick here is to calculate the correct starting LED in the virtual array for this strip and then act accordingly.
There is one dependency that it would be nice to get rid of though – this assumes that each strip will be scanned in order – it calculates the start LED based on the cumulative addition of the strip lengths so far. If this is called out of order, it will probably break.
The controlling function presents the same interface as before, but now allows for repeated calls to scan each strip in turn. Remember a key point of doing things this way was to allow the strip updating to return to allow more MIDI message processing inbetween scanning each strip.
int currentStrip;
void scanStrip () {
if (ledUpdate) {
if (currentStrip < NUM_STRIPS) {
scanOneStrip(currentStrip);
currentStrip++;
} else {
ledUpdate = false;
currentStrip = 0;
}
}
}Notice how the ledUpdate flag is only cleared once all strips have been scanned.
One indication of how much better this approach is, is that I’ve been able to implement a note count – I now keep track of the number of NoteOn vs NoteOff messages for each note, meaning that the lights won’t go out whilst a note is still hanging on. If there were any issues with stuck notes now, these counters would get out of sync very quickly (which they were doing when I tried to have one strip of four rings – hence going down to two).
I’ve kept the global inactivity timer though, just in case.
Closing Thoughts
Whilst obviously a fair bit more complicated both in code and wiring, I was surprised at how well this seems to work.
In the video you can see my Lo-Fi Orchestra arrangement of Sky’s Toccata and it is possible really start to see the shape of the music in the display.
Still completely impractical of course – I mean I’m attempting to map 12 musical “units” (of pitch) onto a display that has 10 display “units” (of LEDs) so it isn’t a natural fit.
But it does now seem to work, and I feel now that if required, and power limits not withstanding, several more pairs of rings could be added each with their own GPIO driver pin and performance ought to keep up fine.
So the question is – do I keep trying other solutions or move onto something else…
Kevin
-
Forbidden Planet “Krell” Display – MIDI Notes
This is my first attempt at some kind of MIDI related visualisation for my Forbidden Planet “Krell” Display. I thought I’d start easy and simply map MIDI notes onto the segments and create a simple display. That turned out to be an awful lot more involved than I imagined…
In fact, this is quite sub-optimal – it largely works but does suffer still from the occasional missed MIDI message, which will almost certainly lead to stuck notes at some point.
In this post I talk through what the issue is and the various mitigations I’ve put in place to attempt to minimise the problem. Finally I present some alternative ideas that I’ll follow up in future posts.
Fundamentally, these days there are much better options for this than an Arduino Nano or Uno.
https://makertube.net/w/qwM4gzPpDSthHY1Mkutr4P
Warning! I strongly recommend using old or second hand equipment for your experiments. I am not responsible for any damage to expensive instruments!
If you are new to Arduino, see the Getting Started pages.
Parts list
- Completed Forbidden Planet “Krell” Display.
- Arduino Nano or Uno.
- MIDI Interface, e.g. DIY MIDI Interfaces, Ready-Made MIDI Modules, and so on.
- Breadboard and jumper wires.
I’ve started with an Arduino Nano, but as we’ll see later, choosing a single-core, 8-bit microcontroller is certainly playing this game on “hard mode”.
I’ve written up what I have for my own interest as it is an interesting problem to solve and interesting to me to see how far I can push it, but if you’re after a more useful solution it is probably worth waiting for a later post where I can show how to use a more suitable microcontroller for this task 🙂
The Circuit
As detailed in my previous post I can just about get away with powering my 8 LED rings from the Arduino provided I keep the power levels down and don’t drive the too much.
I’ve actually used a ready-made MIDI module with a hardware MIDI THRU, again for reasons that will hopefully become clear as I talk about the performance later on.
Using THRU allows me to send data into the Arduino and use that same data to drive a sound source too.
The Code
Once again, I’m using the LED “mapping” technique from my original Forbidden Planet “Krell” Display test code, so that side of things is largely unchanged.
I’m adding in basic MIDI handling using a NoteOn and NoteOff parser to indicate that the LEDs need turning on or off. In this first version I’m just using simple logic as follows:
void handleNoteOn(byte channel, byte pitch, byte velocity) {
if (velocity == 0) {
// Handle this as a "note off" event
handleNoteOff(channel, pitch, velocity);
return;
}
int led = pitch - MIDI_NOTE_START;
ledOn (led);
}
void handleNoteOff(byte channel, byte pitch, byte velocity) {
int led = pitch - MIDI_NOTE_START;
ledOff (led);
}There is some bounds checking added too, but that is essentially it. The downside of this approach is that if several NoteOn messages are received, the first NoteOff message will turn the LED off even if another note is still hanging on.
By default I’ve set it to listen to all channels, but a single channel can be set at the top of the function if required, along with the range of notes to recognise.
#define MIDI_CHANNEL MIDI_CHANNEL_OMNI // 1 to 16 or MIDI_CHANNEL_OMNI
#define MIDI_NOTE_START 48 // C3
#define MIDI_NOTE_END MIDI_NOTE_START+39I experimented with some simple note counting and that would work if the MIDI reception was reliable, but there is a fundamental problem with this code on an 8-bit, single-core, Arduino. The WS2812 LEDs require very precise timing and the Adafruit library has some very hand-crafted assembler running with all interrupts disabled, to achieve it. The longer the string of LEDs, the more time is spent with all interrupts disabled, and so no storing up of, for example, data received over the serial port (MIDI).
This means that I need to ensure as much MIDI handling is done as possible outside of the LED updating, and try to ensure that the actual writing to the LED strip is done as sparingly as possible.
The techniques I’m using to do this include:
- Only allowing writes to the LED strip once every 16 or more so passes through the Arduino’s loop() function, but calling MIDI handling every time (eventually I went for once every 256 scans).
- Ensure that data is only written out to the LEDs if something has actually changed. This means that the Arduino isn’t spending time updating the LED string with the same data, stopping it receiving the next set of MIDI messages.
- Run the MIDI library with Use1ByteParsing = false. This means that each call to MIDI.read() will only return either if there is no data or if the MIDI library has a complete message. Without this, a single NoteOn message requires three calls to MIDI.read() before the message is complete.
- Ensure MIDI THRU is turned off. For serial MIDI, by default, the library provides software-driven MIDI THRU handling which means processor (and serial port) time is spent sending out all MIDI data received. This can be turned off on initialisation using MIDI.turnThruOff().
- Choose an IO pin that wasn’t part of PORTD to ensure no inadvertent clashes with the UART (which is PORTD 0,1). So that means using something in the range D8-D13 (which map onto PORTB for the ATmega328). This probably makes no difference, tbh, but also doesn’t hurt either.
- Add a global inactivity timer to turn all LEDs off after any period with no MIDI activity to catch any stuck notes.
I added a timing GPIO pin to attempt to work out how much time was spent updating the LEDs. It takes just under 2mS to update the strip of 56 (7*8 – there are 7 pixels in each ring, and 8 rings, even though I’m only using 5 per ring myself). Interrupts are disabled for most of that time (from what I can see of the code in the Adafruit library’s show routine). Note, this is quite hand-wavy and the exact timings will depend on the data sent. I believe it is something like 1.2-1.3 uS per bit, so for a single 24-bit pixel (three colour values) that is ~30-35uS per pixel. For a string of 56 pixels that is around 1.7mS in total just for the data. There are some reset and rest times too, so that is where my “almost 2mS” comes from.
MIDI runs at 31250 baud, which I believe means receiving one bit over the serial port every 1/31250 or every 32 uS or so. A complete single byte in MIDI therefore takes around 320uS (there are 8 data bits, one start and one stop bit). So a typical three-byte message is just under 1mS. I don’t know for sure, but it seems like disabling all interrupts long enough to have received two complete three-byte MIDI messages doesn’t seem like a good thing to be doing…
I don’t really know much about the hardware buffer of the UART on the ATMega328 but from conversations on Mastodon (thanks Rue) and having a dig into the USART section of the datasheet, there seems to be a single character buffer, so a 2mS pause would definitely be enough time for 4 or 5 characters to be completely dropped.
This is about as far as I’ve gone using the Adafruit_NeoPixel library as is, with a single string of 40 pixels and MIDI. I have a few thoughts on where to go next, so I’ll explore those in a future post.
Closing Thoughts
This works ok for relatively simple cases and is passable for more complex ones, as long as I’m after effect not accuracy 🙂
Some other things to try include:
- Splitting the string up and using different IO pins on the Arduino to drive the separate elements. A single 7-pixel ring probably takes around 300uS to update – which is comparable with the time taken to receive a single MIDI byte.
- Use a different library (e.g. FastLED) or even hard-code the updates myself (there is an excellent discussion here on how to do that).
- Update: There is a really good description of the interrupt issue on the FastLED Gthub here: https://github.com/FastLED/FastLED/wiki/Interrupt-problems. Looks like FastLED will have the same fundamental issue and if they can’t solve it, I’m unlikely to find a better way myself 🙂
- Use a more modern microcontroller. The Raspberry Pi Pico’s PIO is perfect for things like driving WS2812 LEDs for example. Alternatively a dual-core Pico or ESP32 would allow me to split out the LED updating from the MIDI reception.
- Put a microcontroller in each display unit and string them together with MIDI IN/THRU rather than as a single LED string.
That latter option is quite tempting anyway – a Nano (or even a Micro) equivalent is pretty cheap these days. I could possibly even using something like an ATtiny. This would be an excellent approach if I built a microcontroller PCB for the displays and used those mounting posts I added to the physical design. I could keep using cheap pixel rings or really go for it and mount LEDS on the PCB.
But to be honest, for what I’m doing, I could even get away with a non-addressable LED if I’m adding a microcontroller to each unit…
Kevin
-
Forbidden Planet “Krell” Display – MIDI Notes
This is my first attempt at some kind of MIDI related visualisation for my Forbidden Planet “Krell” Display. I thought I’d start easy and simply map MIDI notes onto the segments and create a simple display. That turned out to be an awful lot more involved than I imagined…
In fact, this is quite sub-optimal – it largely works but does suffer still from the occasional missed MIDI message, which will almost certainly lead to stuck notes at some point.
In this post I talk through what the issue is and the various mitigations I’ve put in place to attempt to minimise the problem. Finally I present some alternative ideas that I’ll follow up in future posts.
Fundamentally, these days there are much better options for this than an Arduino Nano or Uno.
https://makertube.net/w/qwM4gzPpDSthHY1Mkutr4P
Warning! I strongly recommend using old or second hand equipment for your experiments. I am not responsible for any damage to expensive instruments!
If you are new to Arduino, see the Getting Started pages.
Parts list
- Completed Forbidden Planet “Krell” Display.
- Arduino Nano or Uno.
- MIDI Interface, e.g. DIY MIDI Interfaces, Ready-Made MIDI Modules, and so on.
- Breadboard and jumper wires.
I’ve started with an Arduino Nano, but as we’ll see later, choosing a single-core, 8-bit microcontroller is certainly playing this game on “hard mode”.
I’ve written up what I have for my own interest as it is an interesting problem to solve and interesting to me to see how far I can push it, but if you’re after a more useful solution it is probably worth waiting for a later post where I can show how to use a more suitable microcontroller for this task 🙂
The Circuit
As detailed in my previous post I can just about get away with powering my 8 LED rings from the Arduino provided I keep the power levels down and don’t drive the too much.
I’ve actually used a ready-made MIDI module with a hardware MIDI THRU, again for reasons that will hopefully become clear as I talk about the performance later on.
Using THRU allows me to send data into the Arduino and use that same data to drive a sound source too.
The Code
Once again, I’m using the LED “mapping” technique from my original Forbidden Planet “Krell” Display test code, so that side of things is largely unchanged.
I’m adding in basic MIDI handling using a NoteOn and NoteOff parser to indicate that the LEDs need turning on or off. In this first version I’m just using simple logic as follows:
void handleNoteOn(byte channel, byte pitch, byte velocity) {
if (velocity == 0) {
// Handle this as a "note off" event
handleNoteOff(channel, pitch, velocity);
return;
}
int led = pitch - MIDI_NOTE_START;
ledOn (led);
}
void handleNoteOff(byte channel, byte pitch, byte velocity) {
int led = pitch - MIDI_NOTE_START;
ledOff (led);
}There is some bounds checking added too, but that is essentially it. The downside of this approach is that if several NoteOn messages are received, the first NoteOff message will turn the LED off even if another note is still hanging on.
By default I’ve set it to listen to all channels, but a single channel can be set at the top of the function if required, along with the range of notes to recognise.
#define MIDI_CHANNEL MIDI_CHANNEL_OMNI // 1 to 16 or MIDI_CHANNEL_OMNI
#define MIDI_NOTE_START 48 // C3
#define MIDI_NOTE_END MIDI_NOTE_START+39I experimented with some simple note counting and that would work if the MIDI reception was reliable, but there is a fundamental problem with this code on an 8-bit, single-core, Arduino. The WS2812 LEDs require very precise timing and the Adafruit library has some very hand-crafted assembler running with all interrupts disabled, to achieve it. The longer the string of LEDs, the more time is spent with all interrupts disabled, and so no storing up of, for example, data received over the serial port (MIDI).
This means that I need to ensure as much MIDI handling is done as possible outside of the LED updating, and try to ensure that the actual writing to the LED strip is done as sparingly as possible.
The techniques I’m using to do this include:
- Only allowing writes to the LED strip once every 16 or more so passes through the Arduino’s loop() function, but calling MIDI handling every time (eventually I went for once every 256 scans).
- Ensure that data is only written out to the LEDs if something has actually changed. This means that the Arduino isn’t spending time updating the LED string with the same data, stopping it receiving the next set of MIDI messages.
- Run the MIDI library with Use1ByteParsing = false. This means that each call to MIDI.read() will only return either if there is no data or if the MIDI library has a complete message. Without this, a single NoteOn message requires three calls to MIDI.read() before the message is complete.
- Ensure MIDI THRU is turned off. For serial MIDI, by default, the library provides software-driven MIDI THRU handling which means processor (and serial port) time is spent sending out all MIDI data received. This can be turned off on initialisation using MIDI.turnThruOff().
- Choose an IO pin that wasn’t part of PORTD to ensure no inadvertent clashes with the UART (which is PORTD 0,1). So that means using something in the range D8-D13 (which map onto PORTB for the ATmega328). This probably makes no difference, tbh, but also doesn’t hurt either.
- Add a global inactivity timer to turn all LEDs off after any period with no MIDI activity to catch any stuck notes.
I added a timing GPIO pin to attempt to work out how much time was spent updating the LEDs. It takes just under 2mS to update the strip of 56 (7*8 – there are 7 pixels in each ring, and 8 rings, even though I’m only using 5 per ring myself). Interrupts are disabled for most of that time (from what I can see of the code in the Adafruit library’s show routine). Note, this is quite hand-wavy and the exact timings will depend on the data sent. I believe it is something like 1.2-1.3 uS per bit, so for a single 24-bit pixel (three colour values) that is ~30-35uS per pixel. For a string of 56 pixels that is around 1.7mS in total just for the data. There are some reset and rest times too, so that is where my “almost 2mS” comes from.
MIDI runs at 31250 baud, which I believe means receiving one bit over the serial port every 1/31250 or every 32 uS or so. A complete single byte in MIDI therefore takes around 320uS (there are 8 data bits, one start and one stop bit). So a typical three-byte message is just under 1mS. I don’t know for sure, but it seems like disabling all interrupts long enough to have received two complete three-byte MIDI messages doesn’t seem like a good thing to be doing…
I don’t really know much about the hardware buffer of the UART on the ATMega328 but from conversations on Mastodon (thanks Rue) and having a dig into the USART section of the datasheet, there seems to be a single character buffer, so a 2mS pause would definitely be enough time for 4 or 5 characters to be completely dropped.
This is about as far as I’ve gone using the Adafruit_NeoPixel library as is, with a single string of 40 pixels and MIDI. I have a few thoughts on where to go next, so I’ll explore those in a future post.
Closing Thoughts
This works ok for relatively simple cases and is passable for more complex ones, as long as I’m after effect not accuracy 🙂
Some other things to try include:
- Splitting the string up and using different IO pins on the Arduino to drive the separate elements. A single 7-pixel ring probably takes around 300uS to update – which is comparable with the time taken to receive a single MIDI byte.
- Use a different library (e.g. FastLED) or even hard-code the updates myself (there is an excellent discussion here on how to do that).
- Update: There is a really good description of the interrupt issue on the FastLED Gthub here: https://github.com/FastLED/FastLED/wiki/Interrupt-problems. Looks like FastLED will have the same fundamental issue and if they can’t solve it, I’m unlikely to find a better way myself 🙂
- Use a more modern microcontroller. The Raspberry Pi Pico’s PIO is perfect for things like driving WS2812 LEDs for example. Alternatively a dual-core Pico or ESP32 would allow me to split out the LED updating from the MIDI reception.
- Put a microcontroller in each display unit and string them together with MIDI IN/THRU rather than as a single LED string.
That latter option is quite tempting anyway – a Nano (or even a Micro) equivalent is pretty cheap these days. I could possibly even using something like an ATtiny. This would be an excellent approach if I built a microcontroller PCB for the displays and used those mounting posts I added to the physical design. I could keep using cheap pixel rings or really go for it and mount LEDS on the PCB.
But to be honest, for what I’m doing, I could even get away with a non-addressable LED if I’m adding a microcontroller to each unit…
Kevin
-
All design files and test code for my Forbidden Planet "Krell" display are now published: https://diyelectromusic.com/2025/01/25/forbidden-planet-krell-display/
Now I can start work on some of those musical ideas I have for it.
-
Just bought Dead Air (solo RPG book) at Forbidden Planet in Glasgow. Not often you get a game set in Strathclyde.
#DeadAir #SleepySparrow #geama #games #GeamaBuird #BoardGames #TTRPG #alba #scotland #SrathChluaidh #strathclyde #ForbiddenPlanet -
‘Forbidden Planet’ Set By Warner Bros: Brian K. Vaughan Writing & Emma Watts Producing Revisionist Version Of Touchstone 1956 Sci-Fi Pic
#News #BrianKVaughan #EmmaWatts #ForbiddenPlanet #WarnerBros -
What is your favorite (iconic) Star Ship from classic Science Fiction.
If not listed, comment, you might list something I've never seen or thought of! 🙂
#SCIFI #TV #Movie #Classic #Iconic #StarShip #Poll #ThisIslandEarth #ForbiddenPlanet #LostInSpace #StarTrekTOS #StarTrek
#Metaluna #C57D #USSEnterprise #NCC1701 #Jupiter2 -
The 4th was with us as we got to three shops city-centre Northside and Southside, and then out to Dundrum. Well organised and super-friendly staff in Forbidden Planet and at 4pm there was still a healthy queue outside Big Bang. Good vibes.
#free_comic_book_day #FreeComicBook #FreeComicBookDay #Comics #Dublin #MayThe4th #Mastodaoine #SubCity #ForbiddenPlanet #BigBangComics -
🧵 Yeah, I'm watching Forbidden Planet on Tubi with commercial breaks.
It's got Leslie Nielsen in it. Yes, the very same Leslie Nielsen who said, "Don't call me Shirley" in Airplane. This was back when he played leading men in serious movies.
It's a real sausage fest in the ship. Not one woman. One of the guys asked what gender Robby the Robot was, and the robot wisely answered that the question does not apply.
I'm writing this during a break. Will continue the thread during the next breaks.
-
Just noticed a few folks with a #7filmstoknowme hash/meme
So here are seven for me without a lot of deep thought or prioritizing, but my first draft had a too-obvious theme of newspaper-plots. But I would really like to do one list per decade.
#HisGirlFriday
#MyManGodfrey
#DeadlineUSA
#ForbiddenPlanet
#BornYesterday
#Serenity
#TheBoysAndGirlFromCountyClare -
Just noticed a few folks with a #7filmstoknowme hash/meme
So here are seven for me without a lot of deep thought or prioritizing, but my first draft had a too-obvious theme of newspaper-plots. But I would really like to do one list per decade.
#HisGirlFriday
#MyManGodfrey
#DeadlineUSA
#ForbiddenPlanet
#BornYesterday
#Serenity
#TheBoysAndGirlFromCountyClare -
1956 Film Poll - Final Round
One-Day Poll - Followed by one day 'off')
Top two films advance to the 1950's Film Tournament
In case of ties, I will make the decision how to break them.#Film #Films #Movie #Movies #FilmCommunity #Cinema #CineMastodon #ClassicFilms
#ForbiddenPlanet
#TheTenCommandments
#TheSearchers
#InvasionOfTheBodySnatchers