This project is basically a tutorial on managing the brightness of an LED and the color of an RGB LED using PWM or pulse width modulation.
In Section I, we will cover the basics of PWM and how it's used with Arduinos. In Section ll, we will discuss smooth dimming of a single color LED, which requires something other than linearly changing PWM, and in Section lll, we will look at creating colors, and managing a rainbow of colors produced by RGB LEDs.
For fun with this project, I am using "fake neon" - the edge lighting LED strips from Adafruit, specifically the 1 meter RGB version without Neopixel capability. But really, to try everything we talk about here, all you really need is any common anode RGB LED.
Section l - PWM BasicsPulse width modulation is the process of rapidly switching a digital output pin between high and low outputs. The percentage of time the output is in its high state is referred to as the duty cycle.
If we are supplying power to an LED using PWM, the duty cycle reflects on average the percentage of maximum power we are supplying to it. If the frequency we are switching power on and off is high enough, the output of the LED will appear on average to be its maximum output times the duty cycle. For the human eye to see an LED as continuously on rather than flickering, the PWM frequency needs to be at least 100 Hz.
All Arduinos have several digital output pins capable of PWM. They operate at either 490 or 980 Hz. For the Nano that we are using in this project, the digital pins with PWM capability are 3, 5, 6, 9, 10 and 11. In all our examples we are using pin 3 (blue LED), pin 5 (red LED), and pin 6 (green LED).
PWM output is specified for the Arduino using the DigitalWrite(DutyCycle) instruction. The duty cycle is specified using an 8 bit value between 0 to 255, where 0 is 0% duty cycle and 255 is 100% duty cycle.
Section ll - Dimming an LEDThe energy output of the LED and the lumens of light it gives off are roughly directly proportional to the PWM duty cycle.
However, our eyes perception of brightness is not at all linear with respect to light output. So to produce a linear dimming effect, we need our PWM output curve to be something like the inverse of the curve above.
There are several websites devoted to what that correction curve should look like - one of them is here. I have included a couple of different approaches in my code. One math approach that works pretty well is to make the PWM duty cycle equal to the cube of the dimming step, as demonstrated in program NeonCubeDimmer. Another approach accomplishes a similar result using a table. It is demonstrated in program NeonTableDimmer. The video below shows the relatively linear dimming effect it produces.
Section lll - Color ManagementWith any RGB LED, we can produce any color by mixing red, green, and blue of varying intensities. I am using Adafruit's Neon-like edge lighted LED strip for the examples and code included here, but you could use any common anode RGB LED. The only requirement for my code to produce the desired colors is that the LED that you use produces a pretty good version of white when all three colors are turned on at the same intensity.
Now while we can in theory mix the three colors in any combination, the most useful colors scheme is to generate the colors of the rainbow, which involves mixing only two colors. With red and green, we can produce red, orange, yellow and green. With green and blue, we can produce green, aqua-green, aqua-blue, and blue. With blue and red, we can produce blue, purple, violet, and red. We mix two colors together using PWM with a simple scheme. Mixing red and green, we set red's duty cycle to X, and green's duty cycle to 255-X. By varying X from 255 down to 0, we get all the rainbow hues from red to green, including orange and yellow.
So let's take the colors named above: red, orange, yellow, green, etc. and call them our named standard colors. We can build a table with of duty cycle values for each of these standard colors. This is demonstrated in program NeonStdColors and shown below. The values I picked for these standard colors were determined empirically, so they are not necessarily perfect matches to a standard colors chart, but they are close.
Obviously, we can also produce a continuous spectrum of rainbow colors. That is demonstrated in program NeonRainbow and shown below.
For colors of the rainbow, we only use two colors. But another scheme I like, which is similar to the rainbow but different, is to mix all three colors (red, green, and blue) having each rise in intensity and then fall in a three-phase pattern. Again this is accomplished using a table. With this scheme, all three colors are present most of the time, but only one is dominant. This is demonstrated in program NeonTriPhase and shown below.
Notes on Hardware and the VideosThe picture above shows our cat in white outline against a blue background. It is actually the blue LED strip at full brightness (but at only 9 volts) sitting in a black cat-shaped frame. The simulated neon strip is so bright that it completely overwhelms my iPhone's CCD image sensor, making the strip look white, while bathing the entire background in the blue light from the strip! I quickly realized as I started taking pictures and videos for this project that I needed to do something different, if I wanted to accurately show what these strips really look like.
The neon-like edge lighted LED strips are common anode and intended to be powered by 12 volts. Adafruit correctly points out that they are plenty bright enough with just 9 volts. The strip has built in current limiting, using a combination of LEDs in both series and parallel configuration.
To control it with PWM, we need our PWM signal to drive the base of an NPN transistor, as the entire strip draws much more current then our Arduino digital pins can sink. I used 2N2222 transistors, but just about any NPN transistor should work.
To reduce the brightness of these strips to something I could photograph, I had to use 500K ohm potentiometers on the base inputs of the transistors, turning the transistors into constant current sources in addition to being switches for the PWM. Using this constant current approach, you can see what the strip actually looks like below.
So all the videos you see in this project were photographed at significantly reduced brightness, in order to accurately see the colors. However, unless you are going to try photographing these strips, you can replace the 500K ohm pots with any 100-1K ohm resistors, which will provide enough base drive to put our transistors in saturation mode (i.e. fully on when PWM is high).
Comments