Ok so this “project” is, admittedly, a bit silly, but it was fun to build and even more fun to program! A flashlight isn’t all that fancy compared to walking robots, and zippy line tracers, but I needed something I could build with the handful of test components I purchased that would let me test what I suspected would be a solid, sophisticated model for programming the Mini Maestro. The One-Million-Color Flashlight fit the bill, and so far, I’d say I’m on the right track with the code. I <3 the Maestro!
So why One-Million colors? Because the ShiftBrite modules display a 10-Bit RGB spectrum (~ 1 billion colors), but the device changes color component values in steps of 10, and limits maximum intensity to 1000 (instead of 1023, or the max value of 10 bits). So the result is 1,000,000 color combinations rather than 1 Billion.
Operation was designed more around a code experiment than a user experience, but the device is still fairly simple to operate. Toggling the power switch to “On” activates the device and it initially emits “white” light (Red, Green, and Blue components at maximum intensity). The rear color component indicator illuminates red, meaning that the gauge needle is displaying the current Red color component value. A push button to the left of the color component indicator LED can be pressed and released to cycle through the three color components, causing the gauge to display each value in turn. Three push buttons, designated Red, Blue, and Green, by small plastic beads, can be pressed and held to decrement the intensity of the related color component. When a value reaches 0, it is reset to 1000. Finally, in the upper right, a smaller red LED and push button are provided as an “it should be working” button. This button and LED are wired straight to power and pressing the button should cause the light to come on whenever the regulator is powered and working.
On to the physical device itself; here’s a top-down picture of the device on its side, with the beams pointed to the left:
It’s not made of much; a couple of old 5-1/4" drive bay covers from a PC make up the base plate and top cover. There are no sides - just a top and bottom compressed around an eight-cell AA battery holster with cable ties. At the rear end of the battery holster (the right end, with the small green LED in the picture) the Mini Maestro 12 is mounted to the base plate by sliding its two mounting holes over two nylon screws, hot-glued upside-down to the base plate. Behind the Maestro sits the D15V35F5S3 power regulator, essentially suspended by its own 18 gauge wiring. Finally, a small RadioShack prototype PCB board, hot glued on its bottom edge to the base, houses the control interface (e.g. 5 push buttons and 2 indicator LEDs). A sturdy toggle switch was fitted into a notch cut into the top cover and hot-glued into place.
The left end (ahead of the battery pack) houses the two beam assemblies along with a servo which controls the needle of the color component intensity indicator gauge. You can see in the photo (sort of!) that the indicator needle is pointing to 0% intensity and the currently displayed color component is Green (the color of the rear LED). The Red and Blue components have high values, and so the light projected is purple in color.
Here is closer view of the rear of the device, followed by a closer view of the gauge at the front of the device.
The beam assemblies are each constructed from a ShiftBrite module screwed to a nylon spacer via their PCB mounting holes. The nylon spacers are hot-glued to flashlight heads, modified for the purpose. The flashlights where originally $1.00 Rayovac all-plastic flashlights, but I used a Dremel to cut down the head to a much lower profile, and removed the mounting for the original incandescent lamp. The two spacers were then glued to another nylon fastener designed for mounting cable ties (a cable tie cradle mount) and the cable tie mount slides onto a post (modified to have its latch removed) on the 5-1/4” drive bay base plate. Here are a couple of images of the front beam assemblies (too bad the light cannot illuminate itself for the photos! Sorry!!)
The rear control panel, as described above, looks like this:
One thing to note is that the resistor to the left of the power monitor LED is an additional 220 Ohm on the Red channel of the indicator LED. This is to help compensate for the large difference in forward voltage between Red and the other two color leads. In this configuration, each color gets approximately 7 to 8 mA (which is still almost too bright for the application – I found this surprising as I expected the LED to possibly be too dim!).
Here are some shots of the indicators in various states – notice that in the image of the Red indicator, the Red value has been set to 0 and the light has become quite blue.
As I said in the opening, this project was really about testing code designs for the Maestro. I really like the simple stack-based scripting and wanted to explore its potential. The basic idea was to create a variable list at the base of the stack and manipulate it as required to emulate the usage of standard code variables. I suspected that one could create structure layouts to even implement some very basic class-oriented design principles. As the variable usage has worked beautifully, I’m pretty sure that small structures, and subroutines to work with them, could be written to really expand the horizons of what the scripting can do.
Anyway, before looking at the code, here is a screen shot of the configuration in Control Center:
The configuration is a pretty simple set of inputs and outputs, and the labels should make it clear what each does (the Red, Green, and Blue Indicator channels each drive the respective pin of the multicolor LED).
The code was fun to work out, and wound up being simpler than I expected it to be. I’m really interested to start a more complex project now; one where I can ramp-up this model and find its limits. Anyway, the code consists of a main program loop which executes five primary steps. In addition, there is a slightly modified version of the Pololu-provided script for controlling ShiftBrite modules. The logic, and most of the code, is documented in comments so I’ll just post the code and if it doesn’t explain itself, you can feel free to ask questions.
# *************************************************************************
# RGB Flashlight
# For Pololu Mini Maestro
# v1.0 - 1/3/2011
# By Reed Kimble
# *************************************************************************
# Main Program Subroutine
Sub Main
# Boot
100 delay # Wait for device circuits to energize.
# Initialize Variables
1 # [000](Bool) Has desired color changed?
3 # [001](Int ) Level Indicator Color; stack address of color component.
1 # [002](Bool) Color Component Switch state.
1000 # [003](Int ) Desired Red color component.
1000 # [004](Int ) Desired Green color component.
1000 # [005](Int ) Desired Blue color component.
# Primary program loop - 5 steps:
begin
########################################################################
# [Step 1]
#
# Check the state of the color component mode switch. When the switch
# toggles from low back to high, increment the color variable value from
# 3 to 6. This value is the memory address of the value of the selected
# color component. If the value is 6 when incremented, it is wrapped
# back to 3 (the 7 is dropped).
9 get_position # Check the state of the Indicator Button.
if # If the button state is high, check to see if it was low previously...
2 peek
if else # If the indicator button variable was low, increment the value.
1 peek
1 plus
dup 6 minus # Duplicate the incremented value, then subtract the max.
if # If the result was not 0, the incremented value is saved to
1 poke # the color variable.
else
drop 3 1 poke # If the result was 0, the incremented value is dropped
endif # and the color variable is reset to 3.
1 2 poke # Set the button state variable back to high.
endif
else # If the button state is low, just set the state variable to 0.
0 2 poke
endif
########################################################################
# [Step 2]
#
# Check the state of each color component button (Red, Green, and Blue)
# and decrement the associated variable value if the button is pressed.
3 get_position # Check the state of the Red button.
if else # If the input is low (pressed)...
rot # Get the Red variable value to work with.
10 minus dup # Decrement the value, the duplicated it for a check.
if else # If the value is 0, reset it to 1000
drop 1000
endif
rot rot # Restore the variable order
1 0 poke # Set the desired color changed variable to True
endif
# Repeat the above for the Green button and variable
4 get_position
if else
swap
10 minus dup
if else
drop 1000
endif
swap
1 0 poke
endif
# Repeat for the Blue button and variable
5 get_position
if else
# No need to manipulate the stack this time- Blue is on top.
10 minus dup
if else
drop 1000
endif
1 0 poke
endif
########################################################################
# [Step 3]
#
# Check the color component indicator variable value for each color,
# and set the multicolor indicator LED to the appropriate color.
1 peek
3 minus # Copy the indicator value and test it...
if else # If the result is 0 then the value is the Red component register
8000 6 servo # Turn on the Red lead of the indicator LED
0 7 servo # Turn off the Green lead of the indicator LED
0 8 servo # Turn off the Blue lead of the indicator LED
endif
1 peek # Repeat test for Green register, set LED accordingly
4 minus
if else
0 6 servo
8000 7 servo
0 8 servo
endif
1 peek # Repeat test for Blue register, set LED accordingly
5 minus
if else
0 6 servo
0 7 servo
8000 8 servo
endif
########################################################################
# [Step 4]
#
# Get the value of the selected color component (remember, this value
# is a memory register location for the color component value). Then
# set the gauge servo to 4 times this value, plus 4000 (the value will
# be between 0 and 1000 so this gives us a range between 4000 and 8000).
1 peek peek # Get the selected color register, then value at that register.
4 times 4000 plus
10 servo # Send the calculated value to channel 10 (the gauge servo).
########################################################################
# [Step 5]
#
# If necessary (if a color component value was changed), update the
# ShiftBrite modules.
0 peek # Check the desired color changed variable value.
if # If it is 1 (true) then copy the current color component values and
3 peek # call the rgb sub.
4 peek
5 peek
rgb
endif
0 0 poke # Reset the desired color changed variable value.
#########################################################################
# Continue execution of the main program loop.
repeat
return
# The following is a copy of the Pololu supplied ShiftBrite script, with
# minor modifications to copy the last three values, then send the
# ShiftBrite packet twice before flipping the latch (to set both lights
# to the same color at the same time).
# Subroutine for setting the RGB value of a ShiftBrite/ShiftBar.
# example usage: 1023 511 255 rgb
sub rgb
swap rot rot
depth 3 minus peek
depth 3 minus peek
depth 3 minus peek
0 send_bit # this bit does not matter
0 send_bit # the "address" bit - 0 means a color command
send_10_bit_value
send_10_bit_value
send_10_bit_value
0 send_bit
0 send_bit
send_10_bit_value
send_10_bit_value
send_10_bit_value
0 1 8000 1 servo servo # toggle the latch pin
return
# sends a numerical value as a sequence of 10 bits
sub send_10_bit_value
512
begin
dup
while
over over bitwise_and send_bit
1 shift_right
repeat
drop drop
return
# sends a single bit
sub send_bit
if 8000 else 0 endif
2 servo # set DATA to 0 or 1
0 0 8000 0 servo servo # toggle CLOCK
Return
So that’s pretty much it; the One-Million-Color Flashlight! I’m hoping to buy another Maestro so I can start another project (not sure what yet!) without tearing this one apart. It was designed to come apart easily enough, but I’m not quite ready to do that yet! At any rate, I definitely want to explore the limits of the Maestro, and may have to pop over to the New Product Suggestion forum and provide a wish-list of my own!
Thank you, Pololu for giving me such neat toys (and potential tools)!!