Week 10
Creating a Desktop Application
I’ve basically already completed this assignment during week 6, so I’ve decided to make something smaller but with the same idea. I had a snake sketch in C++ left over, so the idea was again to make snake that will be controlled by a rotary encoder. I have some experience in Pygame, so I used that. This time the Arduino didn’t work for me, so I’ve used the ESP32 board.
Connecting the Encoder
Scheme for connecting Keyes KY-040 Rotary Encoder to ESP32
Here you connect:
- (+) -> (5V) or (3V)
- (GND) -> (GND)
- CLK -> GPIO 18
- DT -> GPIO 19
- SW -> GPIO 21
And here’s the code that will print the data to the serial port, adjust the port name and the baud rate to your own board.
#define CLK 18
#define DT 19
#define SW 21
volatile int counter = 0;
int currentStateCLK;
int lastStateCLK;
int currentStateSW;
int lastStateSW;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50; // increase if the output flickers
void IRAM_ATTR handleEncoder() {
// Read the current state of CLK
currentStateCLK = digitalRead(CLK);
if (currentStateCLK != lastStateCLK) {
if (digitalRead(DT) != currentStateCLK) {
counter++;
} else {
// The encoder is rotating counterclockwise
counter--;
}
}
// Save the current state of CLK
lastStateCLK = currentStateCLK;
}
void IRAM_ATTR handleSwitch() {
unsigned long currentTime = millis();
// Check if the debounce delay has passed
if ((currentTime - lastDebounceTime) > debounceDelay) {
// Read the current state of SW
currentStateSW = digitalRead(SW);
if (currentStateSW != lastStateSW) {
if (currentStateSW == LOW) {
Serial.println("Button pressed");
}
// Save the current state of SW
lastStateSW = currentStateSW;
}
// Update the debounce time
lastDebounceTime = currentTime;
}
}
void setup() {
// Set encoder pins as inputs
pinMode(CLK, INPUT);
pinMode(DT, INPUT);
pinMode(SW, INPUT_PULLUP);
// Attach interrupt service routines to the encoder pins
attachInterrupt(digitalPinToInterrupt(CLK), handleEncoder, CHANGE);
attachInterrupt(digitalPinToInterrupt(SW), handleSwitch, CHANGE);
// Initialize the serial monitor
Serial.begin(115200);
// Read the initial state of CLK and SW
lastStateCLK = digitalRead(CLK);
lastStateSW = digitalRead(SW);
}
void loop() {
// Print the counter value
Serial.println(counter);
// Small delay to avoid overwhelming the serial output
delay(100);
}
Code to print the encoders position and presses to the serial port
Game Code
The code for the game itself is very large, so I will just post the file here:
To run it, just follow the instructions in the README file.
Demo
The resulting game runs great and plays well. It has a list of settings you can change in the snake.py file. I probably could have made a separate button in the menu for settings, but that’s too much for this project. It’s really fun, even considering that there aren’t many gameplay mechanics in it.