BBC micro:bit
Joystick Joy

Introduction

The photograph shows a 2 axis analog joystick connected to the micro:bit. These exercises are a good way in if you think you are going to want to add a joystick to a more complex project than there is on this page.

micro:bit circuit

Each axis of the joystick is a potentiometer.

A potentiometer is a type of resistor. Resistors are used to, among other things, reduce current flow and to adjust signals. A potentiometer is a variable resistor. By pushing the joystick, we change the resistance in a way that the micro:bit can sense.

Potentiometers generally require 3 connections each.

X AxisY Axis
VCC3VVCC3V
GNDGNDGNDGND
S-Xpin1S-Ypin0

The Bit:Commander also contains a joystick - its X and Y axis are connected to different pins. With a few adjustments, the following exercises can be completed with the Bit:Commander.

Task 1

The joystick is likely to give you the following readings,

AxisMinMaxCentre
X31023520
Y31023518

Pushing the joystick fully to the left gives a reading of 3 on the X axis. Pusing the joystick fully up gives a reading of 3 on the Y axis.

Try the following program to test that the joystick is working.

from microbit import *
xaxis = pin1
yaxis = pin0
while True:
    x = xaxis.read_analog()
    y = yaxis.read_analog()
    if x<10:
        display.show(Image.ARROW_W)
        sleep(500)
    elif x>1000:
        display.show(Image.ARROW_E)
        sleep(500)
    else:
        display.clear()
    sleep(20)

The program repeatedly takes readings from the joystick.

If it reads less than 10 on the X axis, it displays a West arrow.

If it reads more than 1000 on the X axis, it displays an East arrow.

Your task is to add two more elif clauses to make North and South arrows appear when you move the joystick up and down.

Task 2

You will be adapting and extending your program from Task 1. With 2 axes on the joystick, we can allow for 8 different directions. Here is the start you might make,

from microbit import *

xaxis = pin1
yaxis = pin0

while True:
    x = xaxis.read_analog()
    y = yaxis.read_analog()
    if x<10 and y<10:
        display.show(Image.ARROW_NW)
        sleep(500)
    else:
        display.clear()
    sleep(20)

You need to check all of the diagonal movements before you look for simple left, right, up down. Finish the program so that all 8 compass points can be selected. You may wish to increase the number 10 in the program if you find it hard to select the diagonals.

Task 3

For this task, start with your finished program for Task 1. Remove the lines that sleep for 500 milliseconds. When the user pushes the joystick up, left, right or down, check if the A button is pressed. If the A button is pressed, show the appropriate arrow image.

This makes a subtle change in the user interaction.

Task 4

This example program does not use the joystick. It expects the user to press the A and B buttons in a specific order, showing a smiley face if they do, a sad face if they do not.

from microbit import *
secret = "AABBABAB"
entered = ""
while len(entered)<len(secret):
    if button_a.is_pressed():
        display.show("A")
        sleep(500)
        display.clear()
        entered += "A"
    elif button_b.is_pressed():
        display.show("B")
        sleep(500)
        display.clear()
        entered += "B"
    sleep(20)
if entered==secret:
    display.show(Image.HAPPY)
else:
    display.show(Image.SAD)

Adapt the program so that the A and B buttons are not used.

Make your secret equal to a mix of the letters N,E,S,W (the directions of movement of the joystick).

Instead of capturing button presses, use the 4 inputs from the joystick.

Task 5

The following program adjusts the position of a lit LED on the matrix based on the position of the joystick. This is not about making stepped movements - let the joystick go and the dot falls back to the centre.

Copy the program and read the explanations. Note down any questions you have about the code and put them to your teacher.

from microbit import *

def joy2grid():
    x = pin1.read_analog()
    y = pin0.read_analog()
    x = int((x / 1023) * 4 + 0.5)
    y = int((y / 1023) * 4 + 0.5)
    return x,y
    
lastx = 2
lasty = 2
display.set_pixel(lastx,lasty,9)
while True:
    x,y = joy2grid()
    if x!=lastx or y!=lasty:
        display.clear()
        display.set_pixel(x,y,9)
    lastx = x
    lasty = y
    sleep(20)

This program contains a subroutine. It takes a reading from each axis of the joystick. A formula is used to convert the reading to a pair of coordinates on the LED matrix.

The lastx and lasty variables are used to detect whether there has been a change in the joystick position since the last reading.

A starting position is drawn on the matrix. A while True loop repeats indefinitely. The subroutine is called for a joystick reading and the program only updates the display when either x or y coordinates of the dot are changed.

Adapt the program to do something interesting for each different position on the LED matrix.