Create something with your extra components and an ATtiny85 by building a simple LED Chaser game.
Introduction
You may have scrap or extra components on your workbench (such as tact switches, resistors, and LEDs) just lying around. Why not make them useful and create something interesting? Here, you’ll learn how to make a simple do-it-yourself, push-button LED chaser game.
A Simple ATtiny85 Game – An LED Chaser Game
The LED Chaser game is a game where you chase the turning on of LEDs through button presses. Since an Attiny85 has limited I/O pins (5 – 6 I/O pins), you may use 2 LEDs and 2 push buttons for this. Add a 5V buzzer for sound effects. The LEDs turn on times alternate with each other, challenging the player.
The Actual Circuit
The actual circuit is put on a breadboard with connecting wires. To program the ATtiny85, you need an external programmer. You can program the Attiny85 using an Arduino UNO or just a modular programming tool (such as a USBTinyISP), as is used here.
Test Code
If you optionally want to test your setup quickly, you can use the code below. This code validates your hardware.
#define but_1 PB3
#define but_2 PB4
#define led_1 PB2
#define led_2 PB1
#define buzzer PB0
void setup() {
// put your setup code here, to run once:
pinMode(but_1, INPUT_PULLUP);
pinMode(but_2, INPUT_PULLUP);
pinMode(led_1, OUTPUT);
pinMode(led_2, OUTPUT);
pinMode(buzzer, OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
if(digitalRead(but_1) == 0)
{
digitalWrite(led_1, HIGH);
digitalWrite(buzzer, HIGH);
delay(500);
}
if(digitalRead(but_2) == 0)
{
digitalWrite(led_2, HIGH);
digitalWrite(buzzer, HIGH);
delay(500);
}
digitalWrite(led_1, LOW);
digitalWrite(led_2, LOW);
digitalWrite(buzzer, LOW);
}
Insert Code Here
Writing Actual Code for the Game
To make code quickly, leverage the use of AI tools instead of pondering on code logic. On an AI prompt such as ChatGPT, input:
Make a code for attiny85 that chases the LED state of 2 LEDs using two push buttons. Sound is output to a buzzer if the LED state is missed.
You’ll then have an answer, something like:
Here’s a complete and responsive ATtiny85 sketch for a 2-LED chase game using two buttons and a buzzer for feedback when the user presses the wrong button. It’s designed for non-blocking timing using millis() and works well for embedded game logic.
🧠Game Logic Overview
- Two LEDs alternate every 1 second.
- Two buttons correspond to each LED.
- If the user presses the correct button while its LED is ON → no sound.
- If the user presses the wrong button → buzzer sounds.
- Uses internal pull-ups and debounced input.
🔌 ATtiny85 Pin Mapping
Function | Pin | Port | Arduino Alias |
LED 1 | 6 | PB1 | 1 |
LED 2 | 7 | PB2 | 2 |
Button 1 | 2 | PB3 | 3 |
Button 2 | 3 | PB4 | 4 |
Buzzer | 5 | PB0 | 0 |
Here is the code generated by ChatGPT:
const byte led1 = 1; // PB1
const byte led2 = 2; // PB2
const byte button1 = 3; // PB3
const byte button2 = 4; // PB4
const byte buzzer = 0; // PB0
unsigned long previousMillis = 0;
const unsigned long interval = 1000;
bool ledState = false; // false = LED1 ON, true = LED2 ON
void setup() {
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(buzzer, OUTPUT);
pinMode(button1, INPUT_PULLUP);
pinMode(button2, INPUT_PULLUP);
digitalWrite(led1, LOW);
digitalWrite(led2, LOW);
digitalWrite(buzzer, LOW);
}
void loop() {
unsigned long currentMillis = millis();
// LED alternation
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
ledState = !ledState;
digitalWrite(led1, !ledState);
digitalWrite(led2, ledState);
}
// Button check
if (digitalRead(button1) == LOW) {
if (!ledState) {
// Correct button for LED1
} else {
buzzError();
}
delay(200); // Simple debounce
}
if (digitalRead(button2) == LOW) {
if (ledState) {
// Correct button for LED2
} else {
buzzError();
}
delay(200); // Simple debounce
}
}
void buzzError() {
digitalWrite(buzzer, HIGH);
delay(150);
digitalWrite(buzzer, LOW);
}
Note that you may need to modify some entries to make the LED ports align with your button ports, such as:
const byte led1 = 1; // PB1
const byte led2 = 2; // PB2
const byte button1 = 4; // PB3
const byte button2 = 3; // PB4
const byte buzzer = 0; // PB0
Now that you have the code, download it to your hardware by uploading using your programmer. You can review programming for ATtiny85 through Programming an ATtiny85 using an Arduino. After that, test your circuit, as seen in the video below.
Making the Game More Challenging
The game seems monotonous with constant LED blinking. With this, why not make it more challenging? Decreasing the LED blink rate in time should accomplish this.
You don’t need to ponder on code logic again. Simply ask AI (ChatGPT) how you can do this.
Now make the LED interval less and less over time so that the game can be challenging.
Depending on your AI chatbot and your previous history, your chat should output something like:
Here’s a refined version of your ATtiny85 LED chase game that gets progressively harder: the LED alternation interval decreases over time, making it more challenging to press the correct button in sync. If the player presses the wrong button, the buzzer sounds.
🧠Game Enhancements
- Starts with a 1000 ms interval.
- Decreases by 50 ms every 5 seconds until it reaches 300 ms.
- Uses millis() for non-blocking timing.
- Buttons are debounced and checked against current LED state.
- Buzzer gives immediate feedback on mistakes.
🔌 ATtiny85 Pin Mapping
Function | Pin | Port | Arduino Alias |
LED 1 | 6 | PB1 | 1 |
LED 2 | 7 | PB2 | 2 |
Button 1 | 2 | PB3 | 3 |
Button 2 | 3 | PB4 | 4 |
Buzzer | 5 | PB0 | 0 |
Here is the code generated by ChatGPT:
const byte led1 = 1; // PB1
const byte led2 = 2; // PB2
const byte button1 = 3; // PB3
const byte button2 = 4; // PB4
const byte buzzer = 0; // PB0
unsigned long previousMillis = 0;
unsigned long interval = 1000; // Start at 1 second
const unsigned long minInterval = 300;
const unsigned long intervalStep = 50;
const unsigned long intervalDecayTime = 5000; // Every 5 seconds
unsigned long lastDecayMillis = 0;
bool ledState = false; // false = LED1 ON, true = LED2 ON
void setup() {
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(buzzer, OUTPUT);
pinMode(button1, INPUT_PULLUP);
pinMode(button2, INPUT_PULLUP);
digitalWrite(led1, LOW);
digitalWrite(led2, LOW);
digitalWrite(buzzer, LOW);
}
void loop() {
unsigned long currentMillis = millis();
// LED alternation
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
ledState = !ledState;
digitalWrite(led1, !ledState);
digitalWrite(led2, ledState);
}
// Interval decay
if (currentMillis - lastDecayMillis >= intervalDecayTime && interval > minInterval) {
interval -= intervalStep;
lastDecayMillis = currentMillis;
}
// Button check
if (digitalRead(button1) == LOW) {
if (!ledState) {
// Correct button for LED1
} else {
buzzError();
}
delay(150); // Simple debounce
}
if (digitalRead(button2) == LOW) {
if (ledState) {
// Correct button for LED2
} else {
buzzError();
}
delay(150); // Simple debounce
}
}
void buzzError() {
digitalWrite(buzzer, HIGH);
delay(100);
digitalWrite(buzzer, LOW);
}
The same as before, you may need to modify some entries to make the LED ports align with your button ports, such as:
const byte led1 = 1; // PB1
const byte led2 = 2; // PB2
const byte button1 = 4; // PB3
const byte button2 = 3; // PB4
const byte buzzer = 0; // PB0
Now download the code and test your LED chaser game (as seen in the video clip below). Notice the game now decreases LED blink time (of about 50ms) every 5 seconds. This makes the game more challenging. Enjoy and create other improvements such as an entertaining ending sequence!!
SHOP THIS PROJECT
-
Digital LCD Thermometer Temperature Gauge with Probe
$15.95Original price was: $15.95.$14.95Current price is: $14.95. Read more