Projects Research & Design Hub

Build an RGB LED Controller

Using Parallel FET Dimming

There are a lot of fun and interesting things you can do with LEDs and the different ways to control them. In this article, Dirceu describes an alternative approach to control RGB LEDs, using the parallel FET dimming technique. He steps through his efforts to design and build an alternative lighting system based on power RGB LEDs. To control them he goes very old school and uses an 8-bit MCU and the BASIC programming language.

Nowadays, applications involving advanced processors like Arm and Espressif ESP-32 are commonplace. But I thought it would be cool to test some fun lighting sequences that are controlled by an 8-bit microcontroller (MCU) programmed using an ancient language: BASIC. Although using pulse-width modulation (PWM) to dim LEDs with MCUs is a long-established idea and there’s a plethora of such products on the market, my approach differs from others regarding the drive method used. The benefit will be a relatively shorter BOM, but is also of particular interest to embedded system designers involved with LEDs because it will be possible to experiment with alternative configurations for the control stage.

LEDs are inherently nonlinear devices. Their brightness depends primarily on the current flowing through them, even though the voltage on terminals don’t vary that much. To achieve a constant LED current, there are two approaches: linear or switched current regulation. A linear regulator is preferred in situations where the noise due to commutation would be unacceptable—or for example, in high-precision measurement equipment. When efficiency is the main concern, a switched regulator or driver usually is chosen.

A commercially available driver usually operates above 1 MHz, providing hysteretic regulation for the LED current. To implement the required dimming, a common solution is to apply a PWM signal to an enable pin of the regulator. Because the entire component is switched continuously, the delay due to the soft start function must be taken into account. The disadvantage of this mode is, therefore, the limitation at low frequencies, usually 100 Hz. Other drivers, such as the ZXLD1350 from Diodes Inc. (used here), have a similar input named ADJ, capable of accepting a PWM signal up to 1 kHz.

As outlined in Figure 1, my application takes a different approach. Rather than applying PWM pulses to a dedicated regulator pin, these signals are used to “short-circuit” the LED. So, when a switch is closed, the corresponding LED is off. This technique—known as parallel FET dimming—does not pose a problem itself, since the driver is based on a current source. Regardless of the state of each LED, the same current always flows through the entire circuit. For an independent control of three RGB LEDs, traditionally three drivers are employed, each with its own inductor, Schottky diode and sensor resistor, as shown in Figure 2a.

FIGURE 1 – Shown here is the basic idea for the design.

My alternative configuration to reduce the number of components is to connect the three LEDs in series, each with its own switch driven by PWM (Figure 2b). Note that, in this case, the ADJ pin from the single ZXLD1350 stays floating, and the three PWM signals are moved to the gate of MOSFETs. Therefore, it is possible to control three LEDs using only one set, consisting of driver, sense resistor, flyback diode and inductor.

FIGURE 2 – (a) shows a traditional configuration for driving 3 LEDs. (b) shows my alternative configuration, which reduces the number of components by connecting the three LEDs in series.

The circuit shown in Figure 3 is based on an ATmega8 MCU from Microchip Technology (formerly Atmel) running at 16 MHz, 5 V. The power is provided by a 12 VDC wall adapter. The PWM outputs are OC1A and OC1B pins from Timer 1 and an OC2 pin from Timer 2. Six low RDSON MOSFETs (in fact three double MOSFETs) act as level shifters and parallel switches for the LEDs. The operating mode or lighting profile can be changed by pressing push button S2 or wirelessly through an AX-1838HS infrared receiver. For a lower consumption, a seven-segment display shows the program number only when changing it (by blinking three times in approximately 1 second).

FIGURE 3 – Schematic showing the circuitry connected to an ATmega8 MCU.

Note that a PWM signal is not applied to the ZXLD1350 ADJ pin, as several applications using this driver suggest. Instead, it only serves to keep all three LEDs off when desired. This avoids wasting energy, because otherwise the current would flow even with the three LEDs short-circuited. During normal operation, the ADJ pin is at high level. The ZXLD1350, along with the external inductor L1 and current sense resistor Rs, form a self-oscillating, continuous-mode buck converter. Due to hysteretic operation, the output current of the driver assumes a triangular waveform with a DC value of IAVG_ON and a ripple named here as ∆ION, so that:


with a Rs = 0.33 Ω, we get:


Advertise Here


For this application, we chose an RGB LED rated to 350mA/3W. In practice, each LED is controlled (short-circuited) independently according to a predetermined lighting profile, and this operation influences the shape of the current within the profile period, T. The current is always flowing through the circuit, even when all LEDs are short-circuited. This is not a concern, because we are dealing with a current source. (What changes is only the frequency of the triangular wave.) At any given time, the current is passing through the LED or through the associated MOSFET’s RDSON resistance. Next, we observe the behavior of RMS current (IRMS). Figure 4 shows that period divided into N intervals, each one associated with a different duty-cycle D when an LED is on. At the bottom of page 10, the math in box entitled “Derivation of RMS Current” shows that the RMS current, Equation (2), depends on the average value of the duty cycles belonging to a given profile. For our case:

FIGURE 4 – In this current waveform, you see the period divided into N intervals, each one associated with a different duty-cycle “D” when an LED is on.

The companion code associated with this article is available from Circuit Cellar’s article code download webpage. As you will see from that source code, the PWM generation is accomplished with two outputs from TIMER1 and one output from TIMER2. With a pre-scale value of 256, these two timers are clocked at 62.5 kHz. Although TIMER1 is a 16-bit counter, only half of this was used. That’s because TIMER2 is 8 bits in length, and the same resolution for all outputs is desired. Using parallel FET dimming, the switching frequency, could reach some tens of kilohertz, but the three 8-bit PWM outputs operate here at:

Note that in mode Phase-Correct/Clear-Up, the PWM frequency is halved due to up and-down counting.

The low frequency is a suitable trade-off between avoiding visible flicker and getting a nonlinear response due to PWM signal integration from the ZXLD1350 internal low-pass filter. Due to a pre-scale value of 1,024, the 8-bit TIMER0 is clocked at 15.625 kHz, and its overflow interrupt—occurring every 16.384 ms—allows the creation of three general-purpose time counters by the software. Note that due to MOSFET operation, as shown in Figure 2b, high compare values lead to low LED brightness.


Advertise Here

The firmware, though written in the popular BASIC language, has its executable code generated by a high-performance compiler, the BASCOM-AVR from MCS Electronics. It’s able to access all internal peripherals present on AVR MCUs, including handling of interrupts and execution of assembly instructions using proper directives. The application code comprises the decoding for infrared NEC protocol. To accept a wider range of remote controls—including the older ones—the code provides minimum and maximum tolerances (±10%) for the relevant timings of that protocol. Because an internal pull-up resistor on the MCU is enabled for a PD4 pin, there’s no need to use this type of component on the push-button circuit. Four lighting profiles are implemented, numbered as follows:

0. LEDs off, with a low level on the ZXLD1350 ADJ pin
1. Sinusoidal three-phase with 120-degree offset, using a lookup table for sine function, as shown in Figure 5a
2. Two ramps (six phases, where one LED is off, one rising, and the other decreasing), as shown in Figure 5b
3. “Flashlight” or “white LED” mode

FIGURE 5 – (a) Lighting Profile 1. (b) Lighting Profile 2.

In profiles 1 and 2, the keys “VOL+” and “VOL-” from the remote controller increase/decrease the time step. In profile 3, these keys change the power of white light, while keeping equal duty-cycle for all LEDs. The NEC IR transmission protocol uses pulse distance encoding of the message bits, at a carrier frequency of 38 kHz. On the MCU input (PB0), the received IR message, provided on AX-1838HS, consists of a 9 ms leading pulse burst and a 4.5 ms space. Each bit starts with a low time and is followed by a high time. The low time is always 560 µs, and the high time can be 560 µs (bit 0) or 1.68 ms (bit 1) (Figure 6). Taking this arrangement into account, each message is 4 bytes in length—address, inverted address (bitwise), command and inverted command. With the remote controller used, the relationship between keys and the hexadecimal values for address and command bytes are shown in Table 1.


Advertise Here

FIGURE 6 – Interpretation for bit 0 and bit 1

TABLE 1 – This table shows the relationship between keys and the hexadecimal values for address and command bytes.

The Timer 0 is also used to calculate the number of ticks between the edges of the IR signal. Listing 1 is a code excerpt showing one of the functions used for decoding the NEC protocol, where PinIR is an alias for PB0 pin, and the nextEdge variable is updated in an outer function. The codes in Table 1 might appear different from those used in popular IR decoding libraries. The reason is that I decided to maintain compatibility with the NEC protocol, which sends each byte from the LSB to MSB.

Function GetTicksBetweenEdges(ByVal maxTicks As Byte) As Byte
Local ticksBegin As Byte , ticksDiff As Byte

ticksBegin = TIMER0
ticksDiff = 0

While PinIR <> nextEdge
ticksDiff = TIMER0 - ticksBegin
If ticksDiff >= maxTicks Then
GetTicksBetweenEdges = 0 ‘ Error
Exit Function
End If

GetTicksBetweenEdges = ticksDiff
End Function

LISTING 1 – This code excerpt shows one of the functions used for decoding the NEC protocol, where PinIR is an alias for PB0 pin, and the nextEdge variable is updated in an outer function.

The components fit into a small, home-made PCB, except the power LED, which was attached to the heatsink using a two-part, thermally conductive, adhesive epoxy. The board was placed in a plastic box in an upright position, so that the interface elements were in front of the user (Figure 7). A common switched-mode 12 V × 1 A wall adapter provided the power.

FIGURE 7 – The components fit onto a small, home-made PCB, and the board was placed in a plastic box.

It is possible to place a plastic globe or other structure from an old Luminaire over the box, to spread the colored light and create a nice look. Figure 8 shows a waveform for a typical current in one LED, and a sample of soft-start action. The datasheet for the ZXLD1350 describes the expressions for TON and TOFF times, which depend on how many LEDs are on in any given instant. The waveform in Figure 9 shows a duty-cycle change for profile 1 (TON refers to descending signal).

FIGURE 8 – Shown here are the waveforms for (a) a typical current in one LED (the R LED), and (b) a sample of soft-start action.

Since the beginning, the main concern has been the power consumption when comparing the parallel FET dimming approach with the traditional use of three LED controllers. The minimum resistance R, common for all profiles, is assumed as 810.9 mΩ (0.33 Ω from Rs plus 480.9 mΩ from the inductor’s DCR). The number of MOSFETs in plain switching on “sinusoidal” and “two-ramps” profiles are three and two, respectively. So, an equivalent number of additional series RDSON resistances (58 mΩ each) must be taken in account when calculating the power losses. We can see from Table 2 that the calculated losses are similar.

TABLE 2 – Calculation of power consumption

In addition to not suffering from the effect of the soft-start action, the use of parallel FET dimming reduces the bill of materials, regarding several components, to about one-third. But, in practice, this is offset by the six MOSFETs (three parts due to IRF7317 double MOSFET in the SO-8 package), at least in this implementation. You can consider alternative ways to short-circuit the LEDs, to use regulators other than the ZXLD1350 and also to provide other modifications. The number of RGB LEDs can be increased somewhat, still using only three PWM outputs. For this, replace each current LED with more LEDs in series, all of the same color. Note that this procedure could also require changes in the power supply. 

FIGURE 9 – This is the waveform of duty-cycle change for profile 1.

For detailed article references and additional resources go to:

Diodes |
Microchip Technology |
MCS Electronics |


Keep up-to-date with our FREE Weekly Newsletter!

Don't miss out on upcoming issues of Circuit Cellar.

Note: We’ve made the Dec 2022 issue of Circuit Cellar available as a free sample issue. In it, you’ll find a rich variety of the kinds of articles and information that exemplify a typical issue of the current magazine.

Would you like to write for Circuit Cellar? We are always accepting articles/posts from the technical community. Get in touch with us and let's discuss your ideas.

Sponsor this Article
+ posts

Dirceu R. Rodrigues, Jr. has been a computer engineer since 1994, holding a MsC Electrical Engineering (Control Systems). He is interested in hardware and software for industrial, scientific instrumentation and embedded product design.

Supporting Companies

Upcoming Events

Copyright © KCK Media Corp.
All Rights Reserved

Copyright © 2024 KCK Media Corp.

Build an RGB LED Controller

by Dirceu R. Rodrigues, Jr. time to read: 9 min