ย 

๐Ÿš€ Project 3.1 โ€“ JoyStick Shield

๐ŸŽฏ What youโ€™ll learn

  • โœ… Goal 1: Read joystick X/Y movement as changing numbers on your screen
  • โœ… Goal 2: Detect button presses Aโ€“F and print actions
  • โœ… Goal 3: Map joystick directions to control an LED and navigate a simple menu

Key ideas

  • Short definition: A joystick sends two analog values (X and Y) and six digital button signals.
  • Real-world link: Joysticks control games, robots, and remote vehicles by translating movement into actions.

๐Ÿงฑ Blocks glossary (used in this project)

  • Analog input: Reads a smooth value (0โ€“4095) from a pin.
  • Digital input (pull-up): Reads button state, pressed = 0.
  • Digital output: Turns things ON/OFF like LEDs.
  • Serial print: Shows messages from the robot on your screen.
  • Variable: A named box that stores a value.
  • if / else: Robot decides what to do next.
  • Loop: Repeats actions continuously.

๐Ÿงฐ What you need

PartHow many?Pin connection
D1 R321USB cable (30 cm)
JoyStick Shield1X โ†’ Pin 2, Y โ†’ Pin 4, Buttons Aโ€“F as below
LED Module1Pin 13 (digital output)
  • Button pins: A(26), B(25), C(17), D(16), E(27), F(14)
  • Available pins for extras: 13, 5, 23, 19, 18, 34, 35, 36, 39, 21, 22
  • Z button: Disconnected (ignore)

๐Ÿ”Œ Wiring tip: The Funduino Joystick Shield plugs directly on top of the D1 R32 โ€” no loose wires needed.
๐Ÿ“ Pin map snapshot: Use Pin 2 (X), Pin 4 (Y). Keep Pin 13 free for the LED. Buttons use pull-up and are active LOW.


โœ… Before you start

  • USB cable is plugged in
  • Serial monitor is open
  • Test print shows:
print("Ready!")  # Confirm serial is working

๐ŸŽฎ Microprojects (5 mini missions)

๐ŸŽฎ Microproject 3.1.1 โ€“ Reading X/Y axes joystick

Goal: Print joystick X and Y values to the serial monitor.

Blocks used:

  • Analog input: Read X and Y
  • Serial print: Show values
  • Loop: Repeat reads

Block sequence:

  1. Setup Pin 2 and Pin 4 as analog inputs
  2. Configure attenuation and resolution
  3. Read values
  4. Print values
  5. Delay and repeat

MicroPython code:

# Microproject 3.1.1 โ€“ Read joystick X/Y values

import machine            # Load hardware control library
import time               # Load time library for delays

adc2 = machine.ADC(machine.Pin(2))            # Create ADC on Pin 2 for X-axis
adc4 = machine.ADC(machine.Pin(4))            # Create ADC on Pin 4 for Y-axis

adc2.atten(machine.ADC.ATTN_11DB)             # Set X-axis range to 0โ€“3.3V
adc2.width(machine.ADC.WIDTH_12BIT)           # Set X-axis resolution to 12-bit (0โ€“4095)
adc4.atten(machine.ADC.ATTN_11DB)             # Set Y-axis range to 0โ€“3.3V
adc4.width(machine.ADC.WIDTH_12BIT)           # Set Y-axis resolution to 12-bit (0โ€“4095)

print("[Init] Joystick ADC ready on pins X=2, Y=4")  # Confirm setup

while True:                                    # Start continuous reading loop
    x_value = adc2.read()                      # Read X-axis value (0โ€“4095)
    y_value = adc4.read()                      # Read Y-axis value (0โ€“4095)
    print("[Joystick] X:", x_value, "Y:", y_value)  # Print both axis values
    time.sleep_ms(300)                         # Delay for readable updates

Reflection: You turned hand motion into numbers your robot understands.
Challenge:

  • Easy: Change the delay to 100 ms for faster updates.
  • Harder: Print only when X or Y changes from the last reading.

๐ŸŽฎ Microproject 3.1.2 โ€“ Reading joystick buttons Aโ€“F

Goal: Detect button presses and print messages.

Blocks used:

  • Digital input (pull-up): Read button states
  • if / else: Decide what to print
  • Serial print: Show messages

Block sequence:

  1. Setup buttons Aโ€“F as digital inputs (pull-up)
  2. Read each buttonโ€™s value
  3. If pressed, print a message
  4. Repeat

MicroPython code:

# Microproject 3.1.2 โ€“ Read joystick buttons Aโ€“F

import machine                        # Load hardware control library
import time                           # Load time library for delays

pin26 = machine.Pin(26, machine.Pin.IN, machine.Pin.PULL_UP)  # Button A pull-up
pin25 = machine.Pin(25, machine.Pin.IN, machine.Pin.PULL_UP)  # Button B pull-up
pin17 = machine.Pin(17, machine.Pin.IN, machine.Pin.PULL_UP)  # Button C pull-up
pin16 = machine.Pin(16, machine.Pin.IN, machine.Pin.PULL_UP)  # Button D pull-up
pin27 = machine.Pin(27, machine.Pin.IN, machine.Pin.PULL_UP)  # Button E pull-up
pin14 = machine.Pin(14, machine.Pin.IN, machine.Pin.PULL_UP)  # Button F pull-up

print("[Init] Buttons A=26 B=25 C=17 D=16 E=27 F=14 (active LOW)")  # Confirm setup

while True:                                     # Start continuous reading loop
    if pin26.value() == 0:                      # Check button A pressed (LOW)
        print("[Button] A pressed")             # Print message for A
    if pin25.value() == 0:                      # Check button B pressed (LOW)
        print("[Button] B pressed")             # Print message for B
    if pin17.value() == 0:                      # Check button C pressed (LOW)
        print("[Button] C pressed")             # Print message for C
    if pin16.value() == 0:                      # Check button D pressed (LOW)
        print("[Button] D pressed")             # Print message for D
    if pin27.value() == 0:                      # Check button E pressed (LOW)
        print("[Button] E pressed")             # Print message for E
    if pin14.value() == 0:                      # Check button F pressed (LOW)
        print("[Button] F pressed")             # Print message for F
    time.sleep_ms(100)                          # Delay to avoid spam and bounce

Reflection: Your robot now hears your button taps like a controller.
Challenge:

  • Easy: Print โ€œCombo A+B!โ€ when both A and B are pressed at once.
  • Harder: Count how many times button C was pressed and print the total.

๐ŸŽฎ Microproject 3.1.3 โ€“ LED control with joystick

Goal: Turn an LED ON/OFF based on joystick X direction.

Blocks used:

  • Analog input: Read X
  • Digital output: Control LED
  • if / else: Decide ON/OFF

Block sequence:

  1. Setup Pin 2 as analog input (X)
  2. Setup Pin 13 as digital output (LED)
  3. If X is high (tilted right), LED ON; else, LED OFF
  4. Print status and repeat

MicroPython code:

# Microproject 3.1.3 โ€“ Control LED with X-axis

import machine                         # Load hardware control library
import time                            # Load time library for delays

adc2 = machine.ADC(machine.Pin(2))                    # ADC on Pin 2 for X-axis
adc2.atten(machine.ADC.ATTN_11DB)                     # Set X range to 0โ€“3.3V
adc2.width(machine.ADC.WIDTH_12BIT)                   # Set X resolution to 12-bit
pin13 = machine.Pin(13, machine.Pin.OUT)              # LED on Pin 13 as output

print("[Init] X=2 (ADC), LED=13 (digital output)")    # Confirm setup

threshold = 2800                                      # Threshold for RIGHT tilt
print("[Hint] Threshold:", threshold)                 # Show threshold value

while True:                                           # Start control loop
    x_value = adc2.read()                             # Read X value (0โ€“4095)
    if x_value > threshold:                           # If joystick tilted RIGHT
        pin13.value(1)                                # Turn LED ON
        print("[LED] ON | X:", x_value)               # Print status
    else:                                             # Otherwise (center or LEFT)
        pin13.value(0)                                # Turn LED OFF
        print("[LED] OFF | X:", x_value)              # Print status
    time.sleep_ms(200)                                # Small delay for stability

Reflection: You connected hand motion to light โ€” thatโ€™s physical computing!
Challenge:

  • Easy: LED ON when X is low (LEFT tilt) instead.
  • Harder: Use both X and Y: LED ON only if X RIGHT AND Y UP.

๐ŸŽฎ Microproject 3.1.4 โ€“ Mapping values to actions

Goal: Map joystick X ranges to โ€œLEFTโ€, โ€œCENTERโ€, โ€œRIGHTโ€ messages.

Blocks used:

  • Analog input: Read X
  • if / elif / else: Range checks
  • Serial print: Show direction

Block sequence:

  1. Read X
  2. If X < 1500 โ†’ โ€œLEFTโ€
  3. Else if X > 2500 โ†’ โ€œRIGHTโ€
  4. Else โ†’ โ€œCENTERโ€
  5. Print and repeat

MicroPython code:

# Microproject 3.1.4 โ€“ Map X-axis to LEFT/CENTER/RIGHT

import machine                          # Load hardware control library
import time                             # Load time library for delays

adc2 = machine.ADC(machine.Pin(2))                    # ADC on Pin 2 for X-axis
adc2.atten(machine.ADC.ATTN_11DB)                     # Set X range to 0โ€“3.3V
adc2.width(machine.ADC.WIDTH_12BIT)                   # Set X resolution to 12-bit

print("[Init] Map X to LEFT/CENTER/RIGHT")            # Confirm setup

while True:                                           # Start mapping loop
    x_value = adc2.read()                             # Read X value (0โ€“4095)
    if x_value < 1500:                                # If X in LEFT range
        print("[Dir] LEFT | X:", x_value)             # Print LEFT
    elif x_value > 2500:                              # If X in RIGHT range
        print("[Dir] RIGHT | X:", x_value)            # Print RIGHT
    else:                                             # Otherwise in CENTER band
        print("[Dir] CENTER | X:", x_value)           # Print CENTER
    time.sleep_ms(250)                                # Delay for readability

Reflection: You taught the robot to interpret numbers as directions.
Challenge:

  • Easy: Adjust LEFT/RIGHT cutoffs to match your joystickโ€™s center.
  • Harder: Add Y mapping too: UP, DOWN, CENTER (2D).

๐ŸŽฎ Microproject 3.1.5 โ€“ Joystick navigation menu

Goal: Use X/Y directions to navigate a simple text menu: PLAY, SETTINGS, INFO.

Blocks used:

  • Analog input: Read X/Y
  • if / else: Choose item
  • Serial print: Show selection

Block sequence:

  1. Read X/Y
  2. If UP(Y high) โ†’ โ€œPLAYโ€
  3. If RIGHT(X high) โ†’ โ€œSETTINGSโ€
  4. If DOWN(Y low) โ†’ โ€œINFOโ€
  5. Print current selection

MicroPython code:

# Microproject 3.1.5 โ€“ Navigate a 3-item menu with X/Y

import machine                                  # Load hardware control library
import time                                     # Load time library for delays

adc2 = machine.ADC(machine.Pin(2))                              # ADC on Pin 2 (X)
adc4 = machine.ADC(machine.Pin(4))                              # ADC on Pin 4 (Y)

adc2.atten(machine.ADC.ATTN_11DB)                               # Set X range 0โ€“3.3V
adc2.width(machine.ADC.WIDTH_12BIT)                             # Set X resolution 12-bit
adc4.atten(machine.ADC.ATTN_11DB)                               # Set Y range 0โ€“3.3V
adc4.width(machine.ADC.WIDTH_12BIT)                             # Set Y resolution 12-bit

print("[Init] Menu: PLAY(UP), SETTINGS(RIGHT), INFO(DOWN)")     # Show controls

while True:                                                     # Start menu loop
    x_value = adc2.read()                                       # Read X (0โ€“4095)
    y_value = adc4.read()                                       # Read Y (0โ€“4095)

    if y_value > 2800:                                          # If joystick UP
        print("[Menu] PLAY selected")                           # Announce PLAY
    elif x_value > 2800:                                        # If joystick RIGHT
        print("[Menu] SETTINGS selected")                       # Announce SETTINGS
    elif y_value < 1500:                                        # If joystick DOWN
        print("[Menu] INFO selected")                           # Announce INFO
    else:                                                       # Otherwise CENTER
        print("[Menu] (Hold to choose)")                        # Prompt to move

    time.sleep_ms(300)                                          # Delay for readability

Reflection: You built a tiny user interface โ€” all with the joystick!
Challenge:

  • Easy: Add a โ€œSELECTโ€ action when holding a direction for 1 second.
  • Harder: Use button A = confirm, B = back.

โœจ Main project โ€“ Joystick shield mini control panel

๐Ÿ”ง Blocks steps (with glossary)

  • Analog input: Read X/Y positions
  • Digital input (pull-up): Read buttons Aโ€“F
  • Digital output: Control an LED indicator
  • if / else: Map values to actions
  • Serial print: Show status and selection

Block sequence:

  1. Setup Pin 2 (X) and Pin 4 (Y) as analog inputs
  2. Setup Pins 26, 25, 17, 16, 27, 14 as digital inputs (pull-up)
  3. Setup Pin 13 as digital output (LED)
  4. Read X/Y and buttons
  5. If RIGHT โ†’ LED ON; if LEFT โ†’ LED OFF
  6. If A pressed โ†’ print โ€œSTARTโ€
  7. If B pressed โ†’ print โ€œSTOPโ€
  8. Repeat loop

๐Ÿ MicroPython code (mirroring blocks)

# Project 3.1 โ€“ Joystick Shield: Mini Control Panel

import machine                                     # Load hardware control library
import time                                        # Load time library for delays

adc2 = machine.ADC(machine.Pin(2))                                # ADC on Pin 2 (X)
adc4 = machine.ADC(machine.Pin(4))                                # ADC on Pin 4 (Y)

adc2.atten(machine.ADC.ATTN_11DB)                                   # Set X range 0โ€“3.3V
adc2.width(machine.ADC.WIDTH_12BIT)                                 # Set X resolution 12-bit
adc4.atten(machine.ADC.ATTN_11DB)                                   # Set Y range 0โ€“3.3V
adc4.width(machine.ADC.WIDTH_12BIT)                                 # Set Y resolution 12-bit

pin26 = machine.Pin(26, machine.Pin.IN, machine.Pin.PULL_UP)        # Button A input
pin25 = machine.Pin(25, machine.Pin.IN, machine.Pin.PULL_UP)        # Button B input
pin17 = machine.Pin(17, machine.Pin.IN, machine.Pin.PULL_UP)        # Button C input
pin16 = machine.Pin(16, machine.Pin.IN, machine.Pin.PULL_UP)        # Button D input
pin27 = machine.Pin(27, machine.Pin.IN, machine.Pin.PULL_UP)        # Button E input
pin14 = machine.Pin(14, machine.Pin.IN, machine.Pin.PULL_UP)        # Button F input

pin13 = machine.Pin(13, machine.Pin.OUT)                            # LED output on Pin 13

print("[Init] X=2, Y=4, Buttons=Aโ€“F, LED=13")                       # Confirm setup

while True:                                                         # Start main loop
    x_value = adc2.read()                                           # Read X (0โ€“4095)
    y_value = adc4.read()                                           # Read Y (0โ€“4095)

    if x_value > 2800:                                              # If joystick RIGHT
        pin13.value(1)                                              # Turn LED ON
        print("[LED] ON | X:", x_value, "Y:", y_value)              # Show status
    elif x_value < 1500:                                            # If joystick LEFT
        pin13.value(0)                                              # Turn LED OFF
        print("[LED] OFF | X:", x_value, "Y:", y_value)             # Show status
    else:                                                           # Otherwise CENTER
        print("[LED] HOLD | X:", x_value, "Y:", y_value)            # Show status

    if pin26.value() == 0:                                          # If A pressed (LOW)
        print("[Action] START (A)")                                 # Announce START
    if pin25.value() == 0:                                          # If B pressed (LOW)
        print("[Action] STOP (B)")                                  # Announce STOP
    if pin17.value() == 0:                                          # If C pressed (LOW)
        print("[Action] MODE (C)")                                  # Announce MODE
    if pin16.value() == 0:                                          # If D pressed (LOW)
        print("[Action] SELECT (D)")                                # Announce SELECT
    if pin27.value() == 0:                                          # If E pressed (LOW)
        print("[Action] BACK (E)")                                  # Announce BACK
    if pin14.value() == 0:                                          # If F pressed (LOW)
        print("[Action] INFO (F)")                                  # Announce INFO

    time.sleep_ms(200)                                              # Small delay for responsiveness

๐Ÿ“– External explanation

  • What it teaches: Reading analog and digital inputs, mapping motion and button taps to actions.
  • Why it works: The joystick changes voltage (X/Y), and buttons change digital states the board reads.
  • Key concept: Analog ranges (0โ€“4095) and digital states (pressed = 0 with pull-up).

โœจ Story time

Your robot now has its first โ€œremote brain.โ€ You can steer, select, and signal โ€” just like piloting a rover on a mission.


๐Ÿ•ต๏ธ Debugging (2 common problems)

๐Ÿž Debugging 3.1.A โ€“ Inverted axes

Problem: Moving left/right changes Y instead of X.
Clues: Serial shows Y changing when you move X.

Broken code:

adc2 = machine.ADC(machine.Pin(4))  # Wrong: X wired to Pin 2, not 4

Fixed code:

adc2 = machine.ADC(machine.Pin(2))  # Correct: X-axis on Pin 2

Why it works: The hardware map defines X=2, Y=4 โ€” use the right pin.
Avoid next time: Confirm pin map before coding.


๐Ÿž Debugging 3.1.B โ€“ Buttons are not responding

Problem: Pressing buttons shows nothing on serial.
Clues: No โ€œ[Button] โ€ฆ pressedโ€ messages appear.

Broken code:

pin26 = machine.Pin(26, machine.Pin.IN)  # Missing pull-up configuration

Fixed code:

pin26 = machine.Pin(26, machine.Pin.IN, machine.Pin.PULL_UP)  # Enable pull-up

Why it works: Pull-up sets a default HIGH; pressing connects to LOW (active low).
Avoid next time: Always use pull-up for these shield buttons.


โœ… Final checklist

  • I saw X and Y values change when I moved the joystick
  • Buttons Aโ€“F printed messages when pressed
  • The LED turned ON/OFF with joystick direction
  • My tweak (thresholds or menu choices) changed the result

๐Ÿ“š Extras

  • ๐Ÿง  Student tip: Try diagonal moves โ€” watch both X and Y change together.
  • ๐Ÿง‘โ€๐Ÿซ Instructor tip: Ask students to find their joystickโ€™s โ€œcenter bandโ€ by testing values.
  • ๐Ÿ“– Glossary:
    • Analog value: A smooth number from 0 to 4095.
    • Digital input: A simple true/false signal.
    • Pull-up: Keeps an input HIGH until the button is pressed.
  • ๐Ÿ’ก Mini tips:
    • Keep delays small to make controls responsive.
    • Print short messages so the serial monitor stays readable.
    • Thresholds vary slightly โ€” test and adjust.
On this page