There are two examples included in the Wii Classic Controller library: a simple test and a displayio visualizer. The simple test code listens for a few of the possible inputs from the controller and prints when they've been pressed to the REPL. The displayio visualizer displays a vector image of a controller to show when a button is pressed, as well as the x and y coordinates of the joysticks.
Both examples use a QT Py RP2040.
Plug the Nunchuck breakout into the STEMMA QT port on the QT Py RP2040.
Then, attach your controller to the Nunchuck breakout with the notch facing up towards the front of the breakout.
Library Installation
To use with CircuitPython, you need to first install the Wii Classic controller library, and its dependencies, into the lib folder onto your CIRCUITPY drive. Then you need to update code.py with the example script.
Thankfully, we can do this in one go. In the example below, click the Download Project Bundle button below to download the necessary libraries and the code.py file in a zip file.
Plug your CircuitPython compatible microcontroller into your computer via a known good USB cable. Be sure the cable has data+power wires. The board should show up as a new flash drive named CIRCUITPY in your computer File Explorer or Finder (depending on your operating system).
Extract the contents of the zip file, and copy the entire lib folder and the code.py file to your CIRCUITPY drive.
Your CIRCUITPY/lib folder should contain the following folder and file:
- adafruit_bus_device/
- adafruit_wii_classic.mpy
Simple Test Example
Once everything is saved to the CIRCUITPY drive, connect to the serial console to see the data printed out!
# SPDX-FileCopyrightText: Copyright (c) 2023 Liz Clark for Adafruit Industries
#
# SPDX-License-Identifier: MIT
import time
import board
import adafruit_wii_classic
i2c = board.STEMMA_I2C()
ctrl_pad = adafruit_wii_classic.Wii_Classic(i2c)
while True:
left_x, left_y = ctrl_pad.joystick_l
right_x, right_y = ctrl_pad.joystick_r
left_pressure = ctrl_pad.l_shoulder.LEFT_FORCE
right_pressure = ctrl_pad.r_shoulder.RIGHT_FORCE
print(f"joystick_l = {left_x},{left_y}")
print(f"joystick_r = {right_x},{left_y}")
print(f"left shoulder = {left_pressure}")
print(f"right shoulder = {right_pressure}")
if ctrl_pad.buttons.A:
print("button A")
if ctrl_pad.buttons.B:
print("button B")
if ctrl_pad.d_pad.UP:
print("dpad Up")
if ctrl_pad.d_pad.DOWN:
print("dpad Down")
if ctrl_pad.d_pad.LEFT:
print("dpad Left")
if ctrl_pad.d_pad.RIGHT:
print("dpad Right")
time.sleep(0.5)
In the loop, the values of the two joysticks and the force readings from the two shoulder buttons are continuously printed to the REPL every 0.5 seconds. Please note that only the official Wii Classic controller has support for the shoulder button analog readings.
If you press any of the d-pad buttons or the A or B buttons, they will be printed to the REPL.
Connect the Nunchuck breakout to the QT Py RP2040 via a STEMMA QT cable.
Then, connect the QT Py to the 2.2" TFT via an EYESPI breakout as follows.
- EYESPI Vin to QT Py 3V (red wire)
- EYESPI GND to QT Py GND (black wire)
- EYESPI SCK to QT Py SCK (green wire)
- EYESPI MOSI to QT Py MO (white wire)
- EYESPI MISO to QT Py MI (orange wire)
- EYESPI DC to QT Py A1 (cyan wire)
- EYESPI RST to QT Py A3 (purple wire)
- EYESPI TCS to QT Py A2 (pink wire)
Displayio Visualizer Example
In the example below, click the Download Project Bundle button below to download the necessary libraries and the code.py file in a zip file. Extract the contents of the zip file, and copy the entire lib folder, the code.py file and the wii_classic.bmp bitmap file to your CIRCUITPY drive.
Your CIRCUITPY/lib folder should contain the following files and folders:
- adafruit_bitmap_font/
- adafruit_bus_device/
- adafruit_display_shapes/
- adafruit_display_text/
- adafruit_ili9341.mpy
- adafruit_wii_classic.mpy
- simpleio.mpy
# SPDX-FileCopyrightText: 2023 Liz Clark for Adafruit Industries
# SPDX-License-Identifier: MIT
import adafruit_ili9341
import board
import displayio
import simpleio
import terminalio
from adafruit_display_shapes.circle import Circle
from adafruit_display_text import label
from fourwire import FourWire
import adafruit_wii_classic
displayio.release_displays()
spi = board.SPI()
tft_cs = board.A2
tft_dc = board.A1
display_bus = FourWire(spi, command=tft_dc, chip_select=tft_cs, reset=board.A3)
display = adafruit_ili9341.ILI9341(display_bus, width=320, height=240)
bg = displayio.OnDiskBitmap("/wii_classic.bmp")
bg_tilegrid = displayio.TileGrid(bg, pixel_shader=bg.pixel_shader)
# Make the display context
splash = displayio.Group()
splash.append(bg_tilegrid)
display.root_group = splash
i2c = board.STEMMA_I2C()
ctrl_pad = adafruit_wii_classic.Wii_Classic(i2c)
RED = 0xFF0000
BLACK = 0x000000
button_spots = [
{"label": "dpad_up", "pos": (68, 92), "size": 7, "color": RED},
{"label": "dpad_down", "pos": (68, 132), "size": 7, "color": RED},
{"label": "dpad_left", "pos": (48, 112), "size": 7, "color": RED},
{"label": "dpad_right", "pos": (88, 112), "size": 7, "color": RED},
{"label": "button_a", "pos": (277, 111), "size": 7, "color": RED},
{"label": "button_b", "pos": (253, 137), "size": 7, "color": RED},
{"label": "button_x", "pos": (252, 86), "size": 7, "color": RED},
{"label": "button_y", "pos": (227, 111), "size": 7, "color": RED},
{"label": "button_select", "pos": (136, 116), "size": 4, "color": RED},
{"label": "button_home", "pos": (160, 116), "size": 4, "color": RED},
{"label": "button_start", "pos": (184, 116), "size": 4, "color": RED},
{"label": "button_zl", "pos": (134, 42), "size": 12, "color": RED},
{"label": "button_zr", "pos": (188, 42), "size": 12, "color": RED},
{"label": "button_lshoulder", "pos": (58, 44), "size": 12, "color": RED},
{"label": "button_rshoulder", "pos": (259, 44), "size": 12, "color": RED},
]
overlays = []
for spot in button_spots:
b = Circle(x0=spot["pos"][0], y0=spot["pos"][1], r=spot["size"], fill=spot["color"])
splash.append(b)
overlays.append(b)
texts = [
{"label": "l_x_text", "text": "L_JOY_X: 00", "x": 6, "y": 220, "color": BLACK},
{"label": "l_y_text", "text": "L_JOY_Y: 00", "x": 88, "y": 220, "color": BLACK},
{"label": "r_x_text", "text": "R_JOY_X: 00", "x": 173, "y": 220, "color": BLACK},
{"label": "r_y_text", "text": "R_JOY_X: 00", "x": 248, "y": 220, "color": BLACK},
{"label": "ls_text", "text": "L_PRESSURE: 00", "x": 10, "y": 11, "color": BLACK},
{"label": "rs_text", "text": "R_PRESSURE: 00", "x": 220, "y": 11, "color": BLACK},
]
analog_text = []
for text in texts:
t = label.Label(
terminalio.FONT,
text=text["text"],
color=text["color"],
x=text["x"],
y=text["y"],
)
splash.append(t)
analog_text.append(t)
last_l_x = 0
last_r_x = 0
last_l_y = 0
last_r_y = 0
last_r_press = 0
last_l_press = 0
while True:
l_x, l_y = ctrl_pad.joystick_l
mapped_l_x = simpleio.map_range(l_x, 7, 58, -50, 50)
mapped_l_y = simpleio.map_range(l_y, 7, 58, -50, 50)
r_x, r_y = ctrl_pad.joystick_r
mapped_r_x = simpleio.map_range(r_x, 2, 26, -50, 50)
mapped_r_y = simpleio.map_range(r_y, 3, 28, -50, 50)
left_pressure = ctrl_pad.l_shoulder.LEFT_FORCE
right_pressure = ctrl_pad.r_shoulder.RIGHT_FORCE
if last_l_x != mapped_l_x:
analog_text[0].text = "L_JOY_X: %d" % mapped_l_x
last_l_x = mapped_l_x
if last_l_y != mapped_l_y:
analog_text[1].text = "L_JOY_Y: %d" % mapped_l_y
last_l_y = mapped_l_y
if last_r_x != mapped_r_x:
analog_text[2].text = "R_JOY_X: %d" % mapped_r_x
last_r_x = mapped_r_x
if last_r_y != mapped_r_y:
analog_text[3].text = "R_JOY_Y: %d" % mapped_r_y
last_r_y = mapped_r_y
if last_r_press != right_pressure:
analog_text[4].text = "R_PRESSURE: %d" % right_pressure
last_r_press = right_pressure
if last_l_press != left_pressure:
analog_text[5].text = "L_PRESSURE: %d" % left_pressure
last_l_press = left_pressure
if ctrl_pad.d_pad.UP:
overlays[0].fill = RED
else:
overlays[0].fill = BLACK
if ctrl_pad.d_pad.DOWN:
overlays[1].fill = RED
else:
overlays[1].fill = BLACK
if ctrl_pad.d_pad.LEFT:
overlays[2].fill = RED
else:
overlays[2].fill = BLACK
if ctrl_pad.d_pad.RIGHT:
overlays[3].fill = RED
else:
overlays[3].fill = BLACK
if ctrl_pad.buttons.A:
overlays[4].fill = RED
else:
overlays[4].fill = BLACK
if ctrl_pad.buttons.B:
overlays[5].fill = RED
else:
overlays[5].fill = BLACK
if ctrl_pad.buttons.X:
overlays[6].fill = RED
else:
overlays[6].fill = BLACK
if ctrl_pad.buttons.Y:
overlays[7].fill = RED
else:
overlays[7].fill = BLACK
if ctrl_pad.buttons.SELECT:
overlays[8].fill = RED
else:
overlays[8].fill = BLACK
if ctrl_pad.buttons.HOME:
overlays[9].fill = RED
else:
overlays[9].fill = BLACK
if ctrl_pad.buttons.START:
overlays[10].fill = RED
else:
overlays[10].fill = BLACK
if ctrl_pad.buttons.ZL:
overlays[11].fill = RED
else:
overlays[11].fill = BLACK
if ctrl_pad.buttons.ZR:
overlays[12].fill = RED
else:
overlays[12].fill = BLACK
if ctrl_pad.buttons.L:
overlays[13].fill = RED
else:
overlays[13].fill = BLACK
if ctrl_pad.buttons.R:
overlays[14].fill = RED
else:
overlays[14].fill = BLACK
As you press the buttons on the controller, you'll see red circles appear on the picture of the controller. The x and y coordinates for each of the joysticks, as well as the force reading from the shoulder buttons (if applicable) are also displayed as text on the screen.
Page last edited January 22, 2025
Text editor powered by tinymce.