Submind YouTube summaries
Thumbnail for John Park's CircuitPython Parsec: Seesaw Gamepad QT

John Park's CircuitPython Parsec: Seesaw Gamepad QT

Watch on YouTube

Video summary

In this episode of CircuitPython Parsec, the focus is on integrating a Seesaw Gamepad into a CircuitPython project to efficiently read both analog joystick data and digital button inputs. The gamepad features a PCB with six buttons and an analog thumbstick that functions essentially as two potentiometers for X and Y axes. Rather than requiring complex wiring with multiple individual connections, the device utilizes a simple STEMMA QT cable connected via I2C, making it easy to interface with boards like the Metro M7. This setup allows the microcontroller to quickly capture real-time data, displaying analog values ranging from 0 to 1023 for the joystick and simultaneously monitoring the states of all six buttons, including directional keys and action buttons like start and select. The core functionality is achieved through the Adafruit Seesaw library, which leverages the onboard coprocessor to handle input/output checking without burdening the main processor. The code establishes an I2C bus connection to the Seesaw chip and configures specific pins for bulk reading, ensuring that all six button states are captured simultaneously as a single bit mask. Additionally, the analog sensors are configured with a "slop" factor of three, meaning the system only registers a change in joystick position if the value shifts by at least that amount, which helps filter out minor electrical noise or jitter. This efficient communication method allows for rapid data transmission over I2C, containing all necessary information about button presses and analog adjustments in compact messages. To process this incoming data, the script initializes lists to map pin numbers to their corresponding button names, enabling a user-friendly readout that displays readable labels instead of raw pin indices. Within the main loop, the code reads the analog values from specific pins for the X and Y axes, inverting the logic so that 0 represents one extreme of the stick and 1023 the other. The program then compares current readings against previously stored values to detect changes; if the joystick position shifts significantly or any button state toggles, the system updates the display with the new thumbstick coordinates and the list of currently pressed buttons. By storing the last known states for both analog positions and button inputs, the code ensures that text is only printed when actual changes occur, preventing screen clutter from constant noise. This approach simplifies the process of reading gamepad states within a CircuitPython environment, demonstrating how the Seesaw board can serve as a versatile input device for various projects. Ultimately, this tutorial provides a clear and practical method for developers to implement responsive game controls using I2C communication, highlighting the efficiency of the Seesaw architecture in handling multiple inputs with minimal code complexity.
Read the full video transcript
For the Circuit Python Parsec today, I wanted to talk about using the Seesaw Gamepad inside of Circuit Python to read analog joystick and digital buttons. So, you can see what I'm talking about right here. This is a little Gamepad PCB that will more put together that has six buttons on it and it has a little thumb stick, which is essentially two potentiometers for X and for X to the side and Y up down. However, simplified wiring it's not a series of eight or 10 things plugged into the board. It's just I squared C. So, it uses little STEMMA QT cable. You can also break it out out down across the bottom. I have it plugged into a Metro M7 here just for fun. Why not? The M7 doesn't get enough love. And the way this works, if you look in my REPL, you're going to see I'm recording the XY values of 0 to 1023 and 0 to 1023 and a mix of those. And then if I press buttons, we've got the B button, the A button, the X, the Y, all four of those as well as start and select. So, I can press any and all of those buttons and you can see I can read them really, really quickly. The way that we do this is in Circuit Python. Let me make this a little bigger. Oops. Like that. In Circuit Python, I am importing this library, Adafruit Seesaw. Seesaw allows us to use the little coprocessor on here to do all of the IO checking to see when buttons have been pressed or when the analog sensors are are adjusted or the analog voltages are adjusted. And then send out little contained messages over I squared C very quickly that contain all of that info. It's actually three little interactions. We get all of the buttons as a bit mask. So, hey, any button state, we're going to get them all. And then what's Y up to and what's X up to on the analog. Uh to do this, I'm setting up a little list here of the button numbers or pin numbers on the seesaw chip, as well as their button names, so that I can print those out. And then I'm creating this button mask that'll return the state of all six buttons uh all at once anytime I press one or or more of them. And then I'm setting up the I2C bus to connect creating the seesaw object as seesaw I2C bus and the address that it's on. Uh I think this one you might be able to use multiple of them with a address jumper. We have probably do like four of them. There's two address jumpers there. And then I am setting the pin mode bulk, and that's what says I'm going to check all six of those uh button pins, and this is as a input pull-up. They're all input pull-ups. Then I'm doing a little bit of setup for uh state on the analog sensors, so that we only update when it's changed by enough by uh a value of three is just the little slop factor that I have on there. And then for printing, we have a couple of lines that we're going to fill, and that's uh that's these initially blank lines here that get filled by the print. Uh in the main loop, I'm saying X is equal to 1023 minus the seesaw analog read on pin 14, and Y is 1023 minus the seesaw analog read on 15. And then the buttons are this bulk read. I say that set of of pins, and it grabs them all. Uh then in a uh another list I create called pressed, I have the names of the pins uh for the names of the buttons, and that's what gives me a nice readout down at the bottom here, uh where we see, rather than pin numbers, we get the pin names. Uh and then here's where we check to see if anything changes. So, we're only going to print new text if something has changed, uh and that is if the uh essentially X is different enough from the last read uh by three or more and same with the Y or if any of the pressed states have changed. When that happens, we're then going to grab this joy line and construct the thumb stick X equals whatever that value was and the thumb stick Y from whatever that value was and then the buttons line is any of those buttons state pressed or not. And then the state is set for last X and last Y and last pressed. So that's how we can very simply read the state of any of the buttons on a little seesaw board in this case the game pad cutie over I squared C inside of circuit python. And that's your circuit python parsec.