Learning Goals 5 min
- Wire a common-cathode RGB LED to three PWM pins (~9 R, ~10 G, ~11 B) using one 220 Ω resistor per channel.
- Set any visible colour by calling
analogWriteon all three channels in turn, using values 0–255. - Crossfade smoothly between two colours by ramping one channel up while the other ramps down — your first real animation across multiple pins.
Warm-Up 10 min
So far you've only fed one channel of analogWrite. The RGB LED has three inside one body — a tiny red chip, a tiny green chip, a tiny blue chip — sharing a single cathode (the long leg). Drive each with its own PWM pin and you mix any colour your eye can see.
Quick puzzle
Predict the colour the RGB LED will look:
analogWrite(R, 255);
analogWrite(G, 255);
analogWrite(B, 0);Reveal
Full red + full green + no blue = yellow. (In additive light mixing — different from paint mixing.) The three primary lights add: R + G = yellow, G + B = cyan, R + B = magenta, R + G + B = whitish.
New Concept · Three pins, one colour 20 min
What an RGB LED actually is
Look at one closely — it's a clear LED with four legs. Three are the red, green and blue anodes (one each); the long leg is the shared cathode. In a common-anode part the polarity flips (long leg = +, three short legs each tie to GND through a transistor) — Level 1 covered which kind you have in L01-30. For Level 2 we assume common cathode.
Wiring
On the breadboard what you build
On paper what engineers draw
| LED leg | Goes to | Through |
|---|---|---|
| R anode | Arduino ~9 | 220 Ω resistor |
| Cathode (longest leg) | GND rail | — |
| G anode | Arduino ~10 | 220 Ω resistor |
| B anode | Arduino ~11 | 220 Ω resistor |
One 220 Ω resistor per colour. The cathode pin is usually noticeably longer than the others; if you can't tell by length, the leg next to the flat spot on the bulb is one of the anodes — try both orientations until you see colour.
The additive mixing table
| R | G | B | Colour |
|---|---|---|---|
| 255 | 0 | 0 | Red |
| 0 | 255 | 0 | Green |
| 0 | 0 | 255 | Blue |
| 255 | 255 | 0 | Yellow |
| 0 | 255 | 255 | Cyan |
| 255 | 0 | 255 | Magenta |
| 255 | 255 | 255 | White (ish — see below) |
| 255 | 165 | 0 | Orange |
| 128 | 0 | 128 | Purple |
| 0 | 0 | 0 | Off |
Anything in between mixes proportionally — exactly the same numbers used by every web colour picker. 24-bit colour everywhere on the internet is just three of these channels times eight bits each.
The crossfade pattern
To smoothly transition from red to green, ramp red down from 255 to 0 while ramping green up from 0 to 255 — in the same loop, same speed:
for (int v = 0; v <= 255; v++) {
analogWrite(R, 255 - v); // 255 → 0 (red dims)
analogWrite(G, v); // 0 → 255 (green brightens)
delay(10);
}The eye sees a single point shifting smoothly through orange and lime on its way from red to green. The maths is identical to two fade loops sharing a counter — no new trick.
Why "white" isn't quite white
The red, green and blue chips inside the LED have different forward voltages and different efficiencies. So (255, 255, 255) often looks a bit cool / blue-tinted. To get a warmer white, knock the blue back a little — try (255, 220, 180). There's no "correct" — pick what looks white to your eye.
Worked Example · Red → green → blue → red 20 min
Step 1 — wiring
Build the wiring from the table above. The LED sits in row D of the breadboard with its four legs in adjacent columns; each anode runs through a 220 Ω resistor up to its Arduino pin; the cathode runs to the − rail; the − rail connects to Arduino GND.
Step 2 — the crossfade sketch
Save as rgb-crossfade.ino:
// L02-05: smooth crossfade R → G → B → R, repeating
const int R = 9;
const int G = 10;
const int B = 11;
const int STEP_DELAY = 10;
void setup() {
pinMode(R, OUTPUT);
pinMode(G, OUTPUT);
pinMode(B, OUTPUT);
analogWrite(R, 255); // start on red
}
void loop() {
// Red → Green
for (int v = 0; v <= 255; v++) {
analogWrite(R, 255 - v);
analogWrite(G, v);
delay(STEP_DELAY);
}
// Green → Blue
for (int v = 0; v <= 255; v++) {
analogWrite(G, 255 - v);
analogWrite(B, v);
delay(STEP_DELAY);
}
// Blue → Red
for (int v = 0; v <= 255; v++) {
analogWrite(B, 255 - v);
analogWrite(R, v);
delay(STEP_DELAY);
}
}Step 3 — upload & watch
Three smooth ramps. Total cycle = 3 × 256 × 10 ms ≈ 7.7 seconds. The LED walks through every primary, secondary and intermediate hue you can name.
Step 4 — a helper function to clean up
Three identical-shaped loops is a sign a function is hiding. Extract one:
void crossfade(int outPin, int inPin) {
for (int v = 0; v <= 255; v++) {
analogWrite(outPin, 255 - v);
analogWrite(inPin, v);
delay(STEP_DELAY);
}
}
void loop() {
crossfade(R, G);
crossfade(G, B);
crossfade(B, R);
}The main loop now reads like a stage direction: red fades to green, green fades to blue, blue fades to red. Add a fourth call (crossfade(R, G)... wait, that's the start of the next cycle anyway) and you can re-arrange the colour order without touching the loops.
Basic 7 min
Goal: Make a single static colour. Set the LED to a colour from the table — your choice — and leave it there. No fades.
Challenge 1 7 min
Goal: Build the crossfade sketch from the worked example, then refactor it using the crossfade(outPin, inPin) helper. Confirm the colours and speed look identical to before.
Challenge 2 6 min
Goal: Make the colour cycle through six distinct hues: red → yellow → green → cyan → blue → magenta → red. That's six crossfades per cycle instead of three.
Challenge 3 · The traffic light 15 min
Use the single RGB LED to imitate a traffic-light cycle:
- Red for 4 seconds.
- Yellow (R = 255, G = 100, B = 0) for 1 second.
- Green for 4 seconds.
- Crossfade green → yellow over 0.5 seconds.
- Yellow for 1 second.
- Crossfade yellow → red over 0.5 seconds.
- Repeat.
It works if:
- The colours look distinct — red is unmistakably red, green clearly green, yellow visibly between.
- The crossfades are smooth, not stepped.
- Total cycle is about 11 seconds.
- The code uses a function (
setColour(r, g, b)is a good name) so the main loop reads like a script.
Recap 5 min
An RGB LED is three LEDs in one body sharing a cathode. Three PWM pins control the three brightnesses; the eye mixes them additively. Set a colour with three analogWrite calls; crossfade between colours by ramping one channel up while another goes down. Wrap the three writes in setColour(r, g, b) and your sketch reads like a paint-by-numbers script. Tomorrow we use the same hardware for a calmer project — the breathing mood lamp.
- RGB LED
- An LED containing red, green and blue chips in one body, with three anode legs and one shared cathode (common cathode) or vice versa (common anode).
- Common cathode / common anode
- Which of the two shared legs sits at GND vs +5 V. Common cathode is the easier default — anodes go to PWM pins, cathode to GND.
- Additive mixing
- Light mixing: R + G = yellow, G + B = cyan, R + B = magenta, R + G + B = white-ish. Opposite of paint (subtractive).
- Crossfade
- Smooth transition between two states by ramping one variable up while the related one ramps down in the same loop.
setColour(r, g, b)- Convention helper that takes three brightnesses and writes them to the three RGB pins. Keeps the main sketch readable.
Extra Mission 5 min
Part 1 — Design a colour signal
Many devices speak in colours — a charger glows red then green, a game controller shows which player you are. Pick an everyday object. On paper, design how one RGB LED could tell its user what is going on.
Your design must include:
- A name and a one-sentence job for the device.
- At least three states, each with a colour name and its R, G, B values (0–255).
- Which changes are instant and which are crossfades, and how long each fade takes.
- The PWM pin for each channel and the resistors.
Part 2 — Make it
Build it with today's RGB LED wiring. Write a setColour(r, g, b) function and use a crossfade for at least one change. Step through your states in loop() and print each state name.
Bring back next class: the uploaded sketch, a photo of each colour and a Serial Monitor screenshot.