Created
June 4, 2020 06:46
-
-
Save benwtr/f6467d4fc0508fa5b010e12fd1c8e734 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Air Hockey Score Board | |
* | |
* This project added electronic score keeping to a little tabletop air hockey game | |
* | |
* I made light blocking sensors for the goals using pairs of infrared LEDs, one | |
* emitting light, the other acting as a sensor, amplified through an NPN transistor | |
* | |
* The scoreboard itself contains a small speaker, a 4 digit LED display and a push | |
* button attached to the arduino's reset pin. The display is a TM1637 which is an | |
* i2c device. We use a library that makes it easy so we can just print strings to it. | |
* | |
*/ | |
#include <TM1637.h> | |
// 4 digit LED display | |
TM1637 tm(A5, A4); | |
// I heard somewhere, in the official rules of air hockey, the winner is the | |
// first to reach 7 points.. | |
int max_points = 9; | |
// copypasta from arduino smoothing example | |
const int numReadings = 100; // tune this for smoothing vs responsiveness | |
int readIndex = 0; | |
int g0_readings[numReadings]; | |
int g0_total = 0; | |
int g0_average = 0; | |
int g0_inputPin = A2; // Goal 0 sensor pin | |
int g1_readings[numReadings]; | |
int g1_total = 0; | |
int g1_average = 0; | |
int g1_inputPin = A3; // Goal 1 sensor pin | |
unsigned int counter = 0; // just an arbitrary int to count how many times we've been through the loop and we don't care if we overflow it | |
bool g0_puck = false; // puck in goal? | |
bool g1_puck = false; | |
bool g0_last_puck = false; // puck state last time through the loop | |
bool g1_last_puck = false; | |
int g0_score = 0; | |
int g1_score = 0; | |
bool warmed_up = false; | |
void setup() { | |
Serial.begin(115200); | |
tm.init(); | |
// tm.setBrightness(0); | |
// initialize all the readings to 0: | |
for (int thisReading = 0; thisReading < numReadings; thisReading++) { | |
g0_readings[thisReading] = 0; | |
g1_readings[thisReading] = 0; | |
} | |
// beep | |
tone(9, 262, 500); | |
// display the score | |
tm.display(String(String(g0_score) + " " + String(g1_score))); | |
} | |
void loop() { | |
// avoid jankyness on boot, might not still be needed | |
if (counter > 1000) { | |
warmed_up = true; | |
} | |
// read the voltage from the goal 0 sensor, 0-5V is represented as 0-1023 | |
g0_total = g0_total - g0_readings[readIndex]; | |
g0_readings[readIndex] = analogRead(g0_inputPin); | |
g0_total = g0_total + g0_readings[readIndex]; | |
// sleep for 1ms between readings for stability | |
delay(1); | |
// read the goal 1 sensor | |
g1_total = g1_total - g1_readings[readIndex]; | |
g1_readings[readIndex] = analogRead(g1_inputPin); | |
g1_total = g1_total + g1_readings[readIndex]; | |
// calculate averages | |
g0_average = g0_total / numReadings; | |
g1_average = g1_total / numReadings; | |
delay(1); | |
readIndex = readIndex + 1; | |
if (readIndex >= numReadings) { | |
readIndex = 0; | |
} | |
// when the puck is in the goal, the average is something like -233, otherwise it is > 300 typically | |
g0_puck = g0_average < 0; | |
g1_puck = g1_average < 0; | |
if (warmed_up) { | |
if (g0_puck != g0_last_puck) { | |
if (g0_puck == true) { | |
g0_score++; | |
tm.display(String(String(g0_score) + " " + String(g1_score))); // display score | |
tone(9, 523, 400); // beep | |
delay(100); // debounce | |
} | |
if (g0_puck == false) { | |
delay(4000); // allow 4 seconds to get the puck out | |
} | |
} | |
if (g1_puck != g1_last_puck) { | |
if (g1_puck == true) { | |
g1_score++; | |
tm.display(String(String(g0_score) + " " + String(g1_score))); // display | |
tone(9, 523, 400); | |
delay(100); // debounce | |
} | |
if (g1_puck == false) { | |
delay(4000); // allow 3 seconds to get the puck out | |
} | |
} | |
} | |
// Serial.print(g0_val); | |
// Serial.print("\t"); | |
// Serial.println(g1_val); | |
// Serial.println(scoreString); | |
// Game over, max points reached | |
if ((g0_score == max_points) || (g1_score == max_points)) { | |
// beep 3 times | |
delay(900); | |
tone(9, 523, 500); | |
delay(1000); | |
tone(9, 523, 500); | |
delay(1000); | |
tone(9, 523, 500); | |
while (true) { | |
// flash the score forever, or until someone hits the reset button | |
tm.display(" "); | |
delay(1000); | |
tm.display(String(String(g0_score) + " " + String(g1_score))); | |
delay(1000); | |
} | |
} | |
counter++; | |
g0_last_puck = g0_puck; | |
g1_last_puck = g1_puck; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment