This week, I have developed a gyroscopic controller for different types of games. The working principle is very simple. I am using a GY-521 gyroscope, which I interface using an Arduino Leonardo. The code implements virtual keyboard, which triggers a spacebar/left click, when a jump is detected.
#include
GY_512 device = GY_512();
float xx1 = 0;
float yx1 = 0;
float xy1 = 0;
float yy1 = 0;
float xz1 = 0;
float yz1 = 0;
void setup() {
Serial.begin(115200);
device.sensor_init();
Serial.println("Sensor initialized!");
}
void loop() {
float acc_x_raw = device.get_gyro_x();
float acc_y_raw = device.get_gyro_y();
float acc_z_raw = device.get_gyro_z();
float acc_x = 0.969*yx1 + 0.0155*acc_x_raw + 0.0155*xx1;
float acc_y = 0.969*yy1 + 0.0155*acc_y_raw + 0.0155*xy1;
float acc_z = 0.969*yz1 + 0.0155*acc_z_raw + 0.0155*xz1;
xx1= acc_x_raw;
yx1 = acc_x;
xy1= acc_y_raw;
yy1 = acc_y;
xz1= acc_z_raw;
yz1 = acc_z;
if (acc_x >= 8) {
// delay(500);
Serial.print("JUMP!");
xx1 = 0;
yx1 = 0;
acc_x = 0;
acc_x_raw = 0;
delay(100);
}
delay(50);
}
And of course, the accompanying Python code:
import serial
import time
import pyautogui
# Open the serial port
ser = serial.Serial('COM5', 115200, timeout=1)
while True:
if ser.in_waiting:
# Read the line from serial and decode it
line = ser.readline().decode('utf-8', errors='ignore').strip()
# Check if the string "JUMP!" is in the incoming line
if "JUMP!" in line:
print("Pressed SPACEBAR!")
pyautogui.press('space')
# pyautogui.click()
time.sleep(0.001)
This code has been deployed on Arduino nano, which does not support HID (Hardware Interface Device), making it unable to emulate a keyboard. The implemented workaround it sending the communication via serial to Python, where I have used PyAutoGUI to generate the necessary commands. A huge inconvenience roughly once second delay between the physical jump and the inputted keystroke.
I have used the RDV_GY512 library, which implements the readout from the sensor. One caveat is a very noisy output, making it much more difficult to detect the jump. This is remedied by the implemented time-domain low-pass filter, significantly smoothing the output signal.
The improved version of the code runs on Arduino Leonardo, which has the needed HID interface.
I have made a game called The Adventures of Ludovit Stur, which I’ve wanted to use the controller for. The game is inspired by the infamous Flappy Bird, but with a twist in Slovak history. The programming language used is a bit more archaic and is call the AppGameKit. It is a pain programming language primarily used for the development of 2D games.
Unfortunately, I could not make the HID (Human Interface Device) work on Arduino boards. Luckily, I had some Raspberry Pi Pico 2020s lying around, which can emulate a keyboard using the Arduino-Pico core by Earle Philhower. The sketch was rather simple, as I sent a keyboard command when either the GP27 or GP26 was high. Using external pulldown resistors ensured no false presses due to induced voltage. I have found debouncing not to be a problem in this case.
#include "Keyboard.h"
const int pinA = 27; // GP27
const int pinD = 26; // GP26
void setup() {
pinMode(pinA, INPUT);
pinMode(pinD, INPUT);
Keyboard.begin();
}
void loop() {
if (digitalRead(pinA) == HIGH) {
Keyboard.press('a');
} else {
Keyboard.release('a');
}
if (digitalRead(pinD) == HIGH) {
Keyboard.press('d');
} else {
Keyboard.release('d');
}
delay(10); // Debounce and avoid overloading host
}
The game was again written in AppGameKit. It is an engine I have experience with, and I find it very pleasing to work with when developing 2D games. A demo of the game can be seen in the YouTube video below. It is a simple game consisting of a rocket, which moves at the bottom of the screen. Falling coins spawn every 1.5 seconds, and if they are caught by the rocket, the score increases by one. If they fall to the bottom of the screen, the score is decreased. I have made all of the sprites in the game by myself.