/*
Arduino | general-help
ecz. — 1/13/25 at 12:50 PM
heres my idea right
Interactive potentiometer game.
The tilt switch controls the status of the entire Arduino,
it turns on or off the game. The potentiometer decides the servo's
position, and the push button is used to score a point and turn off
an LED. The game will function as one of 4 LEDs will light up
randomly and we need to position the servo using the potentiometer
to point towards the LED that is lit up. When it is positioned
correctly we will press the push button, it will play a sound and
will display 1 representing a point on the LCD. The score will
increment by one every time you score a successful point.
If the button is pushed when the servo isn't pointing toward the
lit-up LED, Incorrect will be displayed on the same LCD, and the score
will reset as a sign of losing the game.
Use arrays to simplify the code
"// Tilt switch to turn the game on/off"
Do you mean reset? A simple change...
Changed game logic a bit. - Anon
*/
#include <Servo.h>
#include <LiquidCrystal.h>
const int MAX_SCORE = 10;
const int POS_THRESHOLD = 10; // allowable position error
// servo target position values
const int TARGET_POSITIONS[] = {60, 75, 105, 120};
// pin constants for the parallel LCD
const int RS = 12, EN = 11, D4 = 10, D5 = 9, D6 = 8, D7 = 7;
// other pin constants
const int SERVO_PIN = 3;
const int GAME_BTN_PIN = 4; // Push button to score a point
const int BUZZER_PIN = 5; // Buzzer to play sound on successful point
const int TILT_BTN_PIN = 6; // Tilt switch to turn the game on/off
const int GAME_POT_PIN = A5; // servo position
const int LED_PINS[] = {A0, A1, A2, A3};
// Create servo object
Servo pointerServo;
// create a parallel LCD object called "lcd"
LiquidCrystal lcd(RS, EN, D4, D5, D6, D7);
// global variables
bool gameMode = false; // running or not
int score = 0; // Score counter
int currentLed = 0; // Current lit LED
int oldGameState = HIGH; // PULLUP, pin idles HIGH
int oldTiltState = HIGH; // PULLUP, pin idles HIGH
// function returns true if game switch is pressed
bool checkGameButton() {
bool isPressed = false;
int gameState = digitalRead(GAME_BTN_PIN);
if (gameState != oldGameState) {
oldGameState = gameState;
if (gameState == LOW) {
isPressed = true;
Serial.println("Game pressed");
}
delay(20); // debounce
}
return isPressed;
}
// function returns true if tilt switch is activated
bool checkTiltSwitch() {
bool isPressed = false;
int tiltState = digitalRead(TILT_BTN_PIN);
if (tiltState != oldTiltState) {
oldTiltState = tiltState;
if (tiltState == LOW) {
isPressed = true;
Serial.println("Tilt pressed");
}
delay(20); // debounce
}
return isPressed;
}
// start a new game
void doStart() {
score = 0;
resetLeds();
gameMode = false;
pointerServo.write(90);
lcd.clear();
lcd.setCursor(6, 0);
lcd.print("TILT");
lcd.setCursor(4, 1);
lcd.print("to start");
Serial.println("Game ready");
}
void playSound(bool winLose) {
if (winLose) {
tone(BUZZER_PIN, 220);
delay(250);
tone(BUZZER_PIN, 440);
delay(250);
tone(BUZZER_PIN, 880);
delay(250);
} else {
tone(BUZZER_PIN, 880);
delay(250);
tone(BUZZER_PIN, 440);
delay(250);
tone(BUZZER_PIN, 220);
delay(250);
}
noTone(BUZZER_PIN);
}
// Function to reset all LEDs
void resetLeds() {
for (int i = 0; i < 4; i++) {
digitalWrite(LED_PINS[i], LOW);
}
}
// Function to pick random LED / position
void setRandom() {
// turn all LEDs off
resetLeds();
delay(500);
// light up a random LED
currentLed = (int)random(0, 4);
digitalWrite(LED_PINS[currentLed], HIGH);
}
// function to show just the score
void showScore(int value) {
char buffer[16];
snprintf(buffer, 16, "Score: %2d ", value);
lcd.setCursor(3, 1);
lcd.print(buffer);
}
void setup() {
Serial.begin(115200);
lcd.begin(16, 2);
// initialize pins
pinMode(TILT_BTN_PIN, INPUT_PULLUP);
pinMode(GAME_BTN_PIN, INPUT_PULLUP);
pinMode(BUZZER_PIN, OUTPUT);
for (int i = 0; i < 4; i++) {
pinMode(LED_PINS[i], OUTPUT);
}
// initialize servo
pointerServo.attach(SERVO_PIN);
pointerServo.write(90);
// initialize random number generator
randomSeed(analogRead(A4));
// splash screen
lcd.setCursor(3, 0);
lcd.print("Servo Game");
lcd.setCursor(6, 1);
lcd.print("V1.0");
delay(2000); // show splash for 2 seconds
lcd.clear();
// show instructions
doStart();
}
void loop() {
// check tilt sensor if game not already running
if (checkTiltSwitch() && !gameMode) {
gameMode = true;
setRandom();
lcd.clear();
lcd.setCursor(4, 0);
lcd.print("Game ON!");
showScore(score);
Serial.println("Game running");
}
// if game mode was set...
if (gameMode) {
// Game is running, get new potentiometer value
// Read potentiometer and map to servo range
int mapServoPos = map(analogRead(GAME_POT_PIN), 0, 1023, 50, 130);
// Move servo to the mapped position
pointerServo.write(mapServoPos);
// check game button
if (checkGameButton()) {
// uncomment 4 lines below to see values
Serial.print("Current servo position:");
Serial.println(mapServoPos);
Serial.print("Target position:");
Serial.println(TARGET_POSITIONS[currentLed]);
// check if current position is close to target position
if ((mapServoPos >= TARGET_POSITIONS[currentLed] - POS_THRESHOLD) &&
(mapServoPos <= TARGET_POSITIONS[currentLed] + POS_THRESHOLD)) {
// winner
Serial.println("Winner!");
score++;
showScore(score);
playSound(true);
if (score >= MAX_SCORE) {
lcd.setCursor(4, 0);
lcd.print("WINNER! ");
delay(2000);
doStart();
} else {
delay(2000);
setRandom();
}
} else {
// loser
Serial.println("Loser!");
showScore(0);
playSound(false);
lcd.setCursor(4, 0);
lcd.print("Loser...");
delay(2000);
doStart();
}
}
}
}
Tilt
Game
ecz. Pointing Game
Created on
AnonEngineering 1/13/25