http://tonious.ca/Tony Thompson2012-02-29T13:00:00ZTony Thompsonhttp://tonious.catag:tonious.ca,2012-02-29:/2012/02/new-site/And we're back.2012-02-29T13:00:00Z2012-02-29T13:00:00Z<p>Well, that was a bit of an extended absence. It's been about two years since I
have seriously updated this site, and about six months getting around to a new
site layout. In the last two years, quite a lot has happened:</p>
<ul>
<li><a href="http://www.diyode.com">Diyode</a> is off the ground, and we may actually survive!</li>
<li>I've achieved gainful employment at <a href="http://www.mrx.ca">MRX</a>.</li>
<li>I've delved back into my masters degree.</li>
</ul>
<p>The new version of this site is statically built, and compiled with <a href="http://nanoc.stoneship.org/">nanoc</a>.
This time I've decided to build the site template from scratch. This means
there may be sporadic service until I get everything squared away neatly. In
the mean time, there's a <a href="/colophon/">colophon</a> that outlines some of the
software used, and where to find it.</p>
tag:tonious.ca,2010-02-16:/2010/02/valentines-card/Valentines Day Card 20102010-02-17T03:03:28Z2010-02-17T03:03:28ZEvery year, I make Sheena a Valentines card. A few years ago I didn't have a
chance to go to the local card shop, and made one from art supplies I had on
hand. Now I'm doomed -- I can't go back to buying cards.
<div>
<object type="application/x-shockwave-flash" width="500" height="281" data="http://www.flickr.com/apps/video/stewart.swf?v=71377" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"> <param name="flashvars" value="intl_lang=en-us&photo_secret=9ffc8bfdc6&photo_id=4363334389&flickr_show_info_box=true"></param> <param name="movie" value="http://www.flickr.com/apps/video/stewart.swf?v=71377"></param> <param name="bgcolor" value="#000000"></param> <param name="allowFullScreen" value="true"></param><embed type="application/x-shockwave-flash" src="http://www.flickr.com/apps/video/stewart.swf?v=71377" bgcolor="#000000" allowfullscreen="true" flashvars="intl_lang=en-us&photo_secret=9ffc8bfdc6&photo_id=4363334389&flickr_show_info_box=true" height="281" width="500"></embed></object>
</div>
This year I decided to raise my game a little, or at least incorporate another
hobby. As I mentioned <a
href="http://www.tony.thompson.name/2010/02/blinky/">earlier</a>, this is a
blinky sign. It has an 8x8 LED matrix and an Atmel ATmega48 on board, as well
as a CR2032 watch battery. The ATmega uses its internal oscillator, so there
is very little supporting circuitry. It doesn't sound exciting on it's own,
but context is everything.
<div>
<a href="http://www.flickr.com/photos/tonious/4363986814/" title="Valentines
Card by tonious, on Flickr"><img
src="http://farm5.static.flickr.com/4014/4363986814_1f3ab1d769.jpg" width="500"
height="334" alt="Valentines Card" style="border: 0px;" /></a>
</div>
The <a href="http://wyndhamartsupplies.com/">local art store</a> had cards and
envelopes in different sizes. I picked a much larger envelope as the assembled
card is rather thick. The hearts are cut from red craft foam, and hot glued on
to the card and envelope.
<a href="http://www.flickr.com/photos/tonious/4363253371/" title="Valentines Card by tonious, on Flickr"><img src="http://farm3.static.flickr.com/2758/4363253371_f1b484a114.jpg" width="500" height="334" alt="Valentines Card" style="border: 0px;" /></a>
The circuit board is bolted to an acrylic backplate. The card and a black piece of craft foam are sandwiched in place. This will hopefully prevent the circuit board from tearing through the card.
<div>
<a href="http://www.flickr.com/photos/tonious/4363257953/" title="Valentines Card by tonious, on Flickr"><img src="http://farm5.static.flickr.com/4013/4363257953_61d98bd874.jpg" width="500" height="334" alt="Valentines Card" style="border: 0px" /></a>
</div>
The software has about 25 different messages, and it steps through them each time the button is pressed. Then it puts itself into power down mode until the next button press. Updating the matrix is handled by an interrupt routine that reads from a circular buffer. There's also a putchar routine that feeds into the buffer, so I can use it with I/O streams. This lets me use <code>printf</code> to write to the matrix.
And the font: The only 8-bit font with a heart character I know of is the <a href="http://en.wikipedia.org/wiki/PETSCII">Commodore 64 system font</a>. I created ROM dumps from a C-64 quite some time ago, including the character generator. The C-64 was a strange machine by modern standards. Not only did the internal character representation differ from ASCII -- the Commodore version was called <a href="http://en.wikipedia.org/wiki/PETSCII">PETSCII</a> -- but the font in the character generation and the stored screen state both used yet another representation known as screen code. I've modified the font into something more like ASCII, with the heart character as <code>0x7f</code>. Please don't hurt me, Commodore!
The final code, with the font in program memory, comes to 4004 bytes, just fitting inside the 4096 bytes available. The font takes up 768 bytes of flash, and the avr-libc printf implementation takes up another 1.5k or so.
There are more pictures in <a href="http://www.flickr.com/photos/tonious/sets/72157623325815567/">this flickr gallery</a>.
The code is posted on <a href="http://github.com/tonious/valcard2010">GitHub</a>.
<h2>Lessons Learned</h2>
<ul>
<li>AVR microcontrollers have some mad power management capabilities. While running, this card consumes around 20 millamps. While sleeping, it consumes ~1 <em>micro</em>amp.</li>
<li>When wiring up an LED matrix, think about which end should be the most significant bit. I wired up this project to be <a href="http://en.wikipedia.org/wiki/Endianness">little-endian</a> (MSB at the right), while the font I used was big-endian (MSB at the left). This was easy enough to fix in software.</li>
<li>Additionally, I'm reaching the point where point-to-point prototyping may no longer be feasible. I guess I have to break down and learn some real circuit layout software.</li>
<li>I should probably plan ahead more -- It'll be tough to top this next year.</li>
</ul>tag:tonious.ca,2010-02-11:/2010/02/little-robots-firmware/Little Robots -- Firmware2010-02-11T23:39:23Z2010-02-11T23:39:23Z<p>
<a title="Little Robot by tonious, on Flickr" href="http://www.flickr.com/photos/tonious/4286406145/"><img style="border: 0px;" src="http://farm5.static.flickr.com/4060/4286406145_35c8a8a54b.jpg" alt="Little Robot" width="500" height="334" /></a>
</p>
This is part two of a series. <a href="http://www.tony.thompson.name/2010/01/little-robots-hardware/">Part one</a> covered the hardware build. Part three will cover the python based host software.
Without any further ado:
<h2>Firmware</h2>
This entire project was based around <a href="http://www.obdev.at/index.html">Objective Development</a>'s <a href="http://www.obdev.at/products/vusb/index.html">V-USB</a> product -- an open source <em>software</em> USB implementation. Among the AVR community, it seems to be reasonably well used, and has a nice selection of reference projects.
From the outset, I knew one robot -- the one for my desk -- would be talking to a linux or macintosh computer. However, my fiancé's robot would have be happy in windows. Unfortunately, windows devices require kernel device drivers, with a very few exceptions; the most abused being the Human Interface Device profile. So why buck a trend? HID it is.
With that in mind, two existing projects seem most useful.
<ul>
<li><a href="http://blog.flipwork.nl/?x=entry:entry081009-142605">1-Key Keyboard</a> -- the original hardware base for the little robots -- is naturally firmware compatible. In fact the belly switch of each robot does indeed work as a keyboard switch. This is a full bidirectional HID device.</li>
<li>The HID-Data example included in the V-USB distribution. This is a much simpler application -- it allows a host application to set and read the EEPROM storage in an AVR. It is unidirectional -- all interaction is initiated by the host controller.</li>
</ul>
I chose to build off the HID-Data example as it was somewhat simpler, and did come with example host software. From there, little modification was needed; I integrated the timer calibration code from the 1-key keyboard, and added some hardware PWM support.
Every interaction is controlled from the host. For example, the microcontroller counts individual button presses. The host then sends a request to read that value. The microcontroller returns the value, and then resets the counter.
Full firmware and software is available via <a href="http://github.com/tonious/littlerobots">GitHub</a>.
<h2>Servo Control</h2>
Servos are controlled via pulse width modulation. Many microcontrollers do have hardware PWM support, and the ATtiny85 is no exception. However, all of its timers have an 8-bit resolution. For my purposes, this is acceptable, but provides only about 25 steps from one end of the servo's range to the other. This works out to be about seven degrees a step. Better resolution would require a software timer.
I find with the small servos I have handy, the low end of the servo's sweep comes in at around 11, and the high end anywhere from 35 to 40.
<pre lang="C">
void pwm_set( int x ) {
OCR0B = x;
}
void pwm_init( void ) {
// Set non-inverting output mode on pin OC0B.
TCCR0A = ( 1 << COM0B1 ) | ( 0 << COM0B0 );
// Set fast pwm mode.
TCCR0A |= ( 1 << WGM01 ) | ( 1 << WGM00 );
TCCR0B = ( 0 << WGM02 );
// Use /1024 Prescaler.
// This sets a PWM frequency of ~48Hz,
// which is just about perfect for a servo.
TCCR0B |= ( 1 << CS02 ) | ( 0 << CS01 ) | ( 1 << CS00 );
}
</pre>
<h2>Lessons Learned</h2>
<ul>
<li>Include a programming header on a development board. For every firmware revision I had to pop the AVR out, reprogram it, and reinstall it. As simple as the process is, it gets old real quick.</li>
<li>Chip self-protection features are your friend. For example, under-voltage detection and hardware watchdog timers are very useful. When a computer -- especially a laptop -- reboots, it may brown out devices on the USB bus. A microcontroller may come back up in an undefined state. One of the robots burnt out a servo when it flaked out on a reboot.</li>
<li>Embedded software is actually <em>fun</em> to write! It's simple, clean and very scope limited. Perfect for a satisfying hobby project.</li>
</ul>tag:tonious.ca,2010-02-08:/2010/02/blinky/This Weekend's Project.2010-02-08T19:47:33Z2010-02-08T19:47:33Z<object data="http://www.elsewhere.org/mbedr/?p=4341616466&v" type="text/html" height="334" width="500"><a href="http://www.flickr.com/photos/tonious/4341616466/" title="Blinky Sign by tonious, on Flickr" target="_blank"><img src="http://farm5.static.flickr.com/4066/4341616466_45c9a0d0da.jpg" width="500" height="334" alt="Blinky Sign"/></a></object>
I was inspired last night, so I made this little gizmo. It's a blinky sign, about the size of a 3x5 index card. It's destined for a specific purpose, so check back in a couple weeks for the reveal.tag:tonious.ca,2010-02-04:/2010/02/democamp-guelph-success/DemoCamp Guelph Success!2010-02-05T02:25:07Z2010-02-05T02:25:07ZLast week I presented my <a href="http://www.tony.thompson.name/2010/01/little-robots-hardware/">little robots</a> at <a href="http://www.democampguelph.com/">DemoCamp Guelph</a>. And to my surprise, I took home the much coveted <em>Crowie</em> award for best presentation.
<a href="http://www.flickr.com/photos/tonious/4331465464/" title="The Crowie by tonious, on Flickr" style><img src="http://farm3.static.flickr.com/2744/4331465464_fa66344902.jpg" width="500" height="334" alt="The Crowie" style="border:none;"/></a>
There's a USB stick on the back with the names of previous winners. I added myself to the list, then I held the Crowie aloft and said:
<blockquote>By the power of Greyskull!</blockquote>
And nothing happened. So it must be broken. Here's what's inside:
<object data="http://www.elsewhere.org/mbedr/?p=4330734575&v" type="text/html" height="334" width="500"><a href="http://www.flickr.com/photos/tonious/4330734575/" title="Crowie Internals by tonious, on Flickr" target="_blank"><img src="http://farm3.static.flickr.com/2707/4330734575_bb15fc0690.jpg" width="500" height="334" alt="Crowie Internals"/></a></object>
I clearly need to add more magic. I've got a few ideas in mind -- I'll post more as they come to fruition.
In other news, I upgraded the firmware on the little robots. They're now safely back on our respective desks, and keep my fiancé and I in touch all day.tag:tonious.ca,2010-01-27:/2010/01/little-robot-presentation-tonight/Little Robot Presentation! Tonight!2010-01-27T20:00:36Z2010-01-27T20:00:36Z<a style="border: 0px;" title="Little Robots by tonious, on Flickr" href="http://www.flickr.com/photos/tonious/4254732895/"><img src="http://farm5.static.flickr.com/4015/4254732895_8a71c0b591.jpg" alt="Little Robots" width="500" height="304" style="border: 0px;" /></a>
I'm going to be talking these little robots tonight, at <a href="http://www.democampguelph.com/">DemoCamp Guelph</a>! Proceedings get underway at about 6:30 at the eBar.tag:tonious.ca,2010-01-19:/2010/01/little-robots-hardware/Little Robots -- Hardware2010-01-19T06:48:04Z2010-01-19T06:48:04Z<object type="application/x-shockwave-flash" width="500" height="375" data="http://www.flickr.com/apps/video/stewart.swf?v=71377" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"> <param name="flashvars" value="intl_lang=en-us&photo_secret=d6d35fba27&photo_id=4287284794&flickr_show_info_box=true"></param> <param name="movie" value="http://www.flickr.com/apps/video/stewart.swf?v=71377"></param> <param name="bgcolor" value="#000000"></param> <param name="allowFullScreen" value="true"></param><embed type="application/x-shockwave-flash" src="http://www.flickr.com/apps/video/stewart.swf?v=71377" bgcolor="#000000" allowfullscreen="true" flashvars="intl_lang=en-us&photo_secret=d6d35fba27&photo_id=4287284794&flickr_show_info_box=true" height="375" width="500"></embed></object>
This is part one of a three part series: <a href="http://www.tony.thompson.name/2010/02/little-robots-firmware/">Part two</a> covers the firmware, and part three will cover the software.
I find interaction design to be pretty fascinating. And lets face it, most of the technology we deal with on a daily basis has not been designed with interaction in mind. Or at least not <em>subtle</em> interaction.
Take telephones: they're a priority interrupt. When a phone rings, you go through a full context switch. You have to stop what you're doing to answer. Email doesn't interrupt, but it's not priority either. Email doesn't say "I'm thinking of you" it says "I thought of you twenty minutes ago". These are great examples of technologies that meet their minimum need; they do work, but do they work well? Is email the best way to get text from one human being to another? My spam filter says no. Is the telephone the best way to tell someone you were just thinking about them?
When you're in a room with someone, there are many different subtle ways to indicate that you enjoy their presence. Everything from where you sit to how you breath has at least some degree of significance -- some degree of communication. This project was my way of performing that communicative act, when I'm <em>not</em> in a room with that someone.
Enough waxing philosophical: I made two little robots. One for my fiancé's desk, and one for mine. When you poke one in the belly, the other one waves.
Without further ado, here's part one:
<h2>Hardware</h2>
The hardware on this project is absolutely informed by the firmware. From the outset I expected to use <a href="http://www.obdev.at/products/vusb/index.html">Objective Development's V-USB</a> package. It provides a software USB stack capable of running on 8-bit Atmel AVR microcontrollers.
With that in mind, I sought a challenge and picked the smallest AVR I could get on short notice -- the ATtiny85, in an 8-pin DIP package. This is a pretty powerful chip, at least for these purposes. Less than $3 Canadian gets 8kB of flash program storage, a half a kilobyte of RAM, two hardware timers, and an internal oscillator.
Not really being one to reinvent the wheel, I found an existing project using the same firmware and microcontroller -- the <a href="http://www.blog.flipwork.nl/?x=entry:entry081009-142605">one key keyboard</a> by <a href="http://www.flipwork.nl/">Flip van den Berg</a>. After some ethical deliberations, I shamelessly took his schematic, and breadboarded out myself:
<object data="http://www.elsewhere.org/mbedr/?p=4252021321&v" type="text/html" height="375" width="500"><a href="http://www.flickr.com/photos/tonious/4252021321/" title="Prototype USB Layout by tonious, on Flickr" target="_blank"><img src="http://farm5.static.flickr.com/4020/4252021321_064150a06f.jpg" width="500" height="375" alt="Prototype USB Layout"/></a></object>
To my surprise, it actually ran! You can make a USB keyboard on a breadboard! And it works on any computer that supports HID compliant devices!
The next step was to take the same circuit, and put it on something a little bit more permanent. In this case, some protoboard. The circuit on the left is a programming target board, with a standard programming header. I use it with an <a href="http://www.adafruit.com/index.php?main_page=product_info&products_id=46">Adafruit USBtinyISP</a> programmer. The circuit on the right is the USB controller with a button and header for a servo motor.
Servos are fairly useful beasts. They don't really need drivers. Supply them with a suitable PWM signal, and they'll drive themselves. In this case, the servo is powered off the +5v USB supply, even though the microcontroller is running at +3.3v. My servo didn't seem to care, and quick google searching suggests that this is pretty standard; servos will amplify their PWM signal internally.
<object data="http://www.elsewhere.org/mbedr/?p=4252024755&v" type="text/html" height="375" width="500"><a href="http://www.flickr.com/photos/tonious/4252024755/" title="ATtiny85 target board and USB test board. by tonious, on Flickr" target="_blank"><img src="http://farm5.static.flickr.com/4031/4252024755_d7306f049a.jpg" width="500" height="375" alt="ATtiny85 target board and USB test board."/></a></object>
So at this point I found that the electronics basically worked. I was able to control a servo, and read button presses. So now for some larger scale hardware.
I don't have access to a full shop, so I relied on a low impact sculpting material: Sculpey, a polymer clay, similar to Fimo. A little armature wire, some low-fidelity sculpting and the parts went into the oven at 250° F for about 15 minutes. As easy as sculpey is to work, it is even easy to rework. Hot glue and acrylic paint stick to it quite happily.
<object data="http://www.elsewhere.org/mbedr/?p=4252070627&v" type="text/html" height="375" width="500"><a href="http://www.flickr.com/photos/tonious/4252070627/" title="Little Robot Parts by tonious, on Flickr" target="_blank"><img src="http://farm5.static.flickr.com/4061/4252070627_74908cc263.jpg" width="500" height="375" alt="Little Robot Parts"/></a></object>
Next, I installed the guts with lots of hot glue.
<object data="http://www.elsewhere.org/mbedr/?p=4286419365&v" type="text/html" height="334" width="500"><a href="http://www.flickr.com/photos/tonious/4286419365/" title="Little Robot Guts by tonious, on Flickr" target="_blank"><img src="http://farm5.static.flickr.com/4052/4286419365_e35ab54c60.jpg" width="500" height="334" alt="Little Robot Guts"/></a></object>
Then I painted the exterior with acrylic spray paint. I touched up the eyes with acrylic paint, and added craft foam tank treads and covers for the belly-switches.
<object data="http://www.elsewhere.org/mbedr/?p=4253015364&v" type="text/html" height="334" width="500"><a href="http://www.flickr.com/photos/tonious/4253015364/" title="Little Robots by tonious, on Flickr" target="_blank"><img src="http://farm3.static.flickr.com/2798/4253015364_e5625b0caa.jpg" width="500" height="334" alt="Little Robots"/></a></object>
And here's what they look like from the back.
<object data="http://www.elsewhere.org/mbedr/?p=4253017512&v" type="text/html" height="334" width="500"><a href="http://www.flickr.com/photos/tonious/4253017512/" title="Little Robot Innards by tonious, on Flickr" target="_blank"><img src="http://farm3.static.flickr.com/2746/4253017512_c3cc6da676.jpg" width="500" height="334" alt="Little Robot Innards"/></a></object>
Next up: <a href="http://www.tony.thompson.name/2010/02/little-robots-firmware/">The firmware!</a>
<strong>Update:</strong> This article was featured on <a href="http://blog.makezine.com/archive/2010/01/little_robots_cute_tutorial_on_buil.html">Make: Online</a>.tag:tonious.ca,2010-01-15:/2010/01/arduino-physical-computing-demo/Arduino / Physical Computing Demo!2010-01-15T23:09:31Z2010-01-15T23:09:31Z<object data="http://www.elsewhere.org/mbedr/?p=4253005198&v" type="text/html" height="334" width="500"><a href="http://www.flickr.com/photos/tonious/4253005198/" title="Arduino Duemilanove by tonious, on Flickr" target="_blank"><img src="http://farm3.static.flickr.com/2742/4253005198_b644fc3ed7.jpg" width="500" height="334" alt="Arduino Duemilanove"/></a></object>
At the next Guelph <a href="http://www.coffeeandcode.org/">Coffee and Code</a>. I will give a short demonstration of the <a href="http://arduino.cc">Arduino</a> platform. This will be a variation of a talk I gave while TA-ing the Human Computer Interaction course at the <a href="http://www.uoguelph.ca">University of Guelph</a>. It's not going to be technically heavy -- there will be lots of pictures, lots of live demonstrations and a little bit of fire, all in the name of science!
If you are in Guelph, and curious about the Arduino platform, or hardware hacking in general, please come on out to the Synnema, next Thursday (the 21st)!tag:tonious.ca,2010-01-11:/2010/01/little-robot-preview/Little Robot Preview.2010-01-11T20:42:31Z2010-01-11T20:42:31Z<a href="http://www.flickr.com/photos/tonious/4254732895/" title="Little Robots by tonious, on Flickr" style="text-decoration: none; border: 0px;"><img src="http://farm5.static.flickr.com/4015/4254732895_8a71c0b591.jpg" width="500" height="304" alt="Little Robots" style="border: 0px"/></a>
For our wedding save-the-date cards, I drew two little robots.
For Christmas, I made little robots for Sheena.
<object data="http://www.elsewhere.org/mbedr/?p=4253015364&v" type="text/html" height="334" width="500"><a href="http://www.flickr.com/photos/tonious/4253015364/" title="Little Robots by tonious, on Flickr" target="_blank"><img src="http://farm3.static.flickr.com/2798/4253015364_e5625b0caa.jpg" width="500" height="334" alt="Little Robots"/></a></object>
They're USB powered -- one for her desk and one for mine. When you poke one, the other will wave, wherever they happen to be.
These are powered by an ATtiny85, Objective Development's <a href="http://www.obdev.at/products/vusb/index.html">V-USB</a> and <a href="http://www.python.org">python</a>.
More details to come soon.tag:tonious.ca,2010-01-11:/2010/01/arc-reactor/An AVR Powered Arc Reactor2010-01-11T20:30:14Z2010-01-11T20:30:14Z<object type="application/x-shockwave-flash" width="500" height="281" data="http://www.flickr.com/apps/video/stewart.swf?v=71377" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"> <param name="flashvars" value="intl_lang=en-us&photo_secret=78594a5233&photo_id=4257438740"></param> <param name="movie" value="http://www.flickr.com/apps/video/stewart.swf?v=71377"></param> <param name="bgcolor" value="#000000"></param> <param name="allowFullScreen" value="true"></param><embed type="application/x-shockwave-flash" src="http://www.flickr.com/apps/video/stewart.swf?v=71377" bgcolor="#000000" allowfullscreen="true" flashvars="intl_lang=en-us&photo_secret=78594a5233&photo_id=4257438740" height="281" width="500"></embed></object>
For Hallowe'en last year I wanted to go as Tony Stark on a night out. There are quite a few Arc Reactor projects floating around the internet, but I wanted something that would shine through a dress shirt, and have a bit of motion to it.
<h2>Hardware</h2>
I was inspired by <a href="http://spritesmods.com/">Sprite</a>'s post on <a href="http://spritesmods.com/?art=minimalism">electronic minimalism</a>. He points out that many components that are necessary in traditional electronics can be omitted when using a microcontroller. You can fake some hardware in <em>software</em>.
With that in mind, <a href="http://hcgilje.wordpress.com/">HC Gilje</a> has a great write-up on how to make a truly minimal <a href="http://hcgilje.wordpress.com/resources/arduino-standalone/">arduino clone</a>, using the <a href="http://web.media.mit.edu/~leah/LilyPad/">LilyPad arduino</a> firmware.
I wrote the software, and did about half the assembly. Matt Englert did the other half, soldering up the controller board in less than half an hour with no schematic and a semi-coherent description from me. It's pretty basic. The ring is made of 3mm white LEDs hotglued into a piece of dollar store cutting board. I think this one is polystyrene rather than HDPE. The LEDs have a common cathode. Their other ends are connected directly to the microcontroller on pins 6 and 11 to 19 -- that corresponds to digital 4 to digital 13 in the arduino environment.
There are no current limiting resistors. Each LED is controlled via pulse width modulation or PWM. Rather than a constant current, they are each turned on and off at about 250 Hz. By varying the duty cycle, the microcontroller can set the brightness of each LED.
LEDs are like any other component: their specifications are approximate, and recommended values. You can overpower just about any component for small amounts of time. By making sure these LEDs are never given a 100% duty cycle, I felt okay overpowering them. This is an exercise in minimal circuitry. And truth be told, it only needed to last one night.
Mouse over these pictures for more details:
<object data="http://www.elsewhere.org/mbedr/?p=4252233103&v" type="text/html" height="334" width="500"><a href="http://www.flickr.com/photos/tonious/4252233103/" title="Arc Reactor (Back) by tonious, on Flickr" target="_blank"><img src="http://farm5.static.flickr.com/4016/4252233103_6612cfee43.jpg" width="500" height="334" alt="Arc Reactor (Back)"/></a></object>
<object data="http://www.elsewhere.org/mbedr/?p=4253000532&v" type="text/html" height="334" width="500"><a href="http://www.flickr.com/photos/tonious/4253000532/" title="Arc Reactor (Front) by tonious, on Flickr" target="_blank"><img src="http://farm5.static.flickr.com/4068/4253000532_385d8a3222.jpg" width="500" height="334" alt="Arc Reactor (Front)"/></a></object>
Given that a typical AAA has about 750mAh of capacity, and this gizmo was still going at noon the next day, it averaged about <a href="http://www.google.ca/search?q=750+milliamp*hours+%2F+18+hours+in+milliamps">40 milliamps</a>.
<h2>Software</h2>
The ATmega168 chip only has six hardware PWM outputs, and for this project I needed ten. Dimming an LED is a pretty trivial application. Doing PWM in software will certainly be sufficient.
The dimming is handled by a function called update_dimmer(). It is called by a timer interrupt at 4kHz. With 16 dimming levels, a complete PWM cycle occurs about 250 times a second.
The animation is handled by animate_rotating_sine(). It runs constantly, but only updates the animation every 25 milliseconds. The animation is timed to rotate about 70 times a minute, or roughly equivalent to the average human heart rate.
Here's the source code:
<pre lang="arduino" class="brush: arduino; toolbar: false;">
#define ARC_START 4 // Circle of LEDs starts at digital pin 4 (Arduino, not AVR)
#define ARC_SIZE 10 // There are 10 leds.
// Dimming parameters.
#define PIN_DUTY_CYCLE 16 // Number of dimming levels to support
int pin_duty_cycle = 0; // Where are we in the current dimming cycle.
int pin_duty[ ARC_SIZE ]; // Gray level for each pin. Should < PIN_DUTY_CYCLE
// Animation parameters.
#define ANIMATION_INTERVAL 25 // milliseconds
long animation_time = 0; // When did we last update the animation?
#define ANIMATION_CYCLE (((60.0*1000)/(70*ANIMATION_INTERVAL))) // should be about 70bpm -- avg human heart rate.
int animation_cycle = 0; // Where are we in the animation cycle?
#define CPU_FREQ 8000000.0 // Timer2 runs at this speed. Needed for interrupt calculations.
#define TIMER2_DIVISOR 32
#define TIMER2_FREQ ( CPU_FREQ / TIMER2_DIVISOR )
// The setup() method runs once, when the sketch starts
void setup() {
// Set LED pins to output.
for( int pin = 0; pin < ARC_SIZE; pin++ ) {
pin_duty[ pin ] = 0;
pinMode( ARC_START + pin, OUTPUT );
digitalWrite( ARC_START + pin, OUTPUT );
}
// Update our dimming level periodically.
SetupTimer2(4000);
rotate_blink();
}
// Initialize Timer 2
// Shamelessly taken from http://www.uchobby.com/index.php/2007/11/24/arduino-interrupts/
unsigned char SetupTimer2( float timeoutFrequency ){
unsigned char result; //The timer load value.
//Calculate the timer load value
result=(int)((257.0-(TIMER2_FREQ/timeoutFrequency))+0.5);
//The 257 really should be 256 but I get better results with 257.
//Timer2 Settings: Timer Prescaler /32, mode 0
TCCR2A = 0;
TCCR2B = 0<<CS22 | 1<<CS21 | 1<<CS20;
//Timer2 Overflow Interrupt Enable
TIMSK2 = 1<<TOIE2;
//load the timer for its first cycle
TCNT2=result;
return(result);
}
// Interrupt Handler
ISR( TIMER2_OVF_vect ) {
dimmer_update();
}
void dimmer_update() {
// For each LED
for( int pin = 0; pin < ARC_SIZE; pin++ )
// Adjust each pin to reflect current duty cycles.
if( pin_duty[ pin ] <= pin_duty_cycle )
digitalWrite( ARC_START + pin, LOW );
else
digitalWrite( ARC_START + pin, HIGH );
// Update our place in PWM cycle.
pin_duty_cycle = ( pin_duty_cycle >= PIN_DUTY_CYCLE ) ? 0 : pin_duty_cycle + 1;
}
void rotate_blink() {
// Animation start up. Pulse each LED.
for( int pin = 0; pin < ARC_SIZE; pin++ ) {
pin_duty[ pin ] = 0.75 * PIN_DUTY_CYCLE;
delay( 100 );
pin_duty[ pin ] = 0;
delay( 50 );
}
}
void animate_rotating_sine() {
// We might have just overflowed. Overflown?
if( millis() < animation_time )
animation_time = 0;
if( millis() - animation_time > ANIMATION_INTERVAL ) {
// Where is the sine rotated overall?
float animation_angle = PI * 2 * animation_cycle / ANIMATION_CYCLE;
for( int pin = 0; pin < ARC_SIZE; pin++ ) {
// How far around the arc is this LED?
float led_angle = PI * 2 * pin / ARC_SIZE;
// Values tweaked for appearance; there's no science here :)
pin_duty[ pin ] = ( sin( animation_angle + led_angle ) + 2 ) * PIN_DUTY_CYCLE / 3 *.9;
}
animation_time = millis();
animation_cycle = ( animation_cycle >= ANIMATION_CYCLE ) ? 0 : animation_cycle + 1;
}
}
// the loop() method runs over and over again,
// as long as the Arduino has power
void loop()
{
animate_rotating_sine();
}
</pre>