For some reason, I am drawn to Will-o'-the-wisp even though I have never seen them. Fortunately I have an inclination for breaking things and making things and it seemed obvious that I would need to make my own Will-o'-the-wisp with some hardware and software hacking.
In a nutshell, I wanted to put some LEDs in a lantern and randomize the LEDs brightness with a computer to emulate a flickering effect.
Hardware Used
- phone cord : because I have plenty of it
- tin candle lantern : because it was available
- beaglebone ( I used my wall mounted beaglebone ) : because it can have more than one PWM controlled pin
Will-o'-the-Wisp Hardware
The Lantern
This tin candle lantern was the obvious choice for this project because it has been at my home for a few years and I don't really use it. TAKE IT APART!!!
There was a small tin cylinder in the lantern that held candles. Some gentle twisting quickly removed the holder. This was followed by sanding the inside of the lantern to make it more reflective and then small hole was punched in the bottom of the lantern.
This was my first time working with tin.
Solder some LEDs
Three bright LEDs were soldered to a four wire phone cord. Three wires for power and one wire for ground. The phone line adapter was scavenged from a broken touch-tone phone.
pfffttt touch tone
Hack a Notch in the Box
While putting together this hack, I thought it would be a good idea to include a phone cord jack for the rotary input device as well as the lantern.
Why Cringe?
I have friends that are wood crafters, and whenever they see my wood working skills they cringe a little bit. The easiest solution to the problem is to not show them what I do, but that wouldn't be as much fun.
Two phone cord jacks hot glued into the notch. It looks fairly flush on the top... and functional (which is what I really want).
Move the Beaglebone
While I had the box disassembled, I move the stand-offs closer to the wall of the box so that the beaglebone's USB port can be accessed more easily. I don't know what I'll use the USB port for, but it's nice to know that it is ready when I need it.
Plugged In Phone Jacks
All glued up, the lid closes properly, and I'm happy.
On the left is the lantern cord and the rotary phone is on the right.
LEDs
The LEDs are mounted in the tin lantern with a heavy dollop of hot glue! RAD!
Will-O'-The-Wisp Code
For this project, I opted to use the Ruby programming language because... well... just because. For now, all I need is a bit of File IO to write data to files. One of the reasons that I'm such a fan of the beaglebone is that in most instances, controlling the pins can easily be done simply by writing to a file.
All I really need to do, is have 3 instances of PWM on the Beaglebone and set the value of the pins to a random number in order to emulate a flickering effect.
Enter the Ruby
#define the pins that will be used, and their muxing values
#these are:
# 9.14
# 9.16
# 8.13
pins = [
{:mux_value=>6, :mux_target=>"gpmc_a2", :pwm_dir=>"ehrpwm.1:0"},
{:mux_value=>6, :mux_target=>"gpmc_a3", :pwm_dir=>"ehrpwm.1:1"},
{:mux_value=>4, :mux_target=>"gpmc_ad9", :pwm_dir=>"ehrpwm.2:1"}
]
#a class to represent an LED
class Wisp
def initialize( pin )
@min_val = 0
@max_val = 100
#set the pwm_dir
pwm_dir = File.join("/sys/class/pwm",pin[:pwm_dir])
#set the pwm duty_percent file
@duty_percent = File.join(pwm_dir, "duty_percent")
@run = File.join(pwm_dir, "run" )
#mux the target
target = File.join("/sys/kernel/debug/omap_mux", pin[:mux_target])
set_file_value(target, pin[:mux_value] )
#set up the PWM
set_file_value(@duty_percent, 0)
set_file_value(File.join(pwm_dir,"period_freq"), 100)
set_file_value(@run, 1)
end
def clean_up()
set_percent(0)
set_file_value(@run,0)
end
def set_percent( value )
set_file_value(@duty_percent, value)
end
def random()
val = rand(@min_val..@max_val)
set_percent(val)
end
def set_min_val(value)
@min_val = value if value >=0 and value <=100
end
def set_max_val(value)
@max_val = value if value >=0 and value <=100
end
private
def set_file_value(file, value)
#puts "#{file} : #{value}"
File.open(file, 'w') do |f|
f.puts( value )
end
end
end
#make an array of wisps
wisps = pins.each.map {|p| Wisp.new(p)}
#we want to create a controllable loop
loop = true
#let Ctrl+c break the loop
trap "INT" do
loop = false
end
#start looping
while loop do
#give each wisp a random percent
wisps.each do |w|
w.random()
end
#take a bit of a nap
sleep 0.1
end
#when the loop is broken, clean up
wisps.each do |w|
w.clean_up()
end
For easy copy and paste, this code is available at http://hoof.jezra.net/snip/o6.
It should be noted that this code is running on a beaglebone Rev. 3 using Arch Linux.
If I had the hardware, I probably would have used an ethernet cable instead of a phone cord. That way, I could run 7 LEDs instead of 3. Well it works, and that's what really counts. Now I have to start writing the web UI that will allow me to control the LEDs from a web browser. In case you haven't noticed, I like internetted things.
Now quit reading, and go find a will-o'-the-wisps.