Now that Lighting the Room
is close to a finish, i have been learning to develop my own apps for iPhone and iPad.
These are some first screenshots. It’s nice to see how the site gets visited in a browser, but how awesome is it to show nice graphs on your phone!
Visits in landscape mode
There will be a separate project page for the support of this app when it is ready, and of course this blog will keep you up to date.
In this tutorial, i explain the use of a line drawing algoritm to distribute PWM pulses to reduce flicker with dimmed led’s.
PWM is cool. It’s an acronym for Pulse Width Modulation
. You can use it to make awesome synthesizer sounds, drive servo motors, and control the brightness of led’s!
The trick with lights is a kind of magic. When you switch a led on, its almost instantly on. No heating up or such as you would with a regular incandescent bulb (note 3). it goes to maximum brightness in a microsecond. the same thing happens when you turn it off. It has no afterglow. If you turn it on and off very quickly, and i mean many many times a second, the human mind cannot see it going on and off again any more. Above 100 flickers per second, or 100 Hz, the human brain can no longer distinguish the on/off pulses and sees it as a constant brightness (note 1).
I used this effect to dim the lights of my lego truck project, and save a lot of battery power on the side!
This persistence of Vision can be used to dim the leds at almost arbitrary brightness. Let’s use some widely known definitions: a complete cycle on and off is called a pulse. The length of time it is on, compared to the time it is off, is called the pulse width. If you lower the ratio between on and off, the led appears to be dimmer.
Now there’s a little problem with that pulse width. If the total length of the pulse is too long, the eyes start to notice the on/off effect. In practice, this just means that the off-period basically is too long. Especially when doing PWM in software, this can be a nuisance because you cannot switch the led’s on and off fast enough to hide the flicker.
The solution used on most of the software PWM libraries, like softPWM
or the excellent M5451 library
, is to evenly distribute the times over the entire pulse time, as shown in the crude drawing on the right.
In this example, we have a total pulse time of 100 units, say milliseconds, but the LED is only on for 20% of the time. Instead of turning it on for 20msecs and turning it of for 80, we turn it on for 5 msecs with 20 msecs in between. Over the total period of 100 milliseconds, the led was on for an equal amount of time, but without the noticeable 80 milliseconds. Going even further we could turn it on for 1 msec and off for 4 msecs (20 times). The principle of dividing the pulse to achieve the same average density is called Pulse Density Manipulation or PDM (note 2)
Distribution of on/off times
This was a easy example. We calculated this one by hand. But if we wanted to change the brightness to let’s say 57, that would become more difficult. “Oh yeah, it’s easy” you say, “just divide the 57/100, we only need to ….” ah you see? it gets difficult.
In the early days of computer programming, there were no OS core graphics libraries to use, or even download the libraries from the internet. Everything had to be programmed by hand. There was the simple problem of drawing a line on a pixelated computer screen, on its own a difficult concept. You could use floating point arithmetic to calculated the coordinates but that was far from efficient.
An excellent mathematician named Bresenham came up with an algoritm to draw lines
without the need for floating point numbers. All could be done with standard integers. Basically the algorithm magnifies the floating point fractions to a number big enough to fit in an integer.
|Look at the right, A) is a most simple, 45 degree line. and B) a flatter line.
With a) for every horizontal step, the vertical step is increased 1. Line B) is much less steeps, and needs more horizontal steps before increasing the vertical value.
Using steps to draw a line in computer graphics
Back to our pulse distribution problem. We use the vertical steps as ‘ON’ pulses, while the time is indicated by the horizontal steps.
As time progresses to the right, we check if a vertical step is needed. If the vertical rises one step, we turn the light on. If it stays on the same vertical, turn it off.
The process repeats at the end of the graph, we start with 0 again, looping until infinity.
Using line drawing logic to distribute the pulses
Until now, i’ve used the number 100 as a maximum time, and brightness. Computers like to work with multiples of 2, so in my software i used the maximum value of a single byte, 255. 0 is fully off and 255 is maximum brightness (always on).
Although Bresenham’s algorithm can cope with lines going to the left, right, up, down in all directions, for our problem we can ignore all those other quadrants, because our vertical increase is always less than 100%, compared to the time passed. We can use this effect to simplicate our algorithm. The algorithm below was taken from the Wikipedia page for Bresenham’s algorithm. I won’t repeat the intricate working here, the wiki page does a far better job than me.
By using constants for x0, x1 and y0 the algorithm gets substantially simpler.
Optimizing the algoritm
After optimisation, the function turns down to this:
I recognise the work of others as mentioned before, and I know that this algorithm is used in other places. But I didn’t understand the inner workings at first, therefore i wanted to re-invent it myself as a study. Needless to say, the end result is surprisingly similar to G.Andrew Stones M5451 driver
. As such, he deserves credit for using the concept.
Rob van der Veer
- The frequency of Vision Persistence was not 30 Hz, but 100 Hz (thanks to Headroom for pointing that out)
- The principle explained here is Pulse Density Manipulation and is not really PWM (stimmer)
- As a reader pointed out, there’s no problem using PWM to dim a regular bulb – something i didn’t know.
My first Arduino project involved adding lights to a Lego Technics truck. I tried not to modify existing Lego bricks in the process. I’ve been asked a couple if times how i added the led’s in my model
, so let me explain what i did to make it happen.
First, you need the right leds. I bought mine in bulk from a Chinese vendor on eBay. I paid about $6 dollars for 50 wires leds, free delivery. I am sure you can get cheaper via alibaba.com, but i don’t trust those sites (yet) because they want my creditcard info now that they stopped using PayPal.
The led slides easily into the peg, and the peg can connect to many Technic beans and bricks. Make sure they are 3mm, so they can fit inside a 4211483 half peg.
To get an even better look, grind off the rim of the led as explained in this diagram. That way, the led can be pushed further into the peg so only the little dome of the led sticks out on the other side. I used an electric scissor sharpener but any dremel tool or file will do the trick. Don’t be scared to damage the sides of the leds, because that bit will be covered by the peg anyway.
After you do this, solder the wires as close to the led as possible. Make sure you have a good heatsink attacked to the wire or you will burn the led. I used a big clamping wrench.
On my truck, i had to drill a few 3mm holes in a couple of plates (1×4, 2×3) to mount the leds without pegs. I just drilled inside the studs so the parts didn’t lose their function.
If all goes well, it’s going to look like this. I always used heat shrink to cover up any bare wires to avoid shorts from wiggling wires or wet fingers. It’s only a couple of volts, but it still stings.
Thats basically all you need! Happy modding.
Well not really, i need to clean up wires etc. But all the lights are connected. With all lights on, a fully charged PF battery pack with rechargeable AA’s is empty in 2 hrs. But it surely lights the room up!
I’ll be monitoring battery usage in the coming weeks, perhaps i can squeeze out a little more. Also, i’ve been looking to have a proper PCB produced, perhaps with some lego-sized holes for mounting. That would be cool for a 2nd version.
This weekend i plan to update documentation and upload a video of the features. What needs to be done? Cleanup, as mentioned, and the software isn’t finished, it cannot be operated remotely yet. Perhaps add feature to dim the lights so the battery holds out longer.
I’ll leave you with a couple of pictures
The little board at its resting place
Well. There it is. All components fitted and soldered. The first prototype board of ‘light the room’ completed.
34 ports of switched LED connectors, a power rail, Bluetooth connector and a noise-making device AKA piezo speaker.
I say not bad for a first! I must admit we’re not there yet, still we need a lot of work on the emergency lights and the remote control, but i’m glad it all fits.
Bottom work (not so top)
Technically it fits
A view to a grill
There it is. Front lights lit. For more details, check out the project page
I posted my project on a couple of Arduino and Lego boards and look what it did to my site statistics!
Everybody, thank you so much!
Awesome progress made today. I finished soldering the major wires up the M5450 driver to the Arduino.
Top side, notice the 4-pin bluetooth connector and the 2-pin power header
Bottom side, all major connections made.
At first, it didn’t work. Instead of a blinking led I got very irratic behaviour. Of course my first reaction was to pull the power and feel for heat on the chips. No problem there. So i started to think about a solder short. Using the iPad camera as a microscope i saw no errors. Checked the diagram again and again, still all ok.
Then it hit me. I modified the schematic in Eagle to allow a better flow of connections on the board. I swapped the clock and data lines with the buzzer output. But I forgot to adjust the pin numbers in the sketch!
After that simple fix the lights finally lit up as they should!
Ready, Set, Go! After spending quite some time fiddling in EaglePCB shifting around the components, I cut the protoboard to size and started to solder the first components.
A complete first for me. I have soldered a few wires before, but hitting those tiny precious components was a big step up for me. But thanks to the good tutorials on youtube (link needed), great advice from my dad (the engineer), and proper tooling (my brand new solder station, good lighting, perfectly thin solder) i got good results. I am pretty proud with these first results!
Look closely, only a couple of pins fixed here