Raspberry Pi Pico
LED Button Keypad

A nicer way to make a macropad is to use some LED buttons. For this, I used a circuit that I have used before. The button pins are connected to GND and to pins GP2 to GP5. The LEDs are connected to GND via a 220ohm resistor. The positive pins are connected to pins GP6 to GP9. This is a slightly more complex than on the previous page and lets you have an indicator light for each button.

Pico Circuit

This Fritzing shows how you might set this up with the separate components.

Pico Circuit

When the first button is pressed, text is written to the screen with some timing. I did this because one of the things I use Macropads for is to perform timed sequences of actions in games. For example, in the game No Man's Sky, there is a set of techniques called 'glitch building' which work by timing button presses to perfection. Having a macro makes it easier to do this reliably. What you see here has nothing to do with the game but shows how you might easily time sequences of button presses.

The second button triggers some key presses, pretty much at once, with no precise timing. The last two buttons are for adjusting the volume and show how you would do multimedia stuff using a custom button pad.

You need the library on your Pico for this,

import board 
from time import sleep 
from digitalio import DigitalInOut, Pull, Direction 
import usb_hid 
 
from adafruit_hid.keyboard import Keyboard 
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS 
from adafruit_hid.keycode import Keycode 
from adafruit_hid.consumer_control import ConsumerControl 
from adafruit_hid.consumer_control_code import ConsumerControlCode 
 
kbd = Keyboard(usb_hid.devices) 
layout = KeyboardLayoutUS(kbd) 
cc = ConsumerControl(usb_hid.devices) 
 
# function to read buttons into a binary pattern, 1 for pressed 
def read_btns(btn_list): 
    result = 0 
    for i, b in enumerate(btn_list): 
        result +=  (b.value^1)<<i 
    return result 
 
# tells if a button is pressed 
def pressed(pattern, b): 
    return pattern>>b & 1 
 
# sets leds based on a binary value 
def set_leds(led_list, pattern): 
    for i, l in enumerate(led_list): 
        l.value = pattern >> i & 1 
 
# set up button pins 
btn_pins = [board.GP2, board.GP3, board.GP4, board.GP5] 
btns = [DigitalInOut(p) for p in btn_pins] 
 
# set up as buttons 
for b in btns: 
    b.switch_to_input(pull = Pull.UP) 
 
# set up LED pins 
led_pins = [board.GP6, board.GP7, board.GP8, board.GP9] 
leds = [DigitalInOut(p) for p in led_pins] 
 
# set direction 
for l in leds: 
    l.direction = Direction.OUTPUT 
     
previous = 0 
while True: 
    reading = read_btns(btns) 
    set_leds(leds, reading) 
    if reading!=previous: 
        if pressed(reading, 0): 
            # writing text and timing 
            layout.write("A message.\n") 
            sleep(1) 
            for c in "This is a message for you.": 
                layout.write(c) 
                sleep(0.2) 
            layout.write("\n") 
        elif pressed(reading,1): 
            # send a load of key strokes 
            kbd.send(*[Keycode.SHIFT, Keycode.M, Keycode.ENTER]) 
        elif pressed(reading,2): 
            cc.send(ConsumerControlCode.VOLUME_INCREMENT) 
        elif pressed(reading,3): 
            cc.send(ConsumerControlCode.VOLUME_DECREMENT) 
        else: 
            sleep(0.1) 
    previous = reading 
    sleep(0.01) 

No Man's Sky Glitch Building Macropad

If you have been playing No Man's Sky for long enough and have watched a few videos or live streams about building in the game, you will have come across the term 'glitch building'. If you don't already know the term or the game then glitch building is about trying to extend the capabilities of the in-game build system beyond what appears to have been intended. This is done by pressing combinations of keys in rapid succession. This allows you to build in ways that the developers may not have intended but are not actively seeking to prevent.

Some players already use macros to help them carry out the key combinations more reliably than is otherwise possible. They tend to use the macro buttons on their mice and keyboards. I use a laptop for playing the game and don't have the macro keys. I like to have a single button press to execute the macro and don't want to have to set a shortcut combo that might clash with software I use. For that reason, I use some mechanical keys on a breadboard with an Adafruit Itsy Bitsy. So far, I have used an Arduino program. I thought I'd see how well the code translates into CircuitPython using the LED button layout shown above.

The following code shows the 3 glitch-building macros I use. The second button is used for a right adjacency glitch. The third button is used for all glitches involving wires (blender, reverse wire etc.). The first button is used for storing items in the cache when you are doing glitches to resize items or the universal adjacency glitch. I have left the last button unused for the moment.

import board 
from time import sleep 
from digitalio import DigitalInOut, Pull, Direction 
import usb_hid 
 
from adafruit_hid.keyboard import Keyboard 
from adafruit_hid.keycode import Keycode 
from adafruit_hid.mouse import Mouse

kbd = Keyboard(usb_hid.devices) 
m = Mouse(usb_hid.devices)

# function to read buttons into a binary pattern, 1 for pressed 
def read_btns(btn_list): 
    result = 0 
    for i, b in enumerate(btn_list): 
        result +=  (b.value^1)<<i 
    return result 
 
# tells if a button is pressed 
def pressed(pattern, b): 
    return pattern>>b & 1 
 
# sets leds based on a binary value 
def set_leds(led_list, pattern): 
    for i, l in enumerate(led_list): 
        l.value = pattern >> i & 1 
 
# set up button pins 
btn_pins = [board.GP2, board.GP3, board.GP4, board.GP5] 
btns = [DigitalInOut(p) for p in btn_pins] 
 
# set up as buttons 
for b in btns: 
    b.switch_to_input(pull = Pull.UP) 
 
# set up LED pins 
led_pins = [board.GP6, board.GP7, board.GP8, board.GP9] 
leds = [DigitalInOut(p) for p in led_pins] 
 
# set direction 
for l in leds: 
    l.direction = Direction.OUTPUT 
     
previous = 0 
while True: 
    reading = read_btns(btns) 
    set_leds(leds, reading) 
    if reading!=previous: 
        if pressed(reading, 0): 
            # cache a part
            kbd.press(Keycode.C)
            kbd.press(Keycode.Q)
            sleep(0.017)
            kbd.release_all()
        elif pressed(reading,1): 
            # adjacency glitch
            kbd.press(Keycode.E)
            m.press(Mouse.LEFT_BUTTON)
            sleep(0.017)
            kbd.release_all()
            m.release_all()
        elif pressed(reading,2):
            # wire glitch
            kbd.press(Keycode.Q)
            m.press(Mouse.LEFT_BUTTON)
            sleep(0.017)
            kbd.release_all()
            m.release_all()            
        elif pressed(reading,3): 
            #spare button
            print("Button 4")
        else: 
            sleep(0.1) 
    previous = reading 

This is not quite perfect but is so much more reliable than I can do with a keyboard and mouse or a gamepad. It works as well with CircuitPython as it does with compiled Arduino code, which is pleasing. The wire glitch is the least reliable of the 3 options but still so much better than I can do without the macro. Messing with the delays might make a difference but, to be honest, this is good enough to build with. Maybe one day I will solder the circuit to some nice protoboard or place inside a decent enclosure.