Arduino Tutorials

Arduino RGB LED: Mix Any Color with Three PWM Pins

Arduino Uno wired to a common-cathode RGB LED on PWM pins 9, 10 and 11 in a circuit simulator

An RGB LED is three LEDs sharing one plastic bubble — red, green, and blue dies in a single package. Drive them at different brightnesses and they blend into basically any color you can name. It’s the first project that feels like a light show instead of an electronics lesson.

The whole thing runs on three PWM pins and a helper function called setColor(). We’ll cycle through seven colors: red, green, blue, yellow, cyan, magenta, white. In the browser simulator, so no parts bin required.

Four legs, one gotcha

An RGB LED has four pins: three anodes (R, G, B) and one common pin (COM). The gotcha is that “common” comes in two flavors. This project uses a common-cathode LED — COM goes to GND, and you light a channel by driving its pin HIGH. If you ever buy a common-anode one by accident, COM goes to 5V instead and the logic inverts (LOW turns a channel on). The colors will look possessed until you figure that out. Check the listing when you order.

  • R pin → Arduino pin 9 (red wire)
  • G pin → pin 10 (green)
  • B pin → pin 11 (blue)
  • COM → GND (black)

Arduino Uno wired to a common-cathode RGB LED on PWM pins 9, 10 and 11 in a circuit simulator

All three channels must land on PWM (~) pins, because we’re dimming each one independently — 9, 10, 11 qualify. On real hardware you’d also drop a 220Ω resistor on each anode; the sim’s LED model has that covered internally.

The sketch

// RGB LED color cycler
// Seven colors, one second each

const int RED_PIN = 9;
const int GREEN_PIN = 10;
const int BLUE_PIN = 11;

void setup() {
  pinMode(RED_PIN, OUTPUT);
  pinMode(GREEN_PIN, OUTPUT);
  pinMode(BLUE_PIN, OUTPUT);
}

void setColor(int red, int green, int blue) {
  analogWrite(RED_PIN, red);
  analogWrite(GREEN_PIN, green);
  analogWrite(BLUE_PIN, blue);
}

void loop() {
  setColor(255, 0, 0);     // red
  delay(1000);
  setColor(0, 255, 0);     // green
  delay(1000);
  setColor(0, 0, 255);     // blue
  delay(1000);
  setColor(255, 255, 0);   // yellow
  delay(1000);
  setColor(0, 255, 255);   // cyan
  delay(1000);
  setColor(255, 0, 255);   // magenta
  delay(1000);
  setColor(255, 255, 255); // white
  delay(1000);
}

Arduino RGB LED sketch with a setColor helper function cycling seven colors

setColor() is the star. Three arguments, 0–255 each, one analogWrite() per channel. Once that helper exists, the loop reads like a playlist: call a color, wait a second, call the next one. Mixed colors are just addition — red + green gives yellow, green + blue gives cyan, red + blue gives magenta, all three at full gives white-ish.

Under the hood each channel is PWM running at roughly 490Hz: the pin flickers on and off faster than you can see, and the fraction of “on” time becomes the brightness. Same trick as the single-LED fade project, times three.

Run it

Press Run and watch the LED step through the rainbow. The jump between colors is instant — pretty, but a little harsh. We’ll fix that in the extensions.

When the colors look wrong

  • Colors are swapped (you ask for red and get green) → two anode wires are crossed. Match wires to the pin numbers, not to where the legs happen to reach.
  • Dead LED entirely → COM isn’t grounded. It’s the one wire everything depends on.
  • Only full-brightness colors, no mixes → a channel landed on a non-PWM pin. No ~, no dimming.
  • “White” looks blue-ish or pink-ish on real hardware → normal. The three dies have different efficiencies, and 255,255,255 rarely gives a neutral white without tuning. Drop green and blue a bit and eyeball it.

Worth knowing about the sim version

The simulator renders the mixed color perfectly, which is generous. Real RGB LEDs have quirks the model doesn’t bother with: the red die usually needs less voltage than green and blue (which is why its resistor value sometimes differs in serious builds), the viewing angle differs per die so the color shifts as you move your head, and cheap units have visible hotspots. None of it matters for learning — just don’t expect your $5 kit to look like the screen.

Next level

The obvious upgrade is fading between colors instead of jumping: nest a loop that steps each channel from its current value to the target, a few counts every few milliseconds. That one change turns this from a demo into ambient lighting. After that: a potentiometer to sweep the hue, or serial commands so you can type “255 100 0” and get exactly that.

Open the simulator and load the RGB example. First experiment to try: setColor(255, 40, 0). It’s orange, and it looks way better than it has any right to.

Leave a Reply

Your email address will not be published. Required fields are marked *