Joystick bar graph on an Arduino Uno
A thumb stick moves a bar along eight LEDs, and pressing the stick swaps the bar to the other axis. The whole build, an Arduino Uno and 17 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.
Teaching? Assign it to your class in one click.
Intermediate About 25 minutes to build and run. Runs in your browser. Free, and no account needed.
The parts retail for about $35. On Mokxi they're free.
Step by step, with the wiring and the common mistakes: Arduino Joystick Module: Wiring, Code, Live Demo
What you'll learn
- Analog input from a potentiometer-style stick
- Scaling a reading with
map - Driving several LEDs from an array of pin numbers
- Toggling a mode with a button click
- Difficulty: Intermediate
- Time: About 25 minutes
- Board: Arduino Uno R3
- Parts: 19
How it works
The thumb stick has two potentiometers, one per axis. They go to A0 (X) and A1 (Y). The sketch reads one of them and turns the 0 to 1023 reading into 0 to 8 lit LEDs.
Eight LEDs on pins 2 to 9 make the bar, each with its own 220 ohm resistor. Center the stick and about half of them light.
Pressing the stick pulls pin 12 to ground. That swaps the bar between the X and Y axes, and the serial monitor says which one you are reading.
Parts list
19 parts, plus the jumper wires. They retail for about $35; on Mokxi they're free.
- 1 × Arduino Uno R3In Starter Kit, Claw Machine Kit, Vending Machine Kit.
- 1 × Full-size breadboard
- 1 × Thumb stickIn Claw Machine Kit, Spaceship Panel Kit.
- 8 × Resistor, 220 ΩIn Starter Kit, Claw Machine Kit, Halloween Prop Kit.
- 3 × LED, greenIn Starter Kit, Halloween Prop Kit, Logic Lab Kit.
- 3 × LED, yellowIn Starter Kit, Halloween Prop Kit, Logic Lab Kit.
- 2 × LED, redIn Starter Kit, Halloween Prop Kit, Logic Lab Kit.
Kits that can build it
These 8 starter kits have every part in the circuit. Each kit's page lists what else it can build.
Wiring table
Every connection, pin by pin, read from the circuit itself. Each row joins the pin on the left to the pin on the right, by a jumper wire or a breadboard strip.
| Part and pin | Connects to |
|---|---|
| Thumb stick pin SW | Arduino Uno R3 pin 12 |
| Resistor, 220 Ω (8) pin 1 | Arduino Uno R3 pin 9 |
| Resistor, 220 Ω (7) pin 1 | Arduino Uno R3 pin 8 |
| Resistor, 220 Ω (6) pin 1 | Arduino Uno R3 pin 7 |
| Resistor, 220 Ω (5) pin 1 | Arduino Uno R3 pin 6 |
| Resistor, 220 Ω (4) pin 1 | Arduino Uno R3 pin 5 |
| Resistor, 220 Ω (3) pin 1 | Arduino Uno R3 pin 4 |
| Resistor, 220 Ω (2) pin 1 | Arduino Uno R3 pin 3 |
| Resistor, 220 Ω (1) pin 1 | Arduino Uno R3 pin 2 |
| Thumb stick pin VCC | Arduino Uno R3 pin 5V |
| Thumb stick pin GND | Arduino Uno R3 pin GND |
| LED, green (1) pin C | Arduino Uno R3 pin GND |
| LED, green (2) pin C | Arduino Uno R3 pin GND |
| LED, green (3) pin C | Arduino Uno R3 pin GND |
| LED, yellow (1) pin C | Arduino Uno R3 pin GND |
| LED, yellow (2) pin C | Arduino Uno R3 pin GND |
| LED, yellow (3) pin C | Arduino Uno R3 pin GND |
| LED, red (1) pin C | Arduino Uno R3 pin GND |
| LED, red (2) pin C | Arduino Uno R3 pin GND |
| Thumb stick pin VRX | Arduino Uno R3 pin A0 |
| Thumb stick pin VRY | Arduino Uno R3 pin A1 |
| LED, green (1) pin A | Resistor, 220 Ω (1) pin 2 |
| LED, green (2) pin A | Resistor, 220 Ω (2) pin 2 |
| LED, green (3) pin A | Resistor, 220 Ω (3) pin 2 |
| LED, yellow (1) pin A | Resistor, 220 Ω (4) pin 2 |
| LED, yellow (2) pin A | Resistor, 220 Ω (5) pin 2 |
| LED, yellow (3) pin A | Resistor, 220 Ω (6) pin 2 |
| LED, red (1) pin A | Resistor, 220 Ω (7) pin 2 |
| LED, red (2) pin A | Resistor, 220 Ω (8) pin 2 |
The code
The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.
// Bar graph: a thumb stick's X axis drawn on eight LEDs.
//
// pins 2..9 eight LEDs, each through 220 ohm to GND, left to right
// A0 the stick's VRX A1 its VRY
// pin 12 the stick's SW, to GND, internal pull-up
//
// analogRead gives 0..1023 for 0 to 5 V, and map() turns that into 0..8 lamps.
// That is the whole of a bar graph: the meter is the arithmetic, the LEDs are
// just where the answer is written down.
//
// Press the stick and the bar switches to the Y axis, so the same eight lamps
// read the other pot. The mode is printed when it changes, so the serial
// monitor says which axis you are looking at.
//
// A stick does not spring back to exactly 512, and the driver in
// mokxi_joystick.h samples where it rests at begin() and measures from there.
// Here the raw reading is what is wanted (the bar should be half lit when
// the stick is centered), so this one calls x() and y() rather than dx()
// and dy().
#include "mokxi_joystick.h"
const int LED_PINS[] = {2, 3, 4, 5, 6, 7, 8, 9};
const int LEDS = 8;
Joystick stick(A0, A1, 12);
bool useY = false;
static void bar(int lit) {
for (int i = 0; i < LEDS; i++) {
digitalWrite(LED_PINS[i], i < lit ? HIGH : LOW);
}
}
void setup() {
for (int i = 0; i < LEDS; i++) {
pinMode(LED_PINS[i], OUTPUT);
}
stick.begin();
Serial.begin(115200);
Serial.println("Mokxi Arduino Uno: joystick bar graph");
Serial.println("push the stick left and right; press it to swap axis");
}
void loop() {
if (stick.clicked()) {
useY = !useY;
Serial.print("reading the ");
Serial.println(useY ? "Y axis" : "X axis");
}
int raw = useY ? stick.y() : stick.x();
int lit = (int)map(raw, 0, 1023, 0, LEDS);
if (lit > LEDS) {
lit = LEDS;
}
bar(lit);
static int last = -1;
if (lit != last) {
last = lit;
Serial.print(useY ? "Y " : "X ");
Serial.print(raw);
Serial.print(" -> ");
Serial.print(lit);
Serial.println(" lamps");
}
delay(40);
}
Code walkthrough
The key functions of the sketch, and what each one does.
bar sketch.ino
Takes a number of lit LEDs and loops over the eight pins in LED_PINS. Any LED with an index below that number gets HIGH, and the rest get LOW. That makes a solid bar from the left.
static void bar(int lit) {
for (int i = 0; i < LEDS; i++) {
digitalWrite(LED_PINS[i], i < lit ? HIGH : LOW);
}
}setup sketch.ino
Sets all eight LED pins as outputs, calls stick.begin() and opens the serial monitor at 115200 with a short hint about how to use it.
void setup() {
for (int i = 0; i < LEDS; i++) {
pinMode(LED_PINS[i], OUTPUT);
}
stick.begin();
Serial.begin(115200);
Serial.println("Mokxi Arduino Uno: joystick bar graph");
Serial.println("push the stick left and right; press it to swap axis");
}loop sketch.ino
A click flips useY. Then it reads stick.y() or stick.x(), maps the raw value to 0 through LEDS, and calls bar. It prints only when the lit count changes, then waits 40 ms.
void loop() {
if (stick.clicked()) {
useY = !useY;
Serial.print("reading the ");
Serial.println(useY ? "Y axis" : "X axis");
}
int raw = useY ? stick.y() : stick.x();
int lit = (int)map(raw, 0, 1023, 0, LEDS);
if (lit > LEDS) {
lit = LEDS;
}
bar(lit);
static int last = -1;
if (lit != last) {
last = lit;
Serial.print(useY ? "Y " : "X ");
Serial.print(raw);
Serial.print(" -> ");
Serial.print(lit);
Serial.println(" lamps");
}
delay(40);
}Troubleshooting
The usual mistakes with this circuit, and the fix for each.
- The bar does not move This project
Check that VRX goes to A0 and VRY goes to A1, and that the stick has 5V and ground. - The bar is stuck on one axis This project
The switch must go from SW to pin 12. Pressing it should print "reading the Y axis" in the monitor. - Some LEDs never light This project
Check each LED's direction and that its resistor connects to the matching pin from 2 to 9. - The axis reads about half scale at rest instead of exactly zero, and the values drift a little, so the cursor or motor creeps. Thumb stick
Center is about half of the ADC range (about 512 on a 10 bit Arduino). Read it at startup and subtract that, then add a dead zone of a few counts. - The push button reads random values or always looks pressed. The switch pin is a plain contact to ground and has no pull-up on the stick. Thumb stick
Set the switch pin to INPUT_PULLUP and treat LOW as pressed. Debounce it in code. Power the stick from the same voltage as the ADC reference. - The LED is dim, burns out, or the pin reads wrong because the resistor value is off. Resistor
Read the color bands again. A 220 ohm to 330 ohm resistor suits a typical LED on 5 V. 10k is a common pull-up or pull-down value. Check with a multimeter if unsure. - A pull-up or pull-down resistor is missing, so the input floats and reads random values. Resistor
Tie the input to 5 V or ground through about 10k. Or use INPUT_PULLUP and wire the switch to ground. - The LED does not light, or it lights once and then dies. LED
LEDs have polarity. The longer leg (anode) goes toward the positive side. Always add a series resistor, about 220 ohms to 1 k ohm on a 5 V pin.
Change it and keep it
Open it in the editor, change the circuit or the code, and keep your version in a free account.