froetz
Mitglied
Jemand im Bastelthread meinte das sollte auch hier her...
(original hier: https://www.rc-modellbau-portal.de/...-gebastelt-allgemein-ohne-rc.4757/post-183816)
Tipp-Kick-Dash
20200228
in letzter Zeit ist beim Junior Tipp-Kick wieder hoch im Kurs. Um auch mal wieder was mit ihm zu basteln, haben wir uns für eine Tipp-Kick-Anzeige entschieden. Darauf sollen die Tore und die verbleibende Spielzeit zu sehen sein. Also haben wir in der Teilekiste gekramt und einen Arduino Micro gefunden. Dazu noch ein schönes 16x2 LC-Display, das blau hinterleuchtet ist. Kleinkram wie Taster, Kabel und Widerstände hat man ja eh immer zu Hause. Ein erster Softwareprototyp stand recht fix, der zeigte aber erst mal nur eine statische Anzeige um zu sehen, wie das später dann überhaupt wirkt. Beim schreiben des eigentlichen Programms hatte mein Gehirn einen Fehler und ich hab knapp eine Stunde gebraucht bis ich aus "||" endlich "&&" gemacht hab. Ich hab die zwei Pipes irgendwie die ganze Zeit als "UND" gelesen. Auch nach zigfachem gegenlesen und nachprüfen nix falsches gesehen. Irgendwann kam dann das berühmte "Ou mann wie dumm..." und siehe da, macht man es richtig funktioniert es plötzlich.
Aufgebaut hab ich das Teil erst mal auf einem Steckbrett:
Schaltplan:
Und da bewegte Bilder immer toll sind, hier ein Video:
Die LEDs und der Piepser, der den An- und Abpfiff macht kamen erst während des Programmierens dazu. vor dem Anpfiff und nach dem Abpfiff ist eine Änderung der Punkte nicht mehr möglich. passiert während dem Spiel eine "Falscheingabe" kann man einfach weiter auf die entsprechende Taste drücken und korrigieren, da nach 9 Punkten automatisch wieder auf 0 zurückgesetzt wird.
Ein Gehäuse dafür hat der Kurze dann mal mit Bleistift gezeichnet und ich hab es dann mit ihm in Sketchup digitalisiert. Das Gehäuse wird derzeit noch etwas verfeinert und dann gedruckt.
Hier ist das fertige Teil:
von innen:
und komplett:
Im Spoiler ist der komplette Code - ich hoffe ausreichend gut kommentiert.
Fertig!
Wer nachbauen möchte:
(original hier: https://www.rc-modellbau-portal.de/...-gebastelt-allgemein-ohne-rc.4757/post-183816)
Tipp-Kick-Dash
20200228
in letzter Zeit ist beim Junior Tipp-Kick wieder hoch im Kurs. Um auch mal wieder was mit ihm zu basteln, haben wir uns für eine Tipp-Kick-Anzeige entschieden. Darauf sollen die Tore und die verbleibende Spielzeit zu sehen sein. Also haben wir in der Teilekiste gekramt und einen Arduino Micro gefunden. Dazu noch ein schönes 16x2 LC-Display, das blau hinterleuchtet ist. Kleinkram wie Taster, Kabel und Widerstände hat man ja eh immer zu Hause. Ein erster Softwareprototyp stand recht fix, der zeigte aber erst mal nur eine statische Anzeige um zu sehen, wie das später dann überhaupt wirkt. Beim schreiben des eigentlichen Programms hatte mein Gehirn einen Fehler und ich hab knapp eine Stunde gebraucht bis ich aus "||" endlich "&&" gemacht hab. Ich hab die zwei Pipes irgendwie die ganze Zeit als "UND" gelesen. Auch nach zigfachem gegenlesen und nachprüfen nix falsches gesehen. Irgendwann kam dann das berühmte "Ou mann wie dumm..." und siehe da, macht man es richtig funktioniert es plötzlich.
Aufgebaut hab ich das Teil erst mal auf einem Steckbrett:
Schaltplan:
Und da bewegte Bilder immer toll sind, hier ein Video:
Die LEDs und der Piepser, der den An- und Abpfiff macht kamen erst während des Programmierens dazu. vor dem Anpfiff und nach dem Abpfiff ist eine Änderung der Punkte nicht mehr möglich. passiert während dem Spiel eine "Falscheingabe" kann man einfach weiter auf die entsprechende Taste drücken und korrigieren, da nach 9 Punkten automatisch wieder auf 0 zurückgesetzt wird.
Ein Gehäuse dafür hat der Kurze dann mal mit Bleistift gezeichnet und ich hab es dann mit ihm in Sketchup digitalisiert. Das Gehäuse wird derzeit noch etwas verfeinert und dann gedruckt.
Hier ist das fertige Teil:
von innen:
und komplett:
Im Spoiler ist der komplette Code - ich hoffe ausreichend gut kommentiert.
tk_lcd1.ino
[noae]
[/noae]
functions.ino
[noae]
[/noae]
[noae]
Code:
// Dashboard for TIPP-KICK with timer
// select the required libraries
//#include <Adafruit_SSD1331.h>
//#include <PID_v1.h>
//#include <Bounce2.h>
//#include <Stepper.h>
//#include <WiFi.h>
//#include <WiFiClient.h>
//#include <WiFiServer.h>
//#include <WiFiUdp.h>
//#include <ESP8266WiFi.h>
#include <LiquidCrystal.h>
//#include <max6675.h>
//#include <Servo.h>
//#include <OneWire.h>
//#include <DallasTemperature.h>
// _____ _ _ _
// | __ \ | | | | (_)
// | | | | ___ ___| | __ _ _ __ __ _| |_ _ ___ _ __ ___
// | | | |/ _ \/ __| |/ _` | '__/ _` | __| |/ _ \| '_ \/ __|
// | |__| | __/ (__| | (_| | | | (_| | |_| | (_) | | | \__ \
// |_____/ \___|\___|_|\__,_|_| \__,_|\__|_|\___/|_| |_|___/
//
//
//---------------------------------------------------------------------
// these variables are meant to be used for calling functions by time
// in the "loop", because not every function has to be called in every
// loop of the programm.
const int tasks = 9;
unsigned long millis_current;
unsigned long millis_old_task[tasks];
bool task[tasks];
int task_time[] = {5, 10, 25, 100, 250, 500, 1000, 5000, 10000, 60000};
//---------------------------------------------------------------------
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
int ScoreYellow = 0;
int ScoreRed = 0;
long GameTime = 305000;
int Buzzer = 7;
int ButtonRed = 10;
int ButtonYellow = 9;
int ButtonReset = 8;
int LEDGreen = A4;
int LEDRed = A5;
// Buttons
bool ButtonRedState = 0;
bool ButtonYellowState = 0;
bool ButtonRedStateOld = 0;
bool ButtonYellowStateOld = 0;
bool ButtonResetState = 0;
bool ButtonResetStateOld = 0;
//
bool GameReady = 0;
bool GameActive = 0;
bool GameActiveOld = 0;
long TimeGameEndMillis = 0;
int TimeLeft = 0;
int TimeLeftMinutes = 0;
int TimeLeftSeconds = 0;
//---------------------------------------------------------------------
// _____ _
// / ____| | |
// | (___ ___| |_ _ _ _ __
// \___ \ / _ \ __| | | | '_ \
// ____) | __/ |_| |_| | |_) |
// |_____/ \___|\__|\__,_| .__/
// | |
// |_|
void setup() {
pinMode(ButtonRed, INPUT);
pinMode(ButtonYellow, INPUT);
pinMode(LEDGreen, OUTPUT);
pinMode(LEDRed, OUTPUT);
pinMode(Buzzer, OUTPUT);
analogWrite(LEDGreen, 0);
analogWrite(LEDRed, 0);
Serial.begin(115200); // initialize serial communications at 115200bps
//---------------------------------------------------------------------
// The "Splashscreen"
lcd.begin(16, 2);
// Print a message to the LCD.
lcd.print("Tipp-Kick-Dash ");
lcd.setCursor(0, 1);
lcd.print(" froetz.de");
delay(2000);
lcd.clear();
delay(100);
lcd.setCursor(0, 1);
lcd.print(" Press Start! ");
TimeLeft = ((GameTime / 1000) + 5);
digitalWrite(Buzzer, LOW);
analogWrite(LEDRed, 150);
//---------------------------------------------------------------------
}
// _
// | |
// | | ___ ___ _ __
// | | / _ \ / _ \| '_ \
// | |___| (_) | (_) | |_) |
// |______\___/ \___/| .__/
// | |
// |_|
void loop() {
// generate slopes for tasks
millis_current = millis();
for (int i = 0; i < tasks; i++) {
if (millis_current - millis_old_task[i] > task_time[i]) {
millis_old_task[i] = millis_current;
task[i] = 1;
}
}
// Buttonstates and old buttonstates to detect changes
GameActiveOld = GameActive;
ButtonRedStateOld = ButtonRedState;
ButtonYellowStateOld = ButtonYellowState;
ButtonResetStateOld = ButtonResetState;
// read the actual states
ButtonRedState = digitalRead(ButtonRed);
ButtonYellowState = digitalRead(ButtonYellow);
ButtonResetState = digitalRead(ButtonReset);
// Check the buttons and count scores or reset the game
if (GameReady && ButtonYellowState == HIGH && ButtonYellowStateOld == LOW && (TimeLeft <= (GameTime / 1000) - 5)) {
delay(75);
CountYellow();
delay(75);
}
if (GameReady && ButtonRedState == HIGH && ButtonRedStateOld == LOW && (TimeLeft <= (GameTime / 1000) - 5)) {
delay(75);
CountRed();
delay(75);
}
if (ButtonResetState == LOW && ButtonResetStateOld == HIGH ) {
delay(50);
Reset();
delay(75);
}
if (task[0] == 1) {
// 5ms calls
//Serial.println("5ms");
}
if (task[1] == 1) {
// 10ms calls
//Serial.println("10ms");
}
if (task[2] == 1) {
// 25ms calls
//Serial.println("25ms");
}
if (task[3] == 1) {
// 100ms calls
//Serial.println("100ms");
if (GameReady) {
CalculateDisplayTime();
DisplayOutputGame();
}
}
if (task[4] == 1) {
// 250ms calls
//Serial.println("250ms");
SerialOutput();
//start the game
if (GameReady && (TimeLeft <= (GameTime / 1000) - 5)) {
analogWrite(LEDGreen, 140);
analogWrite(LEDRed, 0);
GameActive = HIGH;
}
// it time is up, then gameover
if (TimeLeft <= 0) {
GameOver();
DisplayOutputGameOver();
}
// kick-off
if (GameActive == HIGH && GameActiveOld == LOW) {
KickOff();
}
// final whistle
if (GameActive == LOW && GameActiveOld == HIGH) {
finalwhistle();
}
}
if (task[5] == 1) {
// 500ms calls
//Serial.println("500ms");
// Update the remaining time
if (GameReady) {
UpdateTime();
}
}
if (task[6] == 1) {
// 1s calls
//Serial.println("1s");
}
if (task[7] == 1) {
// 5s calls
//Serial.println("5s");
}
if (task[8] == 1) {
// 10s calls
//Serial.println("10s");
}
if (task[9] == 1) {
// 1m calls
//Serial.println("1m");
}
// reset slopes for the tasks
for (int i = 0; i < tasks; i++) {
task[i] = 0;
}
// DEBUGGING
//Serial.println("######DEBUG########");
//Serial.print("ButtonResetState: ");
//Serial.println(ButtonResetState);
//Serial.print("ButtonResetStateOld: ");
//Serial.println(ButtonResetStateOld);
//
//Serial.print("ButtonRedState: ");
//Serial.println(ButtonRedState);
//Serial.print("ButtonRedStateOld: ");
//Serial.println(ButtonRedStateOld);
//
//Serial.print("ButtonYellowState: ");
//Serial.println(ButtonYellowState);
//Serial.print("ButtonYellowStateOld: ");
//Serial.println(ButtonYellowStateOld);
//
//Serial.print("ScoreRed: ");
//Serial.println(ScoreRed);
//Serial.print("ScoreYellow: ");
//Serial.println(ScoreYellow);
// Serial.print("TimeLeft: ");
// Serial.println(TimeLeft);
// Serial.print("Gametime: ");
// Serial.println(GameTime);
// Serial.print("TimeLeftMinutes: ");
// Serial.println(TimeLeftMinutes);
// Serial.print("TimeLeftSeconds: ");
// Serial.println(TimeLeftSeconds);
}
functions.ino
[noae]
Code:
// ______ _ _
// | ____| | | (_)
// | |__ _ _ _ __ ___| |_ _ ___ _ __ ___
// | __| | | | '_ \ / __| __| |/ _ \| '_ \/ __|
// | | | |_| | | | | (__| |_| | (_) | | | \__ \
// |_| \__,_|_| |_|\___|\__|_|\___/|_| |_|___/
//
//
void SerialOutput() {
Serial.println("Start serial communication");
Serial.print("Remainung time: ");
Serial.println(TimeLeft);
Serial.print("Red: ");
Serial.println(ScoreRed);
Serial.print("Yellow: ");
Serial.println(ScoreYellow);
Serial.println("End serial communication");
}
void CountRed() {
//Serial.println("CountRed start");
ScoreRed++;
tone(Buzzer, 60);
delay(20);
noTone(Buzzer);
if (ScoreRed > 9) {
ScoreRed = 0;
}
}
void CountYellow() {
//Serial.println("CountYellow start");
ScoreYellow++;
tone(Buzzer, 60);
delay(20);
noTone(Buzzer);
if (ScoreYellow > 9) {
ScoreYellow = 0;
}
}
void DisplayOutputGame() {
lcd.setCursor(0, 0);
lcd.print("Rot : Gelb ");
if (GameReady && (TimeLeft > (GameTime / 1000 - 5))) {
//show the "Get Ready" signal when game is about to start
lcd.setCursor(12, 0);
lcd.print("Get");
lcd.setCursor(11, 1);
lcd.print("Ready");
}
if (GameReady && (TimeLeft <= (GameTime / 1000) - 5)) {
//show the time while game is running
lcd.print(TimeLeftMinutes);
lcd.print(":");
if (TimeLeftSeconds > 9) {
lcd.print(TimeLeftSeconds);
}
if (TimeLeftSeconds <= 9) {
lcd.setCursor (14, 0);
lcd.print("0");
lcd.print(TimeLeftSeconds);
}
}
lcd.setCursor(1, 1);
lcd.print(ScoreRed);
lcd.setCursor(4, 1);
lcd.print(":");
lcd.setCursor(7, 1);
lcd.print(ScoreYellow);
}
void DisplayOutputGameOver() {
lcd.setCursor(0, 0);
lcd.print("Rot : Gelb Press");
lcd.setCursor(1, 1);
lcd.print(ScoreRed);
lcd.setCursor(4, 1);
lcd.print(":");
lcd.setCursor(7, 1);
lcd.print(ScoreYellow);
lcd.setCursor(11, 1);
lcd.print("Start");
}
void UpdateTime() {
TimeLeft = ((TimeGameEndMillis - millis()) / 1000);
}
void GameOver() {
analogWrite(LEDGreen, 0);
analogWrite(LEDRed, 150);
GameReady = LOW;
GameActive = LOW;
}
void Reset() {
lcd.clear();
ScoreYellow = 0;
ScoreRed = 0;
TimeGameEndMillis = (millis() + GameTime); //set the timestamp for the end of the game
analogWrite(LEDGreen, 0);
analogWrite(LEDRed, 150);
GameReady = HIGH;
GameActive = LOW; //needed for ingame-resets, without, there will be no kick-off-whistle after an ingame-reset
TimeLeft = ((GameTime / 1000) + 5);
}
void KickOff() {
tone(Buzzer, 50);
delay(200);
noTone(Buzzer);
lcd.clear();
}
void finalwhistle() {
tone(Buzzer, 50);
delay(250);
noTone(Buzzer);
delay(100);
tone(Buzzer, 50);
delay(250);
noTone(Buzzer);
delay(100);
tone(Buzzer, 50);
delay(250);
tone(Buzzer, 75);
delay(200);
noTone(Buzzer);
}
void CalculateDisplayTime() {
// display the remaining time in minutes:seconds
TimeLeftMinutes = (TimeLeft / 60);
TimeLeftSeconds = (TimeLeft - TimeLeftMinutes * 60);
}
Fertig!
Wer nachbauen möchte:
LCD-Scoreboard for Tipp-Kick, Kicker or similar games by froetz
A simple USB-powered scoreboard for tabletop-sportgames like Tipp-Kick or similar. I used an arduino nano, a 16x02a-LCD, a littel 12mm piezo speaker, two 5mm LEDs, a potentiometer for adjusting the contrast and three buttons. https://youtu.be/2sxOfpiPVpE The code, the Sketchup-file for editing...
www.thingiverse.com
Zuletzt bearbeitet: