Feature

Walking Black Hole

A costume for Book Week

Rob Bell

Issue 76, November 2023

Sometimes we make to last. Other times, we make something purely to last a few hours.

There’s always been a joke that many guys can fix anything with WD40 and Duct Tape. If it doesn’t move and should - WD40, if it moves and shouldn’t - Duct Tape. While these solutions might feel temporary (say, if you’re trying to fix plumbing with duct tape), there are times when temporary solutions are perfectly adequate.

However when my son came to me for his school’s Book Week parade, and wanted to go as a Black Hole, it was clearly not something that could be solved with a quick trip to Base Warehouse or any other store that offers cheap costumes for the purpose.

My first thought was realising that sometimes we don’t need to over-engineer things when it only needs to provide a temporary solution.

After all, this is a costume that’s only going to be used once, and for a few minutes at most. Going to the trouble of 3D modelling, printing, and other methods that we’d ordinarily employ for a DIYODE project simply didn’t feel justified.

It also needs to be undertaken with the temporary objective, which is a single-use option.

THE CONCEPT

Image Credit: eso.org

Now it’s somewhat difficult to portray an actual black hole in a costume. After all, this is something which can range from a few times the size of our sun, to TON618 which is the biggest Black Hole we know about with over 66-billion times the mass of our own sun.

While no human has seen one up-close, they vary significantly. Therefore, taking inspiration from an “artist’s impression” is probably the best way to portray it and have people understand what they’re seeing.

With this in mind, we’re going to focus on the interesting parts of a black hole, namely the accretion disc and event horizon. After all, the centre of a black hole you can't see, you simply see the absence of light (or more accurately, the light can't escape the black hole's gravity, so there's plenty in there but it can't escape so we can observe it).

With an all-black costume taking care of the singularity portion as best we can, the accretion disc and event horizon could be portrayed using lights.

Naturally, we took some creative license with how this was represented, given time and budget constraints, and that it was a temporary project. With the approach we took, at worst if people didn't understand what it was, it would appear like an atom, with electrons orbiting a nucleus.

THE METAL FRAME

Originally, I thought about using some hoola hoops or something similar to mount the addressable LED strip, however a quick trip to Bunnings and I found some 3m lengths of 12 x 3mm aluminium. They’re light yet solid, so it could be bent to my will to take whatever shape I needed.

First, since I had two lengths of Aluminium, I taped them together in a few places so that my eventual shape was fairly similar between the two coils.

I was pondering how to form these long strips into circles, and decided to try using a gym weight place for the purpose.

I clamped the end of the Aluminium to the gym weight and grabbed a rubber mallet to try and begin forming.

It quickly became evident however, that the aluminium was too springy to really be bend this way, and not want to recoil when it was unclamped. I pulled it around to form a full circle and clamped it in that position, hoping that the metal would fatigue.

I tried a smaller weight, thinking that I could "over-bend" the aluminium so that when it recoiled it still had some shape.

In the end, this didn't really work. Yet amongst my frustration of its lack of compliance to my projects' desires, I grabbed it by hand and managed to bend it far more easily than i thought.

While I thought that I might end up making an octagonal shape or something using this method, it seemed to be pliable enough by hand to make it happen. After the LED strip was added and it was all done, I figured it was unlikley to matter much at all.

Now that I had some kind of formed circular structure (as crude as it was), it was time to start sorting out the electronics. Each strip of aluminium made about 1.5x wraps around, which was more than enough.

Then I cut the tape holding them together and got to work.

THE LED STRIP

I thought about a handful of ways to mount and wire the LED strip to the aluminum. Adhesive, glue, clips... but once again given the time constraints and low-use nature of the project, I decided that plenty of electrical tape was the simplest way to go.

There was one consideration however - electronics. We have seen a number of instances where LED strip can become dim towards the end of the run. Particularly since we would be running over 6m of strip.

We also weren't precisely sure how we were going to wire the strip just yet. I also figured that since I was removing the strip from the insulating case, I should insulate the aluminum too. After all, there are solder joints along the strip that could easily short out on the aluminum.

Fortunately, I already had the solution. More tape!

I proceeded to run wires for power and data, binding it to the aluminium strip with electrical tape. This held everything in place, and insulated the aluminium at the same time.

At this point I wasn't precisely sure whether we would need or want the wires, but figured it was easier to add it and not use it than need to add it later on.

I then followed by removing the PVC jacket from the LED strip, and using electrical tape at regular intervals to hold it in place.

This is fairly dense LED strip, so unfortunately the tape didn't fit between LEDs nicely. I was going to trim the tape to ensure no LEDs were obscured but once it was powered up for the first time, I ultimately decided it didn't matter.

The end-result was two aluminium "rings", with LED strip and power/data cables. The wires were left as pigtails until I decided how to wire it.

THE DRIVER CIRCUIT

The only real challenge here was deciding how best to power the LED strip and Arduino, while keeping things lightweight and fully portable.

Typically, WS2812 strip runs at around 1A per metre. With 2 x 3m lengths of strip, we could be looking at around 6A of current draw, plus a little for the Arduino running the show.

While the reality is that most school book week parades only last a few minutes, perhaps 30 minutes for everyone from start to finish, I didn't want to have a scenario where my son comes home from school, and the only answer to my query of "how did it go" be "it didn't work".

With this in mind, the battery pack is the one area where this costume is over-engineered. We decided to use a 7.5Ah 12.8V LiPo battery. This could theoretically run the whole show for a few hours.

Naturally, we can't run WS2812 strip from 12V, the control chips on each LED fail rather rapidly. We used two 3A DC-DC converters from Jaycar to provide us with ample power, while adding a 1,000uF capacitor to the outputs on both modules, to smooth out any voltage fluctuations.

Originally we had planned to use an ATtiny85 module we've been playing a lot with recently. Our code was going to be lightweight so the ATtiny was a logical choice.

We started developing the driver board circuit on some high density foam sheet, since once again, this was all going to be relatively temporary.

We started wiring everything up by providing battery power to the DC-DC modules, and 5V output to the ATtiny.

We added a resistor to D1 as recommended for control of WS2812 chips.

We ultimately decided to leave the two LED strips in series, to provide a single data line. By simply mounting one of the strips upside down, we would achieve the helix effect with counter-rotating LED patterns, even though they were being driven as one line of LED strip. We did use quick-connectors however, in case we changed our mind later.

We also added a lamp switch so once it was mounted, it could easily be switched on and off. This simply interrupted the entire battery supply, so nothing was drawing power while the costume wasn't being used.

We quickly recognised the potential of destroying the ATtiny85 when programming, as any voltage difference between the USB connection and the power from the DC modules could flow through the board. A simple toggle switch was added to disconnect power from the DC modules when programming.

Unfortunately, we had a little trouble programming the ATtiny module, despite using them quite a bit recently. While we could have figured it out, the timeline required fast thinking so we switched to a spare UNO which we mounted on the side of the battery, and simple incorporated the wiring.

Once we switched to the UNO and loaded some demo code, everything came to life as expected.

We tidied up a little bit of wiring and firmed up some connections once it was all working, to help avoid any connections pulling free.

The benefit of a Lithium battery here is also that there's a built-in battery management system to protect from any short circuit conditions. It's also far lighter than a Sealed Lead Acid equivalent, but safety was a big consideration since my son was going to take this to school.

MOUNTING

The next challenge was how to mount all of this to make it a removeable costume. My first thought was to make a sort of harness from Gaffers tape. I have made some pretty good carry handles and other things using Gaffers tape before. However I was worried about his ability to remove it when it wasn't needed.

Fortunately, after digging around the house, I found a backpack which had a space theme print too!

Not wanting to cause any damage to a perfectly good backpack however, I decided to create some loops from Gaffers tape that I could use to thread string or fishing line through. Effectively creating an anchor point that could easily be removed after the costume had been used.

I wrapped tape around the straps for the backpack, then reverse-mounted a loop on the top (sticky side out), so I would be able to thread things through easily. Then I covered it in more tape to cover the adhesive side.

I then proceeded to thread fishing line through the loops I had created. At this point I didn't really know precisely how I would mount the LED strips, so just left a few metres of line on either side, about 8 lengths on each side of the bag.

I took the whole project home to test-fit it with my son wearing the bag. Since the LEDs were going to hang around him, I really couldn't estimate how things would sit without someone his size wearing the bag, and would likely have to redo it.

We quickly got things mounted to test it all out, and it was looking amazing!

Sadly, my poor knot-tying skills made using fishing line something of a challenge. My knots kept slipping and it wasn't working the way I would have liked.

Once again, with consideration to the timeline, I switched the fishing line out for regular string. While it was a little more visible, at least I could tie a decent knot in it and things wouldn't slip!

I also tied some of the crossover points of the strips to each other, to help give the whole thing some structure and make it a little less likely to move or reshape itself.

With the test lights mounted and my son very happy with the progress, I turned my attention to the battery pack / electronics.

I found a box from a recent delivery and extracted the packing foam used to protect the goods. In about 5 minutes, with the help of some more Gaffer tape, I had a fairly well-protected battery and electronics unit which I could just place into the backpack, while still allowing it to breathe in case things got warm.

Then I simply loaded it all into the backpack!

With the mounting positions all set, I hung everything from a coat hanger and switched it on just to let it run for a while. I also reprogrammed the LEDs from Blue and Orange to White and Red at my son's request.

THE CODE

With limited time available to get this project done, I was keen to find a springboard. After some quick Googling for some NeoPixel compatible effects, I stumbled on a great set of code here: https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/

I loaded up a few to test their effects, and settled on the RunningLights code (Running Lights.ino).

The code was simple enough to run and worked straight out of the box. However I wanted to have two different colours running on this, so each loop appeared to be a different helix.

After a little digging, it looked pretty simple. Since I was unlikly to ever need this code variant again I just started hacking. The results are as follows:

You dig through the code at your leisure, but there's really one main function called RunningLights.

void RunningLights(byte red, byte green, byte blue, int WaveDelay) {
  int Position=0;
  
  for(int i=0; i<NUM_LEDS*2; i++)
  {
      Position++; // = 0; //Position + Rate;
      for(int i=0; i<NUM_LEDS; i++) {
      // sine wave, 3 offset waves make a rainbow!
        //float level = sin(i+Position) * 127 + 128;
        //setPixel(i,level,0,0);
        //float level = sin(i+Position) * 127 + 128;
        setPixel(i,((sin(i+Position) * 127 + 128)/255)*red,
                   ((sin(i+Position) * 127 + 128)/255)*green,
                   ((sin(i+Position) * 127 + 128)/255)*blue);
      }
      
      showStrip();
      delay(WaveDelay);
  }
}

The code works great, but in order to achieve two colours we needed to break the loop. I noticed that at one point, they would double the LED count. We had 364 LEDs, by the way.

for(int i=0; i<NUM_LEDS; i++) {

I simply updated this to remove the "*2" and instantly the loop would only control half the string.

I then duplicated this "for" loop, setting the counter at 182.

for(int i=182; i<NUM_LEDS; i++) {

Then all that was left was to assign different colours. Instead of creating new variables, I just changed the colour variables to RGB values as required.

For instance:

setPixel(i,((sin(i+Position) * 127 + 128)/255)*red

became:

setPixel(i,((sin(i+Position) * 127 + 128)/255)*128

Then I just set the values I wanted. Easy!

void RunningLights(byte red, byte green, byte blue, int WaveDelay) {
  int Position=0;
  
  for(int i=0; i<NUM_LEDS; i++)
  {
      Position++; // = 0; //Position + Rate;
      for(int i=0; i<NUM_LEDS; i++) {
      // sine wave, 3 offset waves make a rainbow!
        //float level = sin(i+Position) * 127 + 128;
        //setPixel(i,level,0,0);
        //float level = sin(i+Position) * 127 + 128;
        setPixel(i,((sin(i+Position) * 127 + 128)/255)*255,
                   ((sin(i+Position) * 127 + 128)/255)*124,
                   ((sin(i+Position) * 127 + 128)/255)*124);
      }
      for(int i=182; i<NUM_LEDS; i++) {
      // sine wave, 3 offset waves make a rainbow!
        //float level = sin(i+Position) * 127 + 128;
        //setPixel(i,level,0,0);
        //float level = sin(i+Position) * 127 + 128;
        setPixel(i,((sin(i+Position) * 127 + 128)/255)*255,
                   ((sin(i+Position) * 127 + 128)/255)*35,
                   ((sin(i+Position) * 127 + 128)/255)*0);
      }
      showStrip();
      delay(WaveDelay);
  }
}

Full code is available in the resources.

The costume was a hit, and the parts were repurposed the afternoon after it was used. The only waste was a little Gaffer tape!