Skip to content

RGB LEDs

An RGB LED is really three LEDs in one: a red, a green and a blue one, squeezed into the same plastic dome. Turn them on in different amounts and they blend together into any colour you like, which is exactly how the pixels on your phone screen work.

You'll need:

  • 1 × RGB LED, 5 mm, common cathode
  • 3 × 220 Ω resistors
  • 4 × jumper wires

Hardware

An RGB LED has four legs. The longest one is shared by all three colours. On a common cathode LED it's the negative leg, and it goes to GND. The other three legs are the red, green and blue anodes. Each one needs its own resistor, just like a normal LED.

Hold the LED with the longest leg second from the left, and the legs are usually in this order:

Leg Colour Connect to
1 (short) Red 220 Ω resistor → GPIO 16
2 (longest) Common cathode (–) GND
3 Green 220 Ω resistor → GPIO 17
4 Blue 220 Ω resistor → GPIO 18

Common anode LEDs

Some RGB LEDs are common anode: the long leg is positive. Connect it to 3V3 instead of GND. Everything in this lesson still works, but backwards: a colour lights up when its pin is off. In the PWM examples, use 65535 - duty instead of duty to flip it back.

If a colour looks wrong (say, blue lights up when you asked for green), your LED's legs are in a different order. Swap the wires or change the pin numbers in the code.

Software

Mixing with on and off

Start simple: switch each colour fully on or off. Two colours together make a mixed one:

rgb_colors.py
# Cycle an RGB LED through red, green, blue and some mixed colours
import time
from machine import Pin

red = Pin(16, Pin.OUT)
green = Pin(17, Pin.OUT)
blue = Pin(18, Pin.OUT)


def show(r, g, b):
    # each argument is 1 (on) or 0 (off)
    red.value(r)
    green.value(g)
    blue.value(b)


COLOURS = [
    ("red", 1, 0, 0),
    ("green", 0, 1, 0),
    ("blue", 0, 0, 1),
    ("yellow", 1, 1, 0),
    ("cyan", 0, 1, 1),
    ("magenta", 1, 0, 1),
    ("white", 1, 1, 1),
]

while True:
    for name, r, g, b in COLOURS:
        print(name)
        show(r, g, b)
        time.sleep(1)
  • show(r, g, b) is a small helper function that sets all three pins at once, so the loop stays tidy.
  • COLOURS is a list of tuples: each item bundles a name with three on/off values. for name, r, g, b in COLOURS: unpacks them one at a time.
  • Red + green = yellow, green + blue = cyan, red + blue = magenta, and all three = (roughly) white.

Mixing any colour with PWM

On and off gives you just seven colours. To get the millions in between, dim each colour using PWM, the same trick as the dimmer switch in the Potentiometers challenge:

rgb_mix.py
# Mix any colour on an RGB LED using PWM
import time
from machine import PWM, Pin

red = PWM(Pin(16), freq=1000, duty_u16=0)
green = PWM(Pin(17), freq=1000, duty_u16=0)
blue = PWM(Pin(18), freq=1000, duty_u16=0)


def set_colour(r, g, b):
    # r, g and b go from 0 (off) to 255 (full brightness),
    # the same way colours are written on web pages
    red.duty_u16(r * 257)      # 255 * 257 = 65535, the maximum duty
    green.duty_u16(g * 257)
    blue.duty_u16(b * 257)


set_colour(255, 80, 0)     # orange
time.sleep(2)
set_colour(120, 0, 255)    # purple
time.sleep(2)
set_colour(0, 0, 0)        # off
  • PWM(Pin(16), freq=1000, duty_u16=0) switches the pin on and off 1000 times a second, much too fast for your eye to see flicker.
  • set_colour() takes each colour as 0–255, the same scale colour pickers and web pages use. Multiplying by 257 stretches that to PWM's 0–65535 range.

Try it in the Shell: after running the file, type set_colour(0, 255, 100) and see what you get. Search for "colour picker" online, pick a colour, and type its RGB numbers in.

Colours won't match your screen exactly

The green and blue parts of the LED are usually brighter than the red, and the colours don't blend perfectly in the dome. A paper or ping-pong-ball diffuser over the LED helps the colours mix.

Fading around the colour wheel

rgb_fade.py
# Fade smoothly around the colour wheel: red -> green -> blue -> red
import time
from machine import PWM, Pin

red = PWM(Pin(16), freq=1000, duty_u16=0)
green = PWM(Pin(17), freq=1000, duty_u16=0)
blue = PWM(Pin(18), freq=1000, duty_u16=0)


def set_colour(r, g, b):
    red.duty_u16(r * 257)
    green.duty_u16(g * 257)
    blue.duty_u16(b * 257)


while True:
    for step in range(256):         # red fades out, green fades in
        set_colour(255 - step, step, 0)
        time.sleep_ms(8)
    for step in range(256):         # green fades out, blue fades in
        set_colour(0, 255 - step, step)
        time.sleep_ms(8)
    for step in range(256):         # blue fades out, red fades in
        set_colour(step, 0, 255 - step)
        time.sleep_ms(8)

Each for loop cross-fades from one colour to the next: as step counts up from 0 to 255, one colour gets dimmer while the next gets brighter.

Challenge

Use the potentiometer on GPIO 34 to choose the colour: turning the knob should slide smoothly from red, through green, to blue.

Show a hint

Scale the potentiometer's 0–65535 reading down to 0–510. For the first half (0–255), fade red → green like the first loop of rgb_fade.py. For the second half (256–510), subtract 255 and fade green → blue.

Next up: Light Sensors: give your projects eyes that can tell day from night.