The Dimmer Plug contains an I2C chip which can control the brightness of up to 16 individual LEDs using hardware PWM. The advantage over the ATmega’s PWM is that there is no limitation to use only the DIO2, DIO3, or IRQ pin (the only ones which support hardware PWM), and of course that 16 individual LEDs can be controlled. In fact, since there are 3 solder jumpers, up to 128 LEDs can be controlled from a single I2C port (by daisy-chaining eight Dimmer Plugs).
Note that the output of the Dimmer Plug is only suited for driving single low-power LEDs with a series resistor. The default setup assumes that these LEDs are tied to 3.3V or 5V. For higher voltages and higher power, additional driver circuitry must be added (transistors, MOSFETs, or the ULN2803 8-wide driver, for example).
Here’s a demo setup:
(it’s not visible here, but the test LED has a 470 Ω resistor in series)
Although software PWM can handle more I/O pins, that does place a fairly high load on the ATmega, and the dimming takes place at a much lower frequency, which can be visible to the naked eye (and quite annoying).
The disadvantage of the Dimmer Plug is that it’s based on a fairly complex chip, the PCA9635. I’ve extended the DimmerPlug class in the Ports library a bit further to make it somewhat easier to use.
There’s also an updated dimmer_demo.pde sketch:
It exercises several of the PCA9635’s features:
- all 16 output are set to maximum brightness
- the “group blink” mode is enabled, using a specified blink frequency and blink duty cycle
- the sketch waits 10 seconds, while blinking
- the chip is reset to its default “group dimming” mode
- then gradually make all channels dim at the same time
- and lastly enter a loop, which illustrates how to do per-channel dimming
The setMulti() call takes a start register number, then a variable of arguments 0..255, and then a “-1” value to mark the end. It is shorthand for calling setReg() with successive register values, but more efficient.
The code in loop() does some tricky bit fiddling. Figuring out what it does is left as exercise for the reader, but you can simply ignore it if you don’t care about such trickery. The main thing to note is that indiviudal LEDs can be controlled by setting their corresponding register: dimmer.PWM0, dimmer.PWM1, …, up to dimmer.PWM15.
As you can see, the PCA9635 can control individual outputs, but also several outputs combined via the “group” modes. There are other options, i.e. only controlling a subset of the outputs in group mode, inverting the output signal, using open-collector mode instead of the default totem-pole configuration, and more. You will need to go through the datasheet (PDF) to take full advantage of all this. All registers in the PCA9635 can bet read and written using the getReg() and setReg() calls, respectively.
But for simple uses, the above should be sufficient!
Nice! I love the dimmer plug but had a few problems to make it work the way I wanted. This will make future tests much easier, thanks.
Your internal links are broken, i think you want to link to https://jeelabs.net/projects/hardware/wiki/Dimmer_Plug instead of https://jeelabs.org/2011/06/11/controlling-the-dimmer-plug/dp1 in the first paragraph
Good catch – fixed.