#Neopixel

2025-04-23

Another #NeoPixel project, another abstract clock. Well, just a timer for now until I get an RTC sorted.

I have a #TM1637 6-digit 7-segment LED display and a pair of #NeoPixel rings representing elapsed time.

The outer 24 LED ring uses red to show hours, and blue to show twentieths of a second. The inner 12 LED ring shows minutes in green and seconds in blue, each one a step of 5.

Running on an Arduino Pro-mini... because I could not get the NeoPixels to behave with any library on an #Uno R4!

On the left side there is a 6-digit 7-segment LED display showing an elapsed time of 00h17m06s. On the right side are a pair of NeoPixel rings, one inside the other, telling the same time. The outer ring of 24 LEDs represent hours in red, and an inner ring of 12 LEDs represents minutes in green and seconds in blue. A blue LED races around the outer ring, lighting a different LED every twentieth of a second.
2025-04-16

Saw this project on #Instructables from #Moononournation instructables.com/IoT-Emoji-Si
It's a fun project, but I was more interested in the 8x8 #Neopixel #Matrix
So I bought a couple of the #Waveshare #ESP32S3 8x8 boards, and printed out a couple of cases.
The boards work really well - I had an idea in mind when I ordered them, but now I forgot what I wanted to do with them.... I guess I'll make an #emjoi #display after all..... LOL

a couple of Waveshare ESP32S3 8x8 Matrix boards without casesa Waveshare 8x8 ESP32S3 Matrix in a black case with a black defuser....works pretty well under a black defuser - but I really had to bump the brightness of the neopixels up to really see the effects.  This is running the fastLED Demo100 program2 Waveshare 8x8 Matrix boards within 3d printed black cases, one with a black defuser and one with a white defuser. Not on, or displaying anything.  
The white defuser (personally) I think works better then the black, and I can lower the brightness of the leds and it still looks very bright.
Simple DIY Electronic Music Projectsdiyelectromusic.com@diyelectromusic.com
2025-04-04

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

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:

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.

Find it on GitHub here.

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

Simple DIY Electronic Music Projectsdiyelectromusic.com@diyelectromusic.com
2025-04-03

Forbidden Planet “Krell” Display EuroRack Module

This project uses my Forbidden Planet “Krell” Display and the Forbidden Planet “Krell” Display PCB Design but with some slight variations that means it could be EuroRack mounted with a control voltage (CV) input.

This is a DIY module only for use in my own DIY system.

Do NOT use this alongside expensive modules in an expensive rack. It is highly likely to cause problems with your power supply and could even damage your other modules.

https://makertube.net/w/qJqgTxxsEznTuF2DRVZT9o

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 microcontrollers, see the Getting Started pages.

Parts list

EuroRack 3D Print Design

This is an evolution of my original Forbidden Planet “Krell” Display box, but fitting into EuroRack dimensions: 128.5 x 60, which essentially makes it a 12 HP module.

It still takes the same inserts however, but now also includes options for holes for jack sockets or potentiometers:

show_eurorack = 1;
show_eurorack_support = 1;

alg_pot1 = 1;
alg_pot2 = 1;
alg_cv = 0;

I’ve also included a special “supports” option for use with the PCB and the EuroRack case.

Krell Display PCB – EuroRack Build

To build one of my Forbidden Planet “Krell” Display PCB Designs for use with a EuroRack, follow the previous Build Guide but note the following differences:

  • The MIDI circuits are not required when used as a CV input device.
  • The lower potentiometer should be replaced with a CV input circuit.
  • The upper potentiometer is optional, but I’m omitting it for my build.
  • Power will come via the 5V jumper headers from an additional EuroRack power PCB (details below).
  • Low-profile (e.g. 9mm high in total) headers should be used for the Waveshare Zero, but once again note the errata about the footprint on the PCB being too wide.

Here are some build photos of a build for EuroRack use. For this build there are only two diodes (the two BAT43) and two resistors (22K and 33K). Also note that none of the 100nF ceramic capacitors are required either.

Both electrolytic capacitors have been soldered into position on their sides as show below.

The Thonkiconn style mono jack shares the footprint are of the lower potentiometer on the LED side of the board, but be sure to get use the correct mounting holes as shown by the orientation below.

Nothing has been soldered to the power jumper yet. See the discussion below for how to link this to the power board.

Krell Display Companion EuroRack Power PCB

Bill of Materials:

  • Waveshare Zero “Krell” Display EuroRack power PCB (Github Link below).
  • L7805 TO-220 format regulator or equivalent (see discussion below).
  • 1x 16-way DIP EuroRack shrouded header.
  • 1x 1N5017 Zener diode.
  • 2x 47uF electrolytic capacitors.
  • 1x 100nF ceramic capacitor.
  • 2-way Jumper header socket and pins (probably need extended pins – see discussion).

I’ve opted to use a DC-DC converter with a 7805 physical footprint as shown below.

If a 7805 regulator is used then a heatsink will almost certainly be required. I’ve oriented the regular to allow for a “tab up” mounting which hopefully leaves plenty of room for some kind of heatsink to be used.

Here are some build photos.

There is an option on the PCB to install a 10R resistor as is sometimes recommended for EuroRack modules. From what I’ve read this seems to be to allow it to act as a “fuse” in the case of an incorrectly wired module. As I’ve discussed before (see here) I’m not sure this is so relevant for me, so I’m using the provided solder bypass bridge to leave it out.

Note the orientation of the DC-DC converter.

I’ve used extended pin headers for the power link between the two boards, but due to an error in positioning, they’ve had to be bent over slightly – more on that later.

Physical Build

A completed unit has the following parts:

  • 3D printed case, PCB supports, and two “krell” inserts.
  • Main PCB built for EuroRack use as described above.
  • Power PCB as described above.
  • M2.5 spacers and fixings as follows:
    • 4x 6mm M2.5 brass fixings.
    • 4x 15mm M2.5 nylon fixings.
    • 4x M2.5 nylon screws.

The power link between the two PCBs has to be trimmed and slightly bent as shown below.

Once the whole thing is put together, there isn’t room, at least on my build, for the nut to be put on the jack socket. Also, the 6mm and 15mm spacers might be slightly too short, depending on how far off the PCBs the LEDs ended up. Some experimentation and “encouragement” is probably required to get everything together.

The Code

The code is relatively straight forward, and is largely a mix of the analog and neopixel test code from the Forbidden Planet “Krell” Display PCB Build Guide.

One quirk is scaling the analog read from 0..65535 to a useful 0-10 to allow for zero to 10 leds to light up. I’ve allowed for a range of values to be “basically zero” too to allow for some jitter or noise.

As I only write out to the neopixels when something changes, this code seems to be quite responsive.

This requires the following Adafruit Circuitpython Library Bundle libraries:

  • neopixel.mpy
  • adafruit_pioasm.mpy
  • adafruit_pixelbuf.mpy

In fact, the entire Circuitpython code is given below.

import time
import board
import neopixel
from analogio import AnalogIn

cv_in = AnalogIn(board.A3)

pixel_pin1 = board.GP2
pixel_pin2 = board.GP3
num_pixels = 5

pixels1 = neopixel.NeoPixel(pixel_pin1, num_pixels, brightness=0.3, auto_write=False, pixel_order=neopixel.RGB)
pixels2 = neopixel.NeoPixel(pixel_pin2, num_pixels, brightness=0.3, auto_write=False, pixel_order=neopixel.RGB)

col = (80, 35, 0)

lastcv = -1
while True:
cv = cv_in.value / 256

if (lastcv != cv):
lastcv = cv
led = cv / 25
for pix in range(5):
if (pix < led and cv > 5):
pixels1[pix] = col
else:
pixels1[pix] = 0

if (pix+5 < led and cv > 5):
pixels2[pix] = col
else:
pixels2[pix] = 0

pixels1.show()
pixels2.show()

GiHub Resources

There is now an updated version of the OpenSCAD code for the case on GitHub and the PCB and code are also now available.

Closing Thoughts

This isn’t a perfect build in mechanical terms, but I’m not sure I ever do anything perfectly anyway, especially where mechanical things are concerned, but the final result is pretty pleasing.

The video shows it running with a Pimoroni RP2040 in the driving seat. First a potentiometer provides a 0 to 5V input, then I’m using my Educational DIY Synth Thing‘s LFO to provide a 0 to 3V3 input.

Kevin

#circuitpython #EuroRack #Krell #NeoPixel #potentiometer

2025-03-29

I have hit a tough spot in an existing project, so while I think about it, how about a distraction project!

Behold a NeoPixel clock ⌚

An abstract (to me) clock using 2 NeoPixel rings to indicate the time using the position and colour of the pixels.

I added a TM1637 based 6-digit 7-segment display too, because it was on the table beside me, and why not?

More ideas to implement, but pleased with it so far.

All the code on GitHub. Enjoy!

github.com/ilneill/NeoPixelClo

#Arduino
#NeoPixel
#TM1637

A breadboard with a couple of 12 LED NeoPixel rings abstractly roughly telling me the time is 03:35:46.

A 6-digit 7-segment LED display in front of the NeoPixels confirms this time exactly.

All this is being driven by an Arduino Pro Mini  that can be seen in the background.
Andy Warburton ❌❌❌andy_warb
2025-03-28

I think I’m happy with this enclosure design! All goes together with friction. No screws needed!

2025-02-16

Having some #NeoPixel fun!

It is incredibly simple to write code for these things, even with just a small #Arduino.

Here I have 2x 12 RGB pixel rings, one daisy chained from the other. Just tell the library you have 24 pixels and you are off to the races.

It draws rings and the infinity symbol in a variety of colours controlled by some nested RGB loops.

Daniel Buzzodanbz
2025-02-13

Today is experimenting with and - got one working with servo controller and ring - working on the other with ultrasonic distance sensors …

Colin 🐈🌱Colin@meow.social
2025-01-29

I got #Neopixel working on the #CH32V003, working quite well.

Simple DIY Electronic Music Projectsdiyelectromusic.com@diyelectromusic.com
2025-01-26

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

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.

Find it on GitHub here.

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

#arduino #define #ForbiddenPlanet #Krell #NeoPixel

Simple DIY Electronic Music Projectsdiyelectromusic.com@diyelectromusic.com
2025-01-26

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

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+39

I 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.

Find it on GitHub here.

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).
  • 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

#arduino #define #ForbiddenPlanet #Krell #NeoPixel

Simple DIY Electronic Music Projectsdiyelectromusic.com@diyelectromusic.com
2025-01-25

Forbidden Planet “Krell” Display

If you’re not familiar with The Forbidden Planet, then it is an iconic 1956 Sci-Fi movie with an absolutely ground-breaking soundtrack of “Electronic Tonalities” by Bebe and Louis Barron.

In one scene, when the humans visit an alien (the “Krell”) science lab there is a large set of display dials around the room that logarithmically show the power being generated by the Krell machine and I’ve been thinking for a while I’d like to try to reproduce them in a way that I could then use for something musical.

This post details the 3D and electronic design for my version of the Krell’s power indicators. The musical bit will hopefully follow at some point.

https://makertube.net/w/wmXGgm9GUeztDXn1K3nhmG

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 or 3D printing, see the Getting Started pages.

Parts list

  • 3D printed Krell display unit
  • Arduino Nano or Uno
  • Several 7-way “neopixel”-like WS2812 5050 rings of LEDs (one per display face)
  • Breadboard and jumper wires

Design and 3D Printed Case

I’ve opted to build the display in units of two or four. The original Krell setup has gauges one above the other as can be seen in this capture from the film.

I’ve designed the display in four parts as shown below (these are early versions, but you get the idea).

The required “neopixel”-like rings are also shown. I actually only need 5 LEDs per display, but I need them to map onto the 5 cut-out segments on the display. This means that the bottom and centre LEDs are not used, but the other 5 map on quite nicely to the other of the six segments in the display.

OpenSCAD Code

I’ve used OpenSCAD and the code for all parts is in a single file. This means that any definitions relating to dimensions and scale can be used by all parts. Which part gets rendered and shown is selected at the top of the code.

show_frame = 1;
show_insert = 0;
show_support = 1;
show_quadframe = 0;
show_quadsupport = 0;

The inserts are the (white) display faces, and two of these are required per twin display. They also need a frame and optionally a support (if using the LED rings).

There is also a “quad” version of the frame and support which allows for a four-way display, which naturally will then require four inserts printing.

I’ve just used standard white PLA for the inserts and that seems to diffuse the LEDs nicely once lit. The frame and supports I’ve just used black and blue PLA respectively because that was what I had to hand at the time.

Here are the key parts in OpenSCAD for the dual-display.

And these are the parts for the quad display:

The actual insert for each display panel is a pretty complex object and takes a while to render on the display when moving and zooming. And even longer to render as an STL. There is probably a better way to design this, but it works ok for me.

In terms of the OpenSCAD code, there are the following modules:

  • supports() – used to build the supporting partitioning for a single face of the display. This is called twice for a twin display and four times for a quad display.
  • krell() – builds the display face itself for a single display, but is also used for the cutout for the face in the main frame. Again used twice in the twin display and four times for the quad.
  • krell_mark() – used to create each of the four triangles that are part of each single display face.
  • pcbfixing() – used to create a pillar with a M2 sized hole that could be used to mount a PCB.
  • sector() and arc() – used to build the six individual segments. It is taken from https://openhome.cc/eGossip/OpenSCAD/SectorArc.html

It’s perhaps not the most efficient, and certainly is the cause of the longer rendering times for the insert, but I’ve made quite heavy use of difference() and union() to create the various cut-outs and masked-off areas.

The face panel was particularly challenging, using combinations of spheres and cylinders. I particularly wanted the spheres to be hollow so they didn’t show up darker when illuminated from behind. Packing the spheres in also involved calculating the vertical distance using the formula: vertical position = radius * SQRT (3) and then offsetting the start of the next row by a single radius.

Design notes:

  • I planned to allow for a PCB to be made and mounted in the case. This would make for a nice, self-contained unit, hence the PCB fixing points. But in the end opted for the “neopixel” style rings and jumper wires.
  • The supporting partitions originally included mounting points for the M2 holes in the rings, but they proved either too small and brittle or too large. I don’t know if that was an issue that could be solved by tweaking the resolution of the print, but in the end the rings wedge in fairly well without them.
  • There is little provision for wiring at the moment or for mounting a microcontroller. The units themselves are cases and LEDs rings only.
  • I’ve not found any dimensions online for the displays, but from photos of props that have been sold online, I decided on the ratio 65:100 for the displays, so used that in mm for my twin display. They “feel about right” to me.

Find the source and STL files on GitHub here.

Arduino Electronic Control

I’m using an Arduino Nano but pretty much any 5V microcontroller would do. If using a 3V3 microcontroller, then level shifting would probably be required as these LED rings really do nee 5V for power and signals.

The LED rings are collections of WS2812 or compatible 5050 (i.e. 5mm square) multi-colour addressable LEDs. Adafruit call these “NeoPixels” and have a very comprehensive guide for using them here: https://learn.adafruit.com/adafruit-neopixel-uberguide

The rings that I have, have two sets of three solder pads on the rear. Both sets have VCC and GND, but one is a signal IN and one is a signal OUT. This allows them to be chained together as shown above. Two rings are required for a single dual-face unit. Some rings might have pads, holes or even connectors.

The Adafruit Uberguide talks in detail about powering these rings, especially when used in long strings for large displays. As a general rule, the recommendation is to allow for 20mA per “pixel” up to a maximum of 60mA for full brightness with all LEDS on per “pixel”.

As the Arduino can support up to 800mA via its 5V pin and I’m planning on using 8 display faces, each with 5 LEDs per face, that gives an estimate of:

  • 8 x 5 x 20mA = 800 mA as a typical draw.
  • 8 x 5 x 60mA = 2.4A peak for full brightness, all LEDs.

I think I can just about get away with driving my 8 faces from a Nano as long as I’m not expecting to turn everything on at full brightness – more on that in a moment when I get to the example code.

If I wanted to support something nearer the peak current I would need a separate power supply providing 5V and around 2A to the LEDs. That could probably be wired to provide a 5V link directly into the Arduino’s 5V pin too. However, this is not recommended though due to the potential for mistakes, noisy signals, and interrupts in supply, as this bypasses the regulator and any protection circuits on the Arduino.

But if I’m careful, it will be fine as an option for me if I need it.

The Code

Driving WS2812 LEDs is pretty straight forward thanks to the Adafruit_NeoPixel library for Arduino which is easily installed via the Library Manager.

One complication I have is that I need to translate between the order and number of LEDs on the rings and the 5 LEDs per ring I want to be using.

The ordering of my LEDs is as follows:

But that might be different for different rings of course. The following code is a simple test to illuminate each LED in turn allowing me to find the order, and shows all the key principles of how to turn the pixels on or off:

#include <Adafruit_NeoPixel.h>

#define LED_PIN 6
#define LED_COUNT 14

Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

void clearStrip () {
for(int i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, strip.Color(0, 0, 0));
}
}

void setup() {
strip.begin();
strip.show();
strip.setBrightness(50);
}

void loop() {
for(int i=0; i<strip.numPixels(); i++) {
clearStrip();
strip.setPixelColor(i, strip.Color(80, 35, 0));
strip.show();
delay(500);
}
}

The definitions used in the Adafruit_NeoPixel initialisation (NEO_GRB+NEO_KHZ800) work for my rings, but there are several options. Try some of the library examples and consult the Uberguide for details if the rings aren’t working.

In order to map this order over to just the LEDs I need to use for my Krell display, I need two “lists” of LEDs – the real one representing the physical order the 7 LEDs per ring appear on the rings themselves, especially when linked together; and a virtual one representing the desired order of the 5 LEDs per ring I’m interested in using.

I do that via the following definitions and code:

#define LED_PIN   6
#define LED_BLOCK 5
#define LED_RINGS 8
#define LED_COUNT (LED_BLOCK*LED_RINGS)
#define STRIP_BLOCK 7
#define STRIP_COUNT (LED_RINGS*STRIP_BLOCK)

int ledpattern[LED_BLOCK] = {1,0,5,4,3};
int leds[LED_COUNT];

void setup() {
for (int i=0; i<LED_RINGS; i++) {
for (int j=0; j<LED_BLOCK; j++) {
leds[LED_BLOCK*i + j] = ledpattern[j] + STRIP_BLOCK*i;
}
}
...
}

The ledpattern[] array lists which physical LED corresponds to my five virtual LEDs. The leds[] array will expand this list to the number of rings, giving offsets for all physical LEDs used to map onto all my virtual LEDs.

In order to allow this to be changed to match the number of rings used, simply by changing the #defines at the top of the code, leds[] is initialised in code as part of setup(). For two rings in a twin display, this maps virtual LEDS 0 to 9 onto real LEDS 0 to 13, with four of them being unused. For four rings in a quad display, this will map 0 to 19 onto 0 to 27, and so on.

In order to use this with the Adafruit functions, I just take my virtual LED number and use that as an index into leds[] to get the real LED number, for example:

  for(int i=0; i<LED_COUNT; i++) {
clearStrip();
strip.setPixelColor(leds[i], strip.Color(80, 35, 0));
strip.show();
delay(200);
}

I have some example code to test all LEDs. The simple version just illuminates each LED in turn, using the above code. An alternative version will read a potentiometer and use that to determine how many LEDs to illuminate.

With the correct wiring sequence and pattern of LEDs it is possible to mimic the order of the illumination of the panels in the original film.

A note on colour, brightness and power.

As previously discussed, I’m working on the basis that not all LEDs will be on at full brightness and so can get away with powering my display simply from an Arduino. For this to be true, I’m working with the following constraints:

  • No more than 8 rings are used. In my case that is two dual displays and one quad display.
  • Not all LEDs are used for the colours. I’m using: strip.Color(80, 35, 0) which leaves on LED of each of the three in each pixel off and gives a nice, nostalgic, colouring which to my mind matches that used in the film quite well.
  • Brightness is set relatively low, using: strip.setBrightness(50), which is less than a quarter brightness (the maximum is 255).

Find the test code on GitHub here.

Closing Thoughts

I’m really pleased with how this has turned out. It took a little trial and error to get the parts to fit and work, but the colouring through the white PLA is quite pleasing to me. The partitions also work well to allow individual control of the segments without the light bleeding through.

The simple code with a potentiometer control shows the potential. I have a few ideas for how to use this with MIDI, but those can come in a future post.

Kevin

#arduino #ForbiddenPlanet #Krell #NeoPixel

STM32Worldstm32world
2025-01-19

STM32 Tutorial #37 - Cool RGB LEDs (WS2812 aka. NeoPixel)
Driving WS2812 NeoPixel RGB LEDs with a STM32. In this video we'll go through my library which uses Timer PWM + DMA to drive a string WS2812 NeoPixel RGB LEDs.

youtube.com/watch?v=mdZerUTFJUw

2025-01-11

Ended up doing a bit of Arduino coding as my soldering gear was not returned as expected... Some excuse about the cold 🤔

In truth, it has not got above freezing all day, and even the cat did not venture out.

Anyway, behold some NeoPixel goodness. Literally 10 mins coding on the Adafruit "simple" Library example.

#Arduino
#coding
#neopixel

Simon Walters on BlueSkycymplecy.bsky.social@bsky.brid.gy
2024-12-29

And now with added #Neopixel goodness :)

OLED display saying red with 3 Neopixels lighting up red as wellMicroblocks script responding to red broadcast being received to write red to the disaply and turn the Neopixels red as well
Mats :opensuse: :debian:skyhopper4697@toot.teckids.org
2024-12-15

Am Neopixel-Tannenbaum für die #38C3-Assembly von @Teckids mit @macked47, @tuxilio und @mwinter basteln

#teckids #neopixel #tannenbaum

3 Jugendliche und ein Erwachsener, die um eine Leiter sitzen, die mit LEDs geschmückt ist.
kaybeeque 🍁💪💪🍁kaybee335@fosstodon.org
2024-12-12

A massive improvement in the quality of the #neopixel fairy lights between the first generation ones I had already and what is now shipping.

Much, much more durable, less prone to tangles, much easier to string. What's not to like?

#adafruit 4560

Two strings of neopixels above a carpet. 

The string in the top of the picture is the first generation. It is individual coated wires for 5V, GND and DATA which are very prone to tangling, kinking, snagging and if you're unlucky, breaking.

The bottom string is the new style with the wires enclosed in silicon like a ribbon cable and better silicon protection around the individual bulbs. They are a little more diffuse and not quite as 'sparkly' as the originals when lit.A close up shot of the old style string showing the individual wires and the almost impossibility of getting all the wires running straight and clean.A close up shot of the new style showing the nice clean, straight wiring achieved by the 'ribbon' cable and also showing the more diffuse bulb.
kaybeeque 🍁💪💪🍁kaybee335@fosstodon.org
2024-12-10

First #PixelBlaze Feature Request:

Please place a prominent notice on the product page warning potential purchasers of the extremely addictive nature of this product.

I started with one #neopixel project and I now have ten more. Dangerously addictive. What's the bulk purchase discount? I may need to know.

I just made a digital fireplace in less than 15 minutes! 🤯

These things are LED crack!

And I made my first change to a mapper!

kaybeeque 🍁💪💪🍁kaybee335@fosstodon.org
2024-12-10

🤦‍♂️🤦‍♂️🤦‍♂️

Guess who's got another four strings of #neopixel fairy lights on the way?

And another #PixelBlaze Standard and Pico?

🤦‍♂️🤦‍♂️🤦‍♂️

150 LEDs per 1 meter high tree. And earlier I thought of a tree topper I can make with available parts. That adds another 33!

I suspect I will have to limit the overall brightness level to stay within 3 amps.
😎

kaybeeque 🍁💪💪🍁kaybee335@fosstodon.org
2024-12-08

How the heck do you successfully straighten out long #neopixel fairy light strings when you are permitted to live with a cat?

This is not going well!

Time to try air suspension.

Uh. Maybe a *bit* higher. This is generating too much interest again!

#CatsOfMastodon #BlackCat

Fluffy black cat thoughtfully eyeing the two strings of LED lights suspended above his head to try and straighten them. 

I strongly suspect that we have different ideas about what 'straighten' means.

There is also a litter of cardboard boxes in the background that he refuses to let me recycle.

Client Info

Server: https://mastodon.social
Version: 2025.04
Repository: https://github.com/cyevgeniy/lmst