Saturday, May 26, 2012

Blink..and you miss it

I thought about titling this "Don't blink" in honor of the great Doctor Who episode, but that would sound like I was recommending against the ThingM products.

And that isn't true.  I think the BlinkM is, unfortunately, underpowered for theatrical use.  I took my breadboard out to the theater and viewed it from stage distance against a variety of subdued lighting looks and the best that can be said is that it will light up a diffuser globe real well with color.  Casting light you can see on an actor, though...not so much.

So it is time to play Tool-Tim Tim, but there are a bewildering variety of options for "More Power!"  I spent a while trying to spreadsheet them (and downloading lots and lots of datasheets from different manufacturers).  And, well...for a smaller and simpler battery-powered device the BlinkM MaxM is actually quite competitive.  So my work in hacking up alternate software wasn't a complete waste (although I really need to rewrite the core function as an interrupt-driven loop -- and there are some cute PWM tricks you can do to speed things up even more).

At the lowest price end of the options, the ATtiny chips can sink 40 ma from each of the I/O pins.  Each channel in an RGB "Piranha" LED is about 20 ma.  So technically one CPU chip could drive as many as three Pirahna, making it 3x the power output.  Which of course will not appear 3x as bright in most situations!  There are other 20 ma LEDs around, but most of the super-bright and ultra-bright (which inevitably give misleading specs in millicandella) are narrow-angle.  And that just isn't appropriate for most of the lighting applications I have in mind.  One exception is the "flat-top" LED sold by some Hong Kong suppliers, which offers 25 ma and a half angle of 120 degrees.

For making a pure candle (or perhaps some RGB thing that is around the same effective output) it is hard to beat the price point of buying ATtiny's and Piranha LEDs in bulk.  Wire them up with no driver, no power regulator...nothing but ballast resistors.  You can make them on a perf or in "dead bug" style for a nice small form factor.   Actually, you can make them brighter and more efficient by sacrificing the RGB and using amber, yellow, or "warm white" LEDs instead.  The main advantage to using multiple LEDs in a candle is that you can move the point source around a little and produce a nice flicker in angle as well as in intensity.

For practically anything else I can think of in theater -- and that includes a railway lantern or any period portable light sources other than candles -- we need more power.  Which introduces drivers to the equation.  The simplest driver circuit is a Darlington.  The handy ULN2803 can sink 8 channels worth at 500 ma each from a basic 20-pin DIP package.  The venerable TIP120 power Darlington can swing as much as 5 WATTS.

Wiring up multiple LEDs yourself can be time consuming.  SparkFun carries the "Satellite" from the same people who built the ShiftBright; it is a grid of 13 single-color Piranha meaning it puts out about 300 ma per color channel.  Which makes it about 15 x the lumens of the BlinkM.  Adding the driver and CPU and some discretes, however, brings you close to the $24 of the MaxM -- which is already assembled, and uses just three high-power RGBs to put out the same juice in a more compact package.

So to make it worthwhile you need to jump up to the Luxeons and similar LEDs pulling from half an amp to a whopping 10 amps each.  SparkFun does have breakouts, but they are pricey; it brings the surface-mount Luxeon Rebel up to about $7 a channel -- not including controller -- and $18 for an RGB array.  Plus you might just want to add diffusing lens, additional heat sink, even a constant-current source.

At which point you step back and say, "I'm not trying to do UL-listed architectural lighting here; I just want an effect for stage use."  And this makes some of the Hong Kong suppliers hanging out on eBay very attractive; as some of them offer 1-3 watt (300 to 750 ma) single-color surface-mount LEDs with rudimentary breakout boards/heatsinks for as low as a buck each.  Throw in some TIP120's to switch them, hack out some primitive PWM code on an ATtiny, and if you are lucky it won't burn out (or worse, burn up) before the show closes.

Which, if someone comes up to me today and says, "We want Willy Wonka's cane to light up when he taps it on the floor," is what I will do.

And I'm still going to stick my modified BlinkM in one of those cheap plastic candlesticks to show it off.

Wednesday, May 23, 2012

Blink Blink

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.

Sunday, May 20, 2012

Quick Hack

Makers Faire was this weekend and for once I didn't have to work a show.  I went, I wandered, I bought a couple parts, but mostly I listened to music, pedaled a generator at the pedal-powered stage, and drank the only beer they sold (although I was dying for some decent German beer).

Was house tech over the weekend for a show that brings their own sound and light operators.  Except for one early-morning showcase performance.  When they handed me a CD and told me they had a couple of simple lighting cues.  Problem; the sound board is still at FOH position (actually, rear of the house, but the important part is, it is NOT near the light board).

So pulled some toys out of the bag to be able to run the light board remotely.  There's one MacGuyver episode where he has to build a telescope from random lenses and he has maybe five minutes to do what took Galileo years.  But as Mac puts it -- he already knew it could be done.  Same with the lighting console -- I'd SEEN another group use one of the MIDI functions to control the ETC "Expression" board.  I just hadn't done it myself.

Opened the manual.  The Expression speaks MSC (MIDI Show Control) and will take a "Go" in that format.  Ran a MIDI connection through the audio snake that was already there via my hand-made pair of MIDI-to-XLR adapter cables.  I remembered QLab had some kind of drop-down menu of MIDI control sequences already written for you -- I opened up my fully-registered copy of QLab 1.0 and looked around.

The board didn't seem to be seeing the commands, but then after I'd tapped at the button a few times (trying different options) I noticed the lights had changed.  Turns out you had to deliberately press and hold the "send a message now" button within the QLab interface before it would spit out the full-length MSC.

Now, since it was already in my bag, I pulled out my Arduino-based MIDI message generator and the XBee-modified Staple's Easy Button.  And now I could trigger the "Go" button for the next lighting cue from basically anywhere in the theater.

It's a hack, and a bit of a chain; the inside of the Easy Button currently holds not just the XBee node but is wasting a perfectly good USB Explorer as a break-out board.  I haven't gotten around to putting in a new breakout board (and boost converter) as replacements.  When the Easy Button is pressed, the XBee node sends a radio message with the changed status of pin D0.  The receiving node toggles the output level of its pin D0 in response, and the Arduino it is connected to detects this as a switch closed (aka +v is present on a pin that is otherwise pulled to ground.  Or is it the other way around?)  The Arduino, which at least is in a nice box, debounces the "switch/sensor" input, creates a NoteOn event, and sends it out the serial port at 31250 BAUD.  A standard MIDI connector picks this up, creates a newly formatted message via USB, and this triggers a cue within QLab.  The QLab cue creates a new MIDI event -- an MSC "Go" command -- and shoots that OUT the same USB MIDI adapter.  That runs through two adapter cables and sixty feet of audio snake to reach the back of the lighting console.

But, the point of the demonstration is, this worked.  And more importantly than that, it worked off-the-shelf.  I had the components already, and I didn't even have to go inside via the USB connection and write new code to one or more of the components to do this particular task (which, if I had, could have removed the laptop and its MIDI adapter from the chain of connections).

And this is what I've been striving at with all of my theatrical gadgets; to have things that I can pull out of the gig bag and hook up in a few minutes to solve a problem.  Or to so something new that hasn't been done before, thus enhancing the fun and the creative options of a show.

And today I needed to do a touch-up focus on stage and I had no assistant to run the board.  At least this theater has an RFU (Remote Focus Unit), but it was still faster to write a couple of cues, each containing just the system I needed to touch up, then hook up my Wireless Easy Button again.  And then I could move from light to light without having to run back to the board each time.

Thursday, May 10, 2012

Feeping Creaturitis

Physiologists are continuing to refine just how they feel about stretching.  I know that back when I was doing some serious cross-country running, I did not believe in stretching while my muscles were cold.  Instead I would warm up by jogging in place, shallow bends, and so forth.  And I'd stretch out following a run, because it seemed to me I cramped up less if I eased my muscles down to rest again.  Except even when I converted to treadmill running, I found a better cool-down was using the Treadwall my gym had for far too short a time.

Anyhow...stretching may or may not damage your body, but stretch goals can damsure hurt a project.

One of the basic -- and hardest -- elements of good engineering is parameterization.  You have to identify the problem at a larger level than "how do I best make a machine do this" or, worse, "how can I make this machine I happen to have do this?"  Good enough parameterization can ofter parameterize the engineering itself right out of the game; "Oh, I guess there IS a commercial machine that already does it well enough," or "Well, it doesn't look like anyone would even use this application."

Which is all a round-about way of getting to my current work with the BlinkM.  This started with bottom-up practice; there is a device which puts on one very small footprint PCB a bright RGB LED and an AVR.  And it is configured out of the box to upload and run both commands and programs via an I2C serial port.  So I started with a solution in search of an application; could this product be of any use in addressing the various kinds of controllable lights I've identified a need for in live theater?

I wasted a fair amount of time in trying to implement a minimum-component serial-over-wireless link for these devices before I finally got around to doing the higher-level parameterization.  And one thing leapt out at me; there was no identified theatrical application for which full serial communication was necessary.

Of course the basic problem in this kind of geekery for theater is that you are not just replacing existing solutions with more elegant ones.  You are trying to identify solutions for what no-one has identified as a problem before.  Few people have come up and said "In our production of 'Gypsy,' it would be very useful if Electra's boob lights would light every time she bumped."  Fewer still have come up and said "In our production of 'Godot,' it would be great if the spectral plot of the wind sound altered in response to how close Estragon gets to the bush, tree, shrub...whatever the heck that thing is."

In the first example, someone might have imagined the effect, but assumed it was technically unfeasible and thus never brought it up in production or design meetings.  In the latter example, no-one had even envisioned the potential of dynamic alteration of the soundscape of the play via sensor networks and DSP.

Actually, honestly, by the time the resident geek is even consulted even easily solvable problems have already been "solved" either by changing the blocking, or altering the set, or using one of the venerable theater tools like fishline.

(Although sometimes there is the flip side -- a company like Berkeley Rep, that might ask for "blood to come pouring out of the giant translucent eye"; a problem that required electro-pneumatics and some kitchen chemistry to solve.)

The point being, the set of known applications is much, much smaller than the total set of solutions for what had never previously been identified as potentially soluable problems!

Anyhow.  The one BlinkM-derivative application I am absolutely sure of is the candle or lantern.  Because I've done so many of them in the past.

My best lantern solution was a half-dozen grain-of-wheat bulbs or amber LEDs, wrapped with diffusion from the lighting supply closet, and a 9V battery pack stuck in the original fuel reservoir.   The most elegant switch I made was wired to the wick adjustment wheel.  The most intriguing one I saw, however, was at Berkeley Rep, which used an R/C model car servo to turn a potentiometer, when thus allowed the lamp to be turned off remotely and on cue.

Which allows this application to be readily parameterized; "A battery-powered, fully portable simulated lantern light that will fit into a prop lantern, that is bright enough to be visible under stage lights, and that can be turned on and off remotely -- preferably from within lighting cues (aka it becomes a wireless DMX device)."

The first round of stretch goals would be to allow a range of stable intensities (not just fade up, fade out), and to flicker.

The next round of stretch goals says, since this is a potential "drop in any light" solution -- aka candles, small torches, even a wall sconce on a portable set piece -- we should add control of the color, and control of the range of the flicker effect.

I can't actually imagine any other application so specific and well-described.  I can think of, say, a crystal ball (such as is used by the Witch in "Wizard of Oz."  Or a Vial of Mysterious Liquid that glows from within (it might even be Atomic!)

But it seems plausible that whatever the application, the very process of being small, battery powered, not that bright, and installed in a prop, seems to imply that the wanted behavior for each application can be worked out easily before installation.  Which is to say -- it doesn't have to be re-programmed over the air.

And in many, many applications, it makes more sense to have a button in the hands of the actor than it does a wireless connection to the lighting console.

So throw out the attempts to create a serial link.  Instead, as the BlinkM board makes available one analog input of the AVR, simply set it to be controlled via a resistor ladder.  As many different pre-programmed behaviors as the resolution of the analog in port allows can be called up with nothing more complicated than a button.

For the lantern, the most sensible is two commands; fade to lantern-on flicker loop, and fade to all LEDs off. 

And if you do desire wireless control?  Why, then, you can use the pin-passing mode of a pair of XBee nodes to pass an analog value.  Assuming you can work out the balance between the 4.5V nominal of the BlinkM and the 3.3V supply desired for the XBee, you should be able to press a button (or run a line of code on a host AVR) and have the XBee network pass that button value wirelessly to the lantern.

So here I am coding.  I am still using microseconds() to keep the size of the PWM loop consistent, but even though it is a lot more work I may want to switch to an interrupt routine based on one of the ATtiny45's two hardware timers.  The basic idea is straight-forward; for each loop through the PWM loop, the LEDs are all switched off, then at set values from the first step to the last step of the loop they are switched on, thus creating a duty cycle varying from (basically) 0% to 100%.

An added wrinkle is that human perception is roughly log, not linear, thus it makes sense to either include a gamma correction calculation or look-up table prior to determining the duty cycle.  This has the advantage of meaning you need less resolution (fewer steps) in the loop in order to maintain resolution (visible changes in brightness) at the lowest end of the scale.

The simplest possible shell code to this just feeds three numbers into the PWM loop; one each for R, G, and B.

The next iteration is a fade-to.  For this, we have the known RGB state, and a target RGB state, and a rate (the number of program steps between one and the other).  At this point the central statement looks more like  float current_value = (old_value - new_value/rate); if (timer > gamma_table[int (float current_value)) { LED = high; }

Which is to say; we need to use a floating-point variable in order to correctly track fractions of increase, convert it to Int to find the next whole-number step, and feed that into the look-up table in order to find the moment the LED needs to switch on.

But what of, say, a pulse like the sleep light on a computer?  This alternates between two steps; fadeTo on, and fadeTo out.  Or, rather, fade to, in alternating order, two defined RGB values.  So the program flags when all fade steps are completed, and then grabs the new target value and re-commenses.

Except.  It is easy to imagine a program in which more than two states follow.  A traffic-light pattern, say.  So rather than make an arbitrary list, instead we will establish an array of RGB values, and test on the completion of each fade loop if there is an array element in the ++ location.  And, of course, since not all steps would necessarily be the same length, the fourth element in the array is unique fade rates for each target.

And now the goals are getting reeeeaaallly stretchy.  Because it is easy enough to imagine having to fade from one multi-element loop to another.  In the simplest case, imagine a flickering candle slowly fading.  You don't want to freeze the flicker and fade from whatever the current color is.  Instead, you want to continue running the flicker program whilst changing ALL of the values in an incremental way according to the external fade loop.

And since you are being silly already, why not ask how you would go from a steady pulsing white light to a steady pulsing RED light -- without a stutter?  Well, by putting in the command that says "fade to new pulse" a flag that requires the new loop to synchronize with the old loop.

And at some point you realize the iterations become endless -- that there is always some scenario you can imagine by which a multi-stage program could be cross-faded with another multi-stage program.

And that's the point at which stretching really starts to hurt.  Better to get back to the known basics -- things like a flickering candle that can be dimmed -- and actually finish the code for that before adding on more and more bells and whistles.