Project Overview

LI Light

Catching up

It’s been … a long while since I’ve given an update on any of my projects.

And it’s not been for a lack of projects! Since the last time I actually wrote a post I’ve designed, fabricated, and coded matrices big and small …

😉

Blinking pumpkins …

Plywood lanterns (or at least the start of one) …

But the projects that I’ve been REALLY into lately are logo lights.

The prototype

The company my wife works for has a suuuuper cool logo. It’s this cool spiral of different sized triangles.

And I thought “man, it would be cool to make a light out of that”

You know, my normal response to everything.

So I worked through a bunch of ideas on how to turn the logo into a light. I’m not going to go through all of the iterations on this project (there’s a legit long form article’s worth on that build alone). The short of it is that the build was a lot harder than I though, but a lot of fun to figure out and it looked slick as hell when it was done!

That was a lot of triangles to redraw in CAD 😐

I love the way the light defuses through the LED acrylic and the electronics are completely masked off when the light is off. It just looks like a featureless black box when the you turn off the LEDs.

So cool, I have this slick logo that I could stare at for hours, but I can’t put that logo up in the background of my video calls because, you know, it’s not the logo for the company I work for. I gave the logo light to the company’s founder and started planning out one that I could keep for my self 🙂

The plan

The original plan was to make a 3D printed shell in the shape of the Label Insight (the company I work for) logo itself. I was actually going to do this for both the Label Insight and Ripeta lights, but during the Ripeta light build someone said “oh that would be cool in a shadow box”. I tried it and it DID look great, so I changed direction.

Regardless, the the plans for the inside of the light stayed the same. It would consist of:

  • An LED acrylic panel
  • A spacer in the shape of the logo
    • Creates enough space between the LEDs and the acrylic for the light to defuse and avoid the LED “dot” look
    • Acts as a mask for the light to light up in the shape of the logo
  • A mounting plate for the LEDs that aligned the strips in the center of each section of the mask
  • A mounting panel for the custom circuit board and the circuit board itself
  • A panel for the power and the on/off switch

The model

So, first step: model it out in fusion!

I designed all of the parts for this from scratch except for the shadowbox. TBH, I’m not confident enough in my woodworking skills yet to try to do a from-scratch shadowbox (though eventually I want to get there), so instead I opted for fitting everything to a pre-made shadowbox from Ikea. That inner frame wall in the 3D model is the inner dimension of the actual shadowbox, the outer wall in the model is a scale version of the box I used for the Ripeta logo.

The design problems to solve in the model were the logo mask and LED mount itself, the power and control access panel, and then some way of centering the entire logo within the shadowbox itself so the light looks like it’s floating in the middle.

I proved out all of those concerns in the Ripeta light, but I wanted to figure out a better way of centering the design. In the Ripeta light I went down to MADE and laser cut some plywood to do the centering.

But for the LI light I wanted to figure out a way of doing the supports via 3D printing so I could do it all in house (no glowforge at home yet :wistful-sigh: ). So I took an re-thought out the problem.

The reason I didn’t try to 3D print mounts for the Ripeta logo is because the shadowbox was so large that I couldn’t do a single piece on the 3D printer that would fit into the inner bounds of the shadowbox. With more time/perspective I realized that I didn’t need to do it in a single piece, I could just do it with smaller pieces that spanned the gap between the outer perimeter of the logo and the inner perimeter of the shadowbox.

Print just what we need …
… to get centered and squared

Defusing the light

I spent a bit of time testing out a single section of the logo to figure out exactly how deep the mask needed get the light to defuse completely and blend color well.

With the depth figured out I printed the LED mount, the mask, and started wiring it up.

The circuit board

I’ve been designing my own simple circuit boards for a while now off and on, but so far I’d never actually had one professionally manufactured. The most I had done was to create the design in EagleCAD and then hopped down to MADE to use their PCB mill to cut the boards myself.

This works great for testing and one offs, though soldering these without a solder mask is a massive pain.

This time I wanted to go the extra step, so I sent my board designs out to JLCPCB to get manufactured and HOT DAMN LOOK AT THESE SLICK BOARDS!!!

The boards are ultra simple, really they’re just clean mappings of pins to ports, but having a clean functional board that I designed feels like a big milestone.

So, with the boards designed, I slapped one into the LI light and used that moving forward.

The code

Woof, this is where the biggest chunk of time ended up being on this project.

For the Ripeta light the code was simple. As far as coding logic the spiral is just a long array so I could treat it like a normal LED strip. The Label Insight logo was a bit different though.

The barcode section of the logo (the bottom half) is easy enough to light with one section of an LED strip, but the top sections all require doubling up to really fill the section

Another thing to account for is that the data for LED strips flows in a specific direction, so for a shape like this there’s both logic direction switching back and forth per light section and a couple of spots that contain a logic flow switch within the section itself.

And on top of all of that, I knew I wanted to write a couple of distinct patterns by hand and use some kind of physical button to cycle through them, so doing some procedural hard coding of the indexes was not going to work.

I didn’t want to wire this up and treat it like an LED matrix because it’s not really a matrix. The way I wanted to write the pattern logic really was just like treating the whole logo like a zig-zagging LED strip, but where some of the zig-zags were independent but some were grouped.

So, I spun off to write a library specifically for managing array indexes within arbitrary sections that I so creatively named SectionManager 😛

I actually named it FastLED-SectionManager because at the moment the FastLED library is a baked in dependency, but one of my future goals for the library is to decouple the LED library from the manager so you could swap in something like the Adafruit NeoPixel library if you wanted.

The gist of the library is that instead of treating the entire length of an LED strip like a contiguous array:

You can tell the section manager that certain parts of the strip should be grouped together and treated as one section. So in the example below, the second and third section would be treated in code as if they’re one strip:

This is all abstracted behind the library, so now in the pattern code I can write for the top three doubled up sections as if each is just a single set of indexes. The code also abstracts the zig-zagging so you can write as if it’s all one contiguous index:

And more code

Even with the LED index difficulties abstracted away with the SectionManager the code was still a challenge, mostly because up until now I had been writing most of my C/C++ leaning towards a very procedural C style. For small or simple projects this is no big deal, it’s a lot of code for one or two files, but there’s not so much that it’s terrible.

With this code base that wasn’t going to work. I needed to Manage the Sections, run different light patterns, execute the patterns in a non-blocking manner so some kind of interrupt could trigger the switch without getting delayed or completely ignored, the interrupt trigger itself needed to be programmed … it would be a lot for a procedural program.

On top of that, Label Insight is a Kotlin/Java shop (well, a Kotlin/Java/Python shop for back end code, but I write mostly Kotlin/Java), which are 100% Object Oriented languages. Previously most of the code I had written at work was Node/Typescript so professionally I was transitioning from a world where OOP was optional to one where it was required. The advantage to that in my hobby projects is that C++, specifically OOP C++, was starting to click with me a lot more.

So, I ended up going kind of OOP for the code base at first and then going full on OOP in the end.

The light

Cool, so after rambling along for a bit about the making of, let’s look at the light itself.

The LI Light has 3 patterns

Rainbow In
Solid fill

Random and Scan

Each of these was pretty cool to figure out.

The rainbow in pattern does a particularly good job at showing of the advantage of writing out the SectionManager library. Notice that the gradients for the rainbow move from the outsides of the logo in to the center. This would be super difficult to do in a procedural coding style (trust me, I tried :P).

Considering the LEDs in the logo are wired in that zig-zag pattern, you need to tell the pattern which sections are pointed in which direction while iterating over the color wheel to create and move the gradient. ALSO remember that on the top you have to make sure the color gradient is moving in the same direction for the two strips in the doubled up section.

Even typing it out this sounds like a handful, but after abstracting all of that index management to the SectionManager, all of that logic boils down to this:

:chef-kiss: that’s some nice abstraction :chef-kiss:

On an artistic statement level I like the Random and Scan pattern a lot. Trying to explain everything that Label Insight as a company does is outside of the scope of this already overly long and rambling post and is better stated on the company’s website, but a really simplified version of what the company does is “taking data provided by a product label and deriving useful information with what that product data implies”.

So, the idea behind the Random and Scan pattern taking random data points, analyzing them (the scan), and providing insight (the bar graph fade in), before revealing the whole logo.

Pattern switching

With multiple patterns in mind I knew I would need a way of switching between them.

My initial idea was to have an particular pattern run when the light was idle and then use an ultrasonic sensor to trigger a main pattern when someone stood in front of the light. This was actually what the Random and Scan pattern started out as. The light would just run the random portion until someone stood in front of the light which would trigger the scan.

I also knew I wanted to have more than one idle pattern and I only wanted one input component on the light to keep things simple. So, the plan was to define different distance thresholds for the ultrasonic sensor; a super close threshold which would cycle the idle pattern running and a threshold farther out that would trigger the scan pattern.

I actually got really far along with this idea, and by far I mean I fully built it out and got it working.

It’s a cool idea, but after getting it working and trying it out it just didn’t feel right for this project. I like the interactivity, but after you trigger the main pattern once it becomes kind of boring. In the context of this light, the ultrasonic trigger felt like more of a gimmicky backflip than a sensible feature. So, I cut it.

I still wanted a not-just-a-regular-old-button way of switching the patterns, so I went with one of my favorite methods: capacitive touch.

I cut out a square of copper, soldered a jumper wire to it, and ran it to the circuit board. Now, when you tap the copper pad the Adafruit Trinket will measure the change in resistance on the pin attached to the jumper. With a threshold set that denoted the pad being touched and a bit of debounce code to prevent the signal bounce I had my button.

Another nice feature of using this touch pad is that it’s way way easier to design a mount for mechanically verses a traditional button, I just needed to make a spot for the pad, a bezel to cover the rough edges and solder so that it looked nice, and then I was done.

Final thoughts

Thoughts

Overall I’m super happy with this project. There are (as always) other things that I’d like to do to the code base and fabrication, but I think this is a good stopping point.

I learned a lot of new-to-me stuff which is the reason I do most of my side projects, and now I have a slick looking light in the background of all of my work video sessions 🙂

I have ideas for making a couple of more light designs similar to this, but for now I’m going to crank out a couple more for co-workers and move on to a another project idea I’m itching to dive into.

More Similar Posts

Most Viewed Posts
Menu