Progress on the snowman has been a bit slow. Most of what it left is getting the animations to where I like them, which involves a lot of iterations of writing some code, downloading it, debugging it (through the serial port and/or using an oscilloscope), and then working on a new version.
I’ll drop all the code on Github when I’m done with it. I built a couple of nice classes.
ColorFader knows what its current color is and then does a smooth fade (over however many steps you want) from that color to your target color. It uses fixed-point fractional math, a nice little technique that we used to use in the old days to do smooth movement without fast floating point operation.
The problem is if I want to move from the value 1 to the value 8 in 50 steps. If I had floating point, I’d just divide 7/50 and get something like 0.14, and add that on each step. Here’s what I do instead:
| full byte | fractional byte|
So, to go from one to 8, I set my initial values into the full byte.
1 => | 1 | 0 | = 512
8 => | 8 | 0 | = 4096
I can now figure out my delta, which is (4096 – 512) / 50 = 71. That is the value I will add each increment. The stored current value will look like this:
| 1 | 0 |
| 1 | 71 |
| 1 | 142 |
| 1 | 213 |
| 2 | 28 |
| 2 | 99 |
| 2 | 170 |
| 2 | 241 |
| 3 | 56 |
The number we pull out as the actual value is the full byte, but the fractional part makes it change in a smooth way. This technique also works with wider data types (ie you can have a two-byte (unsigned short) full value and use two bytes for the fraction), but color values only range from 0-255 so this is all I need.
Because the fractional value is not exact (it’s really 71.68), we will lose 0.68 * 50 = 34 from our target, so we will only get to 7 (+ a fraction) rather than 8 on our animation. That’s generally okay for this sort of application.
I also build ColorFaderMultiple, which chains <n> of the faders together so it switches to the next as soon as one fade is done.
I ended up with four animations:
- A startup animation fades in from dark to white
- A random color animation that gives each globe and other sections a solid color
- A blend animation that chases colors through all the leds in the globes
- A bounce animation.
You can find the final version of the code in my github repository.
As-built, the snowman has eyes and nose that are just raw LEDs poking through. The mouth and the buttons are raw LEDs behind the globe.
Everybody knows that snowmen have long thin noses, so I decided to print a conical nose out of natural PLA, and that worked pretty well. Things kind of snowballed (HA HA!) from there; I did a octagonal star as a button cover, and it both diffused the light and covered up the LED strip that was visible from behind, so I decided to do more.
The eyes were originally 1” printed PLA discs. They worked, but they didn’t really look like eyes because they weren’t pointed forward. I designed some better ones by building a hollow tube with a flat bottom (think soup can), added a negative ball (“hole” in Tinkercad language) centered over the tube, and then moved it to the side to mimic the distance of the eye from the part of the globe that points right at the viewer. I then dropped the globe so that it cut into the tube, stopping when it left about 4mm on the shortest side. These looked great.
I ended up printing 3 different shapes to use as the buttons. To make them a little more cool, I used the same technique to get them to conform to the shape of the sphere. They also looked nice. That left me with the mouth showing bright LEDs from behind. So, I decided to take the same approach with the mouth. Here are all the appliances:
I put the snowman under conscious sedation and attached all the appliances with silicone cement. I also sealed the nose and eyes with silicone so there’s a bit more water protection.
There was a tiny bit of wiring left to do. I built a little harness that has a header for power coming in (5V @ 3 amps), two headers for the arduino (two pins to supply 5V and GND, and one to pull the animation signal). This harness is wired in to the snowman wiring, and includes a 220 ohm resistor in the signal line and a 220uF capacitor across the power line (both recommended by Adafruit).
I needed something to put the Arduino in. After looking at a few case designs, I decided to do my own. It’s a very simple box with a slide-on cap, and sliced with Slic3r and printed on my Printrbot Simple metal, the cap fits tightly. A different slicer and/or printer may require some tuning.
The quality for this is a bit poor, but you will get the basic idea. The colors are much better in real life. The brightness is deliberately turned down because otherwise the feature RGBs overload the sensor and they just look white.