Mix colours with a joystick

Steer around a colour wheel with the joystick to pick any colour on the RGB LED module, and click to switch between bright and dim.
  • Level:Beginner
  • Duration: 40 min
  • Ages 10+
  • Platform: Arduino

Tools for this lesson

Helpful for this build. Open a tool to see tips and more projects that use it.

Mix colours with a joystick – EEMENTOR STEM™ lesson

A colour wheel puts red, green and blue around a circle with all the mixed colours in between. In this project the joystick becomes a pointer on that wheel: push it in any direction and the RGB LED shows the colour in that direction. The further you push, the stronger the colour. Click the stick to switch between bright and dim.

What you'll learn

  • How to turn joystick X and Y into an angle and a distance
  • How the colour wheel (hue) maps to red, green and blue
  • How to mix colours with PWM
  • How to use the joystick's built-in button

What you need

  • UNO R3 board and USB cable (UNO R3 Starter Kit)
  • Joystick module (45-in-1 Sensor Kit)
  • RGB LED module (45-in-1 Sensor Kit)
  • 3 resistors, 220 Ω (UNO R3 Starter Kit)
  • Breadboard and jumper wires (UNO R3 Starter Kit)

Wiring

Breadboard wiring diagram: Mix colours with a joystick
Breadboard view. Check each connection against the wiring table below.
From Through To
Joystick GND GND
Joystick +5V 5V
Joystick VRx UNO pin A0
Joystick VRy UNO pin A1
Joystick SW UNO pin 2
UNO pin 9 220 Ω resistor RGB module R
UNO pin 10 220 Ω resistor RGB module G
UNO pin 11 220 Ω resistor RGB module B
RGB module − GND

Sensor modules from different makers can label and order their pins differently. Always follow the labels printed on your module.

The sketch

const int X_PIN = A0;
const int Y_PIN = A1;
const int SW_PIN = 2;
const int RED_PIN = 9;
const int GREEN_PIN = 10;
const int BLUE_PIN = 11;

bool dim = false;
int lastButton = HIGH;

// Hue 0-359 on the colour wheel -> red, green and blue 0-255
void hueToRgb(int hue, int &r, int &g, int &b) {
  int part = hue / 60;                      // which sixth of the wheel
  int f = (hue % 60) * 255 / 60;            // how far into that sixth
  switch (part) {
    case 0:  r = 255;     g = f;       b = 0;       break;   // red -> yellow
    case 1:  r = 255 - f; g = 255;     b = 0;       break;   // yellow -> green
    case 2:  r = 0;       g = 255;     b = f;       break;   // green -> cyan
    case 3:  r = 0;       g = 255 - f; b = 255;     break;   // cyan -> blue
    case 4:  r = f;       g = 0;       b = 255;     break;   // blue -> magenta
    default: r = 255;     g = 0;       b = 255 - f; break;   // magenta -> red
  }
}

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

void loop() {
  int x = analogRead(X_PIN) - 512;          // -512 ... +511, 0 in the middle
  int y = analogRead(Y_PIN) - 512;

  int button = digitalRead(SW_PIN);
  if (button == LOW && lastButton == HIGH) dim = !dim;   // click: bright <-> dim
  lastButton = button;

  float distance = sqrt((float)x * x + (float)y * y);    // how far you push
  float strength = constrain(distance / 500.0, 0.0, 1.0);
  int hue = (int)(atan2(y, x) * 180.0 / PI + 360) % 360; // which direction

  int r, g, b;
  hueToRgb(hue, r, g, b);
  float scale = strength * (dim ? 0.15 : 1.0);
  if (distance < 60) scale = 0;             // in the middle: off

  analogWrite(RED_PIN, r * scale);
  analogWrite(GREEN_PIN, g * scale);
  analogWrite(BLUE_PIN, b * scale);
  delay(20);
}

How it works

The joystick gives two numbers, X and Y, each about 512 when the stick is in the middle. Subtracting 512 puts the middle at 0, so the pair (x, y) is an arrow pointing where you push. atan2(y, x) turns that arrow into an angle, and the Pythagorean theorem gives its length, which is how far you push.

The angle becomes the hue, the position on the colour wheel. The wheel is split into six parts; in each part one colour channel rises or falls while the other two stay fixed, which is exactly how screens produce all the colours in between. The length sets the brightness, and the click toggles a dim mode for using the lamp in the dark.

Try this next

  • Hold the colour when you let go of the stick, so you can pick a colour and keep it.
  • Show the hue as a number from 0 to 359 in the Serial Monitor.
  • Fade slowly through the whole colour wheel when nobody touches the joystick.

Troubleshooting

  • The colours go round the wrong way: swap the X and Y wires, or write atan2(-y, x).
  • One colour never appears: check that channel's resistor and its wire to pin 9, 10 or 11.
  • The LED flickers in the middle position: raise the 60 in distance < 60 a little.
  • The click doesn't work: check SW on pin 2.

Build it yourself

Everything used in this lesson comes in one kit, with parts tested by our engineers.

UNO R3 Starter Kit | Arduino IDE Compatible | Free Tutorials $56.00

Shop the kit