Monday, November 11, 2019

Building the Key of Aaravos

A few months ago, my wife and I binge-watched the first two seasons of The Dragon Prince on Netflix.  It’s a cute little cartoon show with some really good writing and well fleshed out characters, and with only 18 episodes so far it doesn’t take long to catch up on the whole thing.
In the show, there is a magical device initially referred to as the “Primal Cube” initially, though revealed in the second season to be more properly called the Key of Aaravos.

The Primal Arcanum Cube
The Key of Aaravos

The cube has six sides, each with a symbol of one of the types of primal magic in the show, that lights up when in the presence of each type of magic.  After watching the show, I wondered if anyone had published 3D files of it for printing. A quick search on Thingiverse brought up a few results. I was considering printing one, but my wife pointed out that I should make one that lights up.  It shouldn’t be too hard, I thought. Just a few colored LEDs, right?

I downloaded one of the better Key of Aaravos files from Thingiverse to use for reference, but ended up redrawing everything essentially from scratch anyway. I tried to guess based on stills from the TV show just how large it was supposed to be, which was difficult as we really don’t know how large Callum’s hands are. I scaled the cube relative to my own hands, which may have resulted in a slightly oversized cube in retrospect - I have large hands.

To test how it would look, I split the cube into faces, and split the raised illuminated sections on each face into a separate section that would be printed in translucent plastic and pressed into the face pieces. I was lucky to have a reel of a beige color that fairly closely matched the color of the cube on the show, and a reel of ‘natural’ translucent PLA, both of which I had no other immediate use for. The test print, held up to the ceiling light for backlighting, revealed some issues with how light bled through both the transparent and the opaque plastics. Too much light was bleeding through the parts of the structure that were meant to be opaque, and the transparent parts didn’t look right either, but I was pretty sure I knew how to solve both issues.

Initial illumination test. Still needs a lot of work.

At this point, I needed to choose internal components, so I could design the final printed parts. My initial plan had been to simply grab some ultrabright LEDs in various colors, but I wasn’t sure I could exactly match the right shades of colors with easily available LEDs. It occurred to me that I might need to mix multiple colors of LEDs to get it just right. Fortunately, there’s an off the shelf solution for that. Neopixel LEDs have red, green, and blue LEDs along with a control chip all combined in one package, programmable through a serial data link that’s daisy-chained from one LED to the next. I had never worked with them before, and this would be a good excuse.

I decided to use one Adafruit Neopixel Ring, and one Neopixel Jewel, inside each face of the cube, for a total of 19 Neopixels in each. In retrospect, this was far more than I needed. I didn’t realize just how bright these things are, it actually hurts to look at the LEDs at full brightness without the printed faces over them.

Neopixels require a microcontroller to command them, something with enough memory and a sufficiently fast port for the required serial data signal. I had originally considered an arduino, but looking through the Adafruit catalog I noticed the Trinket M0, a remarkably small and inexpensive control board capable of running CircuitPython. I’ve been using Python for various projects for years on larger computers, and was surprised and somewhat skeptical that it was even possible to make it run on an embedded controller. I decided to try using it to control this project.

The cube would need a battery, for which I chose the 1200mAh Lithium Ion Polymer cell from Adafruit. I also chose the Adafruit Powerboost 1000 to act as a charger and 5V regulator. I’d used it on previous projects with success, and it would handle more than enough current to drive a single face at full brightness.

One problem was that while the Trinket M0 would accept 5V input power, it would only output 3.3V on its data pins, and the Neopixels really want the serial data signal to be at the same voltage as the power line. I added in a little bi-directional voltage level shifter to do the conversion from the Trinket to the Neopixels. It has four channels, but I’m only using one.

Being able to just buy simple drop-in breakout boards makes designing things like this so much easier. I remember back in the day, when I first started doing electronics, I would have to draw and etch my own circuit boards, ironing transfers onto bare copper boards and then carefully washing them in tubs of unsafe chemicals. These days, having companies like Adafruit that make everything available on breakout boards just makes everything so much easier.

With power and serial data control of the LEDs worked out, I needed a way for a person to indicate which side of the cube should light. Adafruit didn’t have any primal magic detecting sensor boards available, so I’d have to fake it. I considered building a separate remote control with buttons for each side of the cube, but I really wanted this to be a single-piece build. I also considered using a Bluetooth connection to control it from a cell phone, but that was more work than I wanted to spend on this project. Another idea was to use an accelerometer, and have the person holding the cube gesture or angle the cube a certain way to indicate which side to light. Awkward, but Adafruit did have an inexpensive accelerometer board available. Then I saw the 12 channel capsense board, and though that it might be possible for the cube to detect your hand and light the side opposite where it was being held by. I wasn’t sure if the capacitive sensing would work well enough, so I included the accelerometer anyway as a backup.
Final schematic and parts list

All of the parts were conveniently available from Adafruit. A few days later, and I had a pile of boards ready to start working with.

Always a nice day when my Adafruit order has arrived.

A test with a single side and just enough electronics to make it light up showed a bit more of a spotlight effect than I’d like, but it was acceptable.

Far brighter than expected.  I could probably have used fewer LEDs

Before doing anything further, I needed to do a detailed design of the interior. The structure ended up a lot more complex than I initially expected. Each face has a LED assembly consisting of one Neopixel ring and one Neopixel jewel, centered in a truncated pyramid which acts as a light baffle to block light from one side from bleeding into another. In the center is a roughly cubical space where most of the electronics go, although the Powerboost charger/regulator board and the Trinket needed to be arranged such that their respective USB ports were accessible from the outside of the cube. Fitting the battery in place was tricky, as it had to extend slightly into the diagonal spaces between the light baffles. The Trinket ended up having to go into a corner behind the Star arcanum space, as it was the only place it wouldn’t block any light.

Each edge of the cube needed to contain an antenna for capacitive proximity sensing. I experimented with a few different ideas before deciding to use strips of copper tape. The Adafruit Captouch board that I was using was really meant for touch sensing, but I needed to detect a person’s hands through some distance of plastic, since the electrodes wouldn’t be on the surface. I had a challenge in how to route the wires from the breakout board to each of the edge electrodes, as I wanted to route them away from potentially electrically noisy components in the center. I also wanted to keep the wires away from the outside to avoid incorrect sensing of user’s hand. This meant carefully routing the wires through carefully designed holes and channels inside the walls between faces, avoiding the battery charger and other components.

Capsense wires in red, fanning out to antennas on edges.

The segments of the core took about six hours to print each. There were a few iterations of the design, mostly as I figured out how to route the capsense antenna leads. The final design did make it difficult to install them, and results in them essentially stitching the pyramids together, but does keep them away from the LEDs and other electronics. These pieces were printed in black, with a high infill, to keep them opaque and prevent light from bleeding over from one side to another.

Printing core segments on my sweet custom Delta printer.

For the outer shell of the cube, I had a reel of tan filament on hand that was a near perfect match for the color of the cube.  I also had a reel of translucent ‘natural’ PLA which I’d been looking for an opportunity to use.  You can’t really print transparent parts with a printer like mine, but I was hoping I could get a decent frosted-glass look that would let the light through while also diffusing enough to prevent hot spots.

The initial test print showed several problems.  The plastic I chose for the shell just wasn’t opaque enough.  There was far too much bleed through when any bright light was behind it.  I had really underestimated just how bright the Neopixels were, and although I liked the brightness and how they illuminated the runes, I didn’t like how much bled through the parts that were supposed to be opaque.  The nice tan plastic that matched the color of the cube just wasn’t very opaque.

Too much light bleeding through the center.

I considered a few different options for making the faces block light better.  I considered lining the inside with dark tape, printing an inner shell out of black plastic, or even taping copper foil over the inside, which I briefly thought might have been required for proper capsense function.  The simplest solution - several coats of black spray paint - turned out to work very well.

Careful masking to keep the paint on the inside.

The other issue was the proper appearance of the translucent parts.  I discovered very quickly that the infill pattern would be highly visible due when illuminated.  I wanted the lit parts to look smooth and without pattern, which wasn’t really possible with a printed translucent part.  After a few experiments I found that printer settings with no infill, no top and bottom, but very high side wall thickness, worked the best.  This setting resulted in a part that was made up entirely of concentric shells.  When illuminated, the pattern was barely visible, and when not illuminated it had a shimmering, almost crystalline look that I really liked.

All six faces, with translucent parts inserted.

I had a challenge in figuring out how to attach the faces to the core.  I decided early on that I wanted it to be possible to completely disassemble the cube without breaking or cutting anything.  No glue or plastic-weld, it had to be fit together with fasteners.  For the initial design I had small wood screws hidden in the leaf detailing near the corners.   I built up a full prototype cube this way before deciding it was unacceptable.  The screw heads stood out far too well against the plastic, and the edges of the plastic faces tended to curl away from each other resulting in visible seams.  It looked terrible.

Unacceptable.  Time to re-think the design.

I went back to the drawing board on the faces, and ended up redesigning the core too.  I decided to attempt a friction interlocked, puzzle-box type design.  The faces would have edges that locked into each other in a way that was designed to hide the seam between faces from the viewer, breaking up the seam and hiding it in the detailing.  The resulting design relied on friction and interlocking geometry to attach the faces edge-to-edge.  The corners became separate pieces which were inserted after the faces were in place, to furner lock them together and pin them to the core.  The resulting design was surprisingly strong, had no visible screws or other fasteners, and did a good enough job of concealing the seams.  I could probably have done a bit more work to make the seams harder to see, but at this point I was getting tired of the project and was also running low on tan filament from having printed so many prototypes.

Of course, I had to completely re-print the core, since I had redesigned them to interlock with the corners and also to address some assembly issues found earlier. 

Much better.

With the design finished and all parts printed, it was time for the final build.  Assembling the core was difficult, as it’s very tightly packed in there.  All of the boards and other parts had pockets to hold them in place, and routes for wiring built into the plastic.  Everything had to fit in just exactly the right spots.

I even made mounting brackets to hold these four electrolytic capacitors, added to ensure a stable regulated voltage with the LEDs being PWM-switched.  These are almost certainly overkill electrically, but they were a convenient place to tie all of the 5V supply lines to.

First side of the core to be assembled.

The lithium-polymer battery is crosswise across the internal cubical space, as that’s the only place it will fit, and actually extends slightly into the space between faces.  Note the fanout from the capsense board.  Each antenna wire has its own channel in the plastic from the board to the antennas.  I hadn’t worked much with capacitive sensing before, and was worried about electrical interference and crosstalk, so I tried to keep each of the antenna wires away from the parts in the core.

Stitching the sides together with wire

Blue painter’s tape was used to hold parts in place temporarily until the rest of the cube was assembled around them.  The final steps of assembly were very tricky, as I was trying to carefully tuck wires and parts into pockets in the plastic as I closed the core parts up.

Almost there.  Just have to tuck these last wires in place.

The final wiring was installing the actual capacitive sensing antennas.  The wires from the capsense breakout board were each run out to one edge of the cube.  Initially I had planned to simply have metal rods running along each edge for the actual antennas, but that did not work well.  When using capacitive proximity sensing, the more surface area you have in your antenna, the more sensitive it will be.  I ended up using adhesive-backed copper foil along each edge, soldered to the antenna lead in the middle, and this gave me acceptable antenna sensitivity.  It did however slightly violate my initial goal of not having anything glued together, and if I ever want to disassemble the cube I’ll need to cut off the copper foil.
Taped together, but I'll live with that.

One thing that I was never completely happy with on this design was the charging port.  I needed to leave open a USB port where I could plug in a charger to charge the internal battery.  I couldn’t figure out a good place to integrate the charger into the cube’s design, and ended up just putting it behind one of the corners of the cube.  It’s not ideal, as you have to take the corner off to charge it, and the corner piece actually falls off easily as it’s not held in nearly as securely as the other corners are.  This would be something to think about if I ever decide to redo this design.

Not ideal, but where else am I going to put it?

This project was my first experience with embedded Python.  I’ve been programming in Python for years, but never tried the embedded CircuitPython version, and I was curious as to what you could actually do with it.

What I learned was that while it’s easy and fun to work with, and amazing that it works on such a small processor at all, CircuitPython is severely limited in its capabilities.  I was fighting with memory and processor speed limitations throughout this project.  Though it was a fun learning experience, if I had to do this again I’d just write it in C.

The code on this cube has to talk to three external devices:  the MPR121 capsense board, the LIS3DH accelerometer, and the chain of NeoPixel devices.  It also has to keep track of the state of 216 NeoPixels, and have unique animation routines for all six sides of the cube.  I discovered very quickly that the Trinket M0 running CircuitPython just doesn’t have the memory for all of this.  I couldn’t even load all of the libraries for the devices I was trying to talk to.  I ended up not using the LIS3DH library, instead using direct I2C access to read the accelerometer registers.  Along with careful pruning and optimization of my code, that got all of the functionality I needed to work.

For all the difficulty in getting it to work, the only thing that I ended up using the accelerometer for was to detect when the cube is being held.  I had originally planned to use a gesture-based system to select which side to light if I couldn’t get the proximity sensing to work.  I did ultimately get that to work, so the accelerometer is simply used as an on-off switch, to shut the cube off if it’s not being held.  The main loop polls the accelerometer and looks for changes in the readings, and only permits the lights to be on if there’s been enough change in the readings to indicate that the cube is being held.

The MPR121 capacitive touch board is really intended for touch sensing, with essentially no distance between the touch antenna and someone’s hand.  Unfortunately, I needed to have the foil antennas on the inside of the casing, with a shell of plastic between the antenna and the user’s hand.  With the initial settings, the sensors would almost never register contact.  With a bit of searching online, I found a register I could write to in the MPR121 that would increase the sensitivity enough to detect a hand at a distance.  This was also done with a direct I2C write, as the MPR121 driver did not include this function.


The code contains an animation engine which illuminates one side of the cube at a time, as determined by the location of the hand holding it.  Each side has a slightly different algorithm to generate the RGB values for the 19 LEDs making up the face, with a random effect to make a unique shimmering appearance for each side.  I tried to match the appearances to the arcanum runes shown on the show, although I had to completely guess for the Star and Earth runes as they haven’t been shown on the show yet.  There is also a ramp function, so that the sides will gradually fade in and fade out as needed.

The resulting cube probably runs for a few hours continuously, which should be enough for doing cosplay at a convention, if I was inclined to do that.  The truth is, I don’t really do cosplay, and mostly built this just as a learning experience.  Building the cube was educational and fun, but I’m not really sure what if anything I’ll be doing with it now.

Came out pretty well.  I think this is about the best match I can get, considering the materials and parts I have to work with.

I have posted all the files needed to re-create this, including the schematic and Python code, on Thingiverse at


  1. Found Your thing on thingiverse, interesting read. Your one is impressively made. Congratulations on making that ��
    I just finished season 3 and might be tempted to make one myself, but probably not your design. Might focus on miniaturization and make cube size something around 50x50x50mm. Thanks for inspiration ��

  2. Amazing build out! I'd love to know what wire/gauge you used for the capacitive touch as everything I've tried has been impossible to get through the holes in the holes on the core segments.

  3. Hello! What was the size of the screws and hex bolts you used?