My code is kudzu, but have the basics for the new BlinkM running. One thing I didn't think about was that mixing to amber isn't wonderful on an RGB LED. It makes an "okay" candle but it isn't a lovely color. Might be better to build one from scratch around a 1 watt amber LED instead!
Except -- one thing I was thinking as I remembered how real candles and lanterns look, is that they don't just dim up and down. The location of the light SHIFTS over time, which can lead to very visible flickering shadows. So a cluster of amber LEDs, each fading independently, is a better model and a better effect.
So maybe I should just design my own board from scratch. Sigh.
In other electronics news, one of the three shows in the pipeline might have an R/C robot in it. I think the director's idea was that we would find a cool toy robot and use it, but just maybe we'll make up our own stage-sized, 1970's looking, camera-toting robot.
A fresh look around and we could put together a tracked chassis and controller for a bit over a hundred bucks. How long it would take to program to respond to the controller is unknown -- it might be a simple plug-and-play, or it might be a hassle.
Well, back to trimming the kudzu. I'm using a hand-drawn look-up table to smooth the fade curve (128 possible programmed levels feeds into 255 pulse width positions). I'm still using delay(microseconds) instead of delving into an interrupt timer, because I'm pretty sure the built-in Arduino functions are all pointing at the wrong register locations for an ATtiny45. Actually, I'm rather surprised at how much of the Arduino code compiles without issue on the ATtiny. If I really cared about performance I'd re-do the code in straight C.
I've tried three different methods of plugging in target values; the random(min, max) function, a toggle or switch/case for simple binary looks (like a power button pulse), and an array for multi-step programs.
I haven't added the next layer of the code, which is smooth cross fading from one running program to another. I'm not sure it is actually needed. What I DO have to try out soon is the button method. At Makers Faire, ThingM was showing off a couple of MaxM demonstrations with program functions through that analog input port. So it obviously can be done. Unfortunately that same pin is part of the ISP header, so programming and testing this is likely to be fun.
As I suspected, it was fun -- the exposed analog I/O pin is shared with Sck -- the clock pin necessary for programming. So spent a delightful hour pulling out and putting back that pin so I could try out different software interpretations of the analog input.
The concept proofs. Using a 500K linear slide pot, I am able to solidly dial in at least 10 selections. Once I get it off breadboard and soldered up properly with power supply smoothing and so forth it should be just fine.
But writing various "looks" so I could see what it was like to switch between them really impressed on me that I need to finish the "program step" code that will allow me to simply write a short array of numbers and let the software take care of the rest of it.
It never is quite so simple, is it? I wrote a somewhat cool set of functions that read off target values from an array. This meant I could write new looks just by writing columns of four numbers (R, G, B intensity and Fade Rate.) In addition, a set of "999" codes told the software whether to loop back or hold at the end of the array values.
Except. Because of my shaky breadboard and random old potentiometers -- plus the hassle of pulling the Scl Pin out of the programmer and putting it back over and over -- I didn't realize the jitter I was seeing was actually in the code.
Apparently arrays are a bit funky on the ATtiny. Or they are funky when combined with things like AnalogRead. Because even when I gave up on getting stable behavior with the analog pin, I still couldn't switch looks with a digital input without all sorts of funny behavior.
So I tossed that whole section of code. As it turned out anyhow, most of the looks I wanted to write were randomized functions (candle light, color swirls) and those were already rather shoe-horned into the array value code. But I did have to give up being able to change looks any arbitrary point in a fade cycle; all those button calls were making the fades jittery.
The new version works. It was solid enough going from look to look via potentiometer, which means that a selected resistor soldered to a switch will work just fine. And since I'd already gone too late to start on other tasks, I checked out the XBee connection as well. Since the XBee node I was using was configured to reset the pin values after 650 ms, I had to do a bit of a hack to be able to switch looks. In the proper version, the XBee will maintain a particular pin state and thus the BlinkM will always be able to detect it the next time it hits the end of a fade loop.
But I'd say the concept is now well and truly proofed.
The question is, is it worth it? For what I want to do with theatrical candles or lanterns, it might be smarter to purchase amber LEDs and create a custom circuit. Even using a through-hole ATtiny, in the 8-pin DIP configuration the electronics package is still going to be smaller than the battery. And for other applications, like the Witch's Crystal Ball for "Wizard of Oz," I think I need more output than the BlinkM can give me.
And here we have a few choices, all of them poor. The MaxM, which can take the same programming but is about twice the cost of the BlinkM. SparkFun has a fairly cheap breakout and driver board for the Luxeon LEDs but it is badly designed and using it just offends the engineer in me. The ATtiny chip by itself tops out at the 30 mW or so of the Piranha LEDs (and buying ATtinys and Piranhas in bulk is a lot cheaper than buying BlinkMs) but that is not any brighter. There are some driver chips that will handle an intermediate value...but at some point you need to admit what you need for some effects is close to the output of a theatrical instrument. So we're talking 5 watt LEDs here and a lot of work with drivers and power supplies and heat sinks.
Well. The concept is proofed, but it is hard to show off a breadboard with ISP and battery pack stuck to it with double-stick. I might, might just find a cheap candlestick -- even better, one that already has a fake candle flame at one end -- and hack it to the full glory of a remote-controlled candle.
November 9, 2012 --
Made two more discoveries. First is that the current show is using a dozen or so of those LED tea candles, and they are quite bright enough for what they are doing. So the BlinkM, modified or not, may not be capable of doing all of the effects I wanted from it, but it can make a realistic candle.
(I also brought my current circuit to a dinner party and left it running on a coffee table -- and the host asked "is that candle over there safe or should we put it out before it catches something on fire?")
The other was discovery of an article on the internal coding of the Arduino "digitalWrite" function. It had not occurred to me that the function could be THAT inefficient. 56 program cycles? This explains why my math was off by what appeared to be (without benefit of an oscilloscope) about two magnitudes.
So writing a new version that uses direct pin manipulation instead of the Arduino macro would run a good 50 times faster. And that would mean smoother fading.