Das Blinken Top Hat

Contributors: Nate
Favorited Favorite 1

Vector Math

If you've been out of school and away from Newtonian physics as long as I have, it takes a second to remember how to combine the three acceleration vectors into one. For our purposes we care only about the movement of the hat (magnitude of movement), not direction:

A2 + B2 + C2 = Z2

or in code:

float magnitude = sqrt((aX * aX) + (aY * aY) + (aZ * aZ)); //Combine all vectors

Here's what the actual code looks like:

float avgMag = 0;
for(int x = 0 ; x < 8 ; x++)
    aX = analogRead(accelX);
    aY = analogRead(accelY);
    aZ = analogRead(accelZ);

    float magnitude = sqrt((aX * aX) + (aY * aY) + (aZ * aZ)); //Combine all vectors 
    avgMag += magnitude;
avgMag /= 8;

We take 8 readings and average them together to reduce the noise. This works pretty well. Now we just have to decide what to do with this magnitude reading.

For the purposes of das blinken top hat we needed to have the LEDs spin fast when acceleration or movement was detected and then begin to slow the rotation as movement subsided. To do this, we use an exponential growth equation to organically increase the time between channel changes (tBCC in the code).

Time delay between LED changes = A * xt

This is a basic exponential growth equation. The time between LED changes will increase exponentially with time based on a constant A and a growth rate x. I knew I wanted the LED strips to slow down across 3 or 4 seconds when the accelerometer stopped detecting movement, I just had to determine A and x.

I determined the constant A by programming the hat to rotate in a circle and seeing how small a delay the rotation could use before my eyes couldn't discern the difference. 10-20ms between a step to the next LED strip looked pretty awesome. Anything less than 10ms just turned into a blur.

To determine the growth rate x, I used a spreadsheet and found that a growth rate of 1.00086 would cause the delay to increase to over 500ms within 3.5 seconds. Checkout the google spreadsheet here to see the calculations.

long currentTime = millis() - startTime;
timeBetweenChannelChange = shortestDelay * pow(growthRate, currentTime); //Exponentially grow the delay between changes

In the equations above we calculate the current time and then calculate the new tBCC using the two constants. This value (timeBetweenChannelChange) in milliseconds will increase exponentially over time until it becomes greater than our maxTimeBetween (3.5 seconds). Once tBCC becomes larger than the max time the hat will stop spinning altogether.

After a bit of testing and a few small tweaks the rotational light effect looked pretty good.

Soft PWM

I have had a few costumes and LED pieces where the LEDs were so bright they were blinding. This also happened with the top hat -- the light was so intensely awesome it bordered on epileptic dance party. To counter this, I wanted to reduce the brightness by pulse-width-modulating the 8 channels. If we reduce the PWM ratio, then the LED strips should be less bright, we extend our battery life, and we blind less harmless bystanders. The problem is that the Arduino Pro Mini only has 6 PWM channels, not enough to run all 8. Luckily, there is a software solution to the rescue!

SoftPWM is a library written by Brett Hagman of Rogue Robotics. This really slick library allows us to turn any pin into a PWM pin. It's not perfect (looks like servo support may be limited), but it works great for controlling LEDs!

SoftPWMSetPercent(chan0, brightLevel);

This simple function allows us to set a given LED strip to a brightness level between 0 (off) and 99 (full brightness). Through testing, I found that a brightness level of 9% (yep, that's all) was still plenty bright without being overbearing.

The original plan was to solder a trimpot onto the Pro Mini so that the brightness could be adjusted on the fly. This became a bit of a problem (trying to detect changes to the trimpot during run-time got tricky), so, instead, I tested a few brightness levels and then set it permanently. I've had the hat set on 9% ever since.

Das Bliken Firmware

There are two example sketches to give you an idea of how to create different lighting effects. Dave wrote the original code which provides tons of great lighting effects with physics engines coupled with energy systems. I wrote a much less interesting sketch that uses a simple exponential growth formula to control the light spin.


alt text

The Das Blinken Top Hat was a fantastic gift that has wowed crowds and lit up parties. It's amazingly robust and a ton of fun to show off.

Thank you Diana and Dave!