Intelligentes Basketball-Scoreboard mit Bluetooth, Sensoren & Echtzeit-Anzeige
Komponenten und Materialien
| Bauteil | Menge | Hinweise |
|---|---|---|
| Arduino Nano R3 | 1 | |
| HC-05 Bluetooth-Modul | 1 | |
| E18-D80NK Infrarot-Näherungssensor | 1 | Unempfindlich gegen Sonnenlicht |
| Vibrationssensor SW-420 (Grove) | 1 | |
| DHT22 Temperatur-/Luftfeuchtesensor | 1 | |
| 8 mm RGB-LED | 1 | |
| Widerstand 10 kΩ | 3 | |
| Widerstand 100 Ω | 3 | |
| Widerstand 47 Ω | 1 | |
| Widerstand 1 kΩ | 1 | |
| Widerstand 2,21 kΩ | 1 | |
| 9V-Batterie | 1 |
Software und Online-Dienste
- Arduino IDE
- MIT App Inventor (Android-App Entwicklung)
Projektbeschreibung
Ich trainiere regelmäßig Basketball und möchte meine Statistiken (Würfe, Treffer, Fehlwürfe) automatisch erfassen. Manuelle Aufzeichnung ist mühsam. „Smart Balls“ gibt es, aber sie haben Nachteile:
- Bei mehreren Bällen müsste man mehrere teure Smart Balls kaufen.
- Die Genauigkeit ist oft mangelhaft.
- Die Haltbarkeit des Balls leidet unter der Elektronik.
In einem früheren Prototyp nutzte ich das Avnet SmartEdge-Gerät. Jetzt geht es um eine definitive Lösung.
Versionen
Version 1.1.0: Erste Version mit verfügbaren Komponenten. Funktionierte gut.
Version 2.0.0: Kostengünstigere Komponenten und Software-Verbesserungen.
Schritt 1: Arduino (Hardware & Software)
Hardware-Änderungen v1.1.0 → v2.0.0
- Arduino Mega 2560 → Arduino Nano R3
- Bluetooth Shield → HC-05 Bluetooth Modul
- Li-Ion-Akku → 9V-Batterie
- Hinzugefügt: DHT22 Temperatur- & Luftfeuchtesensor
Hinweise zu Sensoren:
- E18-D80NK Näherungssensor: Andere Sensoren möglich, aber dieser leidet nicht unter Sonnenlicht-Störungen.
- SW-420 Vibrationssensor: Funktioniert sehr zuverlässig.
Schaltpläne für beide Versionen finden sich im Schematics-Bereich.
Software-Strategie (Arduino)
- Initialisierung (Variablen, LED, Bluetooth, Sensoren)
- Kontinuierliche Überwachung der Sensoren
- Näherungssensor erkennt Ball → Treffer (Score)
- Vibrationssensor erkennt Bewegung → Wurf erkannt, wartet 2 Sekunden auf Entscheidung
- Innerhalb der 2 Sekunden: Erkennt Näherungssensor den Ball → sofortiger Treffer
- Nach 2 Sekunden ohne Naherkennung → Fehlwurf (Miss)
- Ergebnis per Bluetooth an Android-App senden
- Prozess neu starten
Software-Änderungen v1.1.0 → v2.0.0:
- Unterstützung HC-05 statt Bluetooth Shield
- DHT22 Unterstützung hinzugefügt
- Verbesserte Erkennungslogik (Wurf/Treffer/Fehlwurf) und LED-Signalisierung
Schritt 2: Android-App (MIT App Inventor)
App-Strategie
- Initialisierung (Zähler, Bluetooth)
- Warte auf „Start“-Button
- Bei Start: Kontinuierliche Bluetooth-Überwachung
- Bei Dateneingang: Scoreboard aktualisieren, Benachrichtigungston abspielen
- Bis „Pause“ gedrückt wird
- Zusatz: Bluetooth-Gerät wählen, Zähler zurücksetzen, manuelle Korrektur
Änderungen v1.1.0 → v2.0.0:
- Layout: Hochformat → Querformat
- Anzeige: Licht, Luftfeuchte, Temperatur, Heat Index
- Verbesserte Korrektur-Buttons
- Bildschirm bleibt an (Wake Lock)
- Tastentöne bei allen Buttons
- Warnung bei jedem 50-Wurf-Meilenstein (50, 100, 150…)
Schritt 3: Basketball-Korb Montage
Ausgangsbasis: Ein normaler Basketball-Korb für regelmäßiges Training.
- Plastikabdeckung unter dem Korb entfernt, Loch für Näherungssensor gebohrt.
- Kleines Loch für Vibrationssensor.
- Wegen Krümmung der Abdeckung: MDF-Halter für Vibrationssensor gebaut.
- Sensoren mit Schrauben und Muttern befestigt.
- Übrige Komponenten verdrahtet.
- Rauch-Test (Funktionsprüfung).
- Endmontage am Korb.
Schritt 4: Trainingstest
System getestet – funktioniert einwandfrei.
Schritt 5: Fazit
- Sehr präzise: Sehr wenige False Positives, seltene False Negatives.
- Fantastisch: Echtzeit-Statistiken während und nach dem Training.
Viel Spaß beim Nachbauen!
Code
Arduino Code v1.1.0
//----------------------------------------------------------------------------//
// Filename : Scoreboard.ino
// Description : Smart Basketball Scoreboard
// Version : 1.1.0
// Author : Marcelo Avila de Oliveira <marceloavilaoliveira@gmail.com>
//----------------------------------------------------------------------------//
// DEFINITIONEN
// #define DEBUG
// #define DEBUG_PROX
// #define DEBUG_VIBR
// KONSTANTEN
const int prox_pin = 2;
const int vibr_pin = 3;
const int led_r_pin = 4;
const int led_g_pin = 5;
const int led_b_pin = 6;
const unsigned long wait_interval = 3000;
const float percent_to_bright_factor = 100 * log10(2) / log10(255);
// VARIABLEN
unsigned long wait_time;
boolean prox = false;
boolean vibr = false;
boolean wait = false;
// SETUP
void setup() {
pinMode(prox_pin, INPUT);
pinMode(vibr_pin, INPUT);
pinMode(led_r_pin, OUTPUT);
pinMode(led_g_pin, OUTPUT);
pinMode(led_b_pin, OUTPUT);
set_led(5, 100); // Magenta
Serial.begin(9600);
setup_bluetooth();
set_led(4, 100); // Blau
#ifdef DEBUG
Serial.println("Board is alive");
#endif
}
void setup_bluetooth() {
#ifdef DEBUG
Serial.println("Setting Bluetooth");
#endif
Serial1.begin(38400);
Serial1.print("\r\n+STWMOD=0\r\n"); // Slave mode
Serial1.print("\r\n+STNA=Arduino\r\n"); // Name
Serial1.print("\r\n+STOAUT=1\r\n"); // Paired device may connect
Serial1.print("\r\n+STAUTO=0\r\n"); // No auto-connect
delay(2000);
Serial1.print("\r\n+INQ=1\r\n"); // Inquirable
delay(2000);
while (Serial1.available()) { delay(50); Serial1.read(); }
}
// LED-STEUERUNG
int percent_to_bright(int percent) {
return 256 - pow(2, percent / percent_to_bright_factor);
}
void set_led(int color, int bright) {
// Farbe: 0=Grün, 1=Gelb, 2=Rot, 3=Cyan, 4=Blau, 5=Magenta, 6=Weiß
// Helligkeit: 0=Aus .. 100=Max
if (color < 0 || color > 6 || bright < 0 || bright > 100) return;
int r=255, g=255, b=255;
int br = percent_to_bright(bright);
switch(color) {
case 0: g=br; break;
case 1: r=br; g=br; break;
case 2: r=br; break;
case 3: g=br; b=br; break;
case 4: b=br; break;
case 5: r=br; b=br; break;
case 6: r=br; g=br; b=br; break;
}
analogWrite(led_r_pin, r);
analogWrite(led_g_pin, g);
analogWrite(led_b_pin, b);
}
// SENSOR-PRÜFUNG
void check_prox() {
if (!prox && digitalRead(prox_pin) == LOW) {
#ifdef DEBUG_PROX
Serial.println("Proximity detected");
#endif
prox = true;
if (!vibr) { wait = true; wait_time = millis() + wait_interval; }
set_shot(1);
}
}
void check_vibr() {
if (!prox && !vibr && digitalRead(vibr_pin) == HIGH) {
#ifdef DEBUG_VIBR
Serial.println("Vibration detected");
#endif
vibr = true;
wait = true;
wait_time = millis() + wait_interval;
set_led(1, 100); // Gelb
}
}
void check_wait() {
if (wait && millis() > wait_time) {
if (!prox) set_shot(0);
reset();
}
}
// HILFSFUNKTIONEN
void set_shot(int mode) {
// 0 = Fehlwurf (Rot), 1 = Treffer (Grün)
set_led(mode == 0 ? 2 : 0, 100);
Serial1.print(mode);
delay(1000);
}
void reset() {
vibr = false; prox = false; wait = false;
set_led(4, 100); // Blau
}
// HAUPTSCHLEIFE
void loop() {
check_prox();
check_vibr();
check_wait();
}
Arduino Code v2.0.0
//----------------------------------------------------------------------------//
// Filename : Scoreboard.ino
// Description : Smart Basketball Scoreboard
// Version : 2.0.0
// Author : Marcelo Avila de Oliveira <marceloavilaoliveira@gmail.com>
//----------------------------------------------------------------------------//
// BIBLIOTHEKEN
#include "DHT.h"
#include "SoftwareSerial.h"
// DEFINITIONEN
// #define DEBUG
// #define DEBUG_BLUE
// #define DEBUG_PROX
// #define DEBUG_VIBR
// #define DEBUG_DHT
#define DHTPIN 7
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
SoftwareSerial Bluetooth(10, 11); // RX, TX
// KONSTANTEN
const int prox_pin = 2;
const int vibr_pin = 3;
const int led_r_pin = 4;
const int led_g_pin = 5;
const int led_b_pin = 6;
const unsigned long wait_interval = 2000;
const unsigned long dht_interval = 10000;
const float percent_to_bright_factor = 100 * log10(2) / log10(255);
// VARIABLEN
unsigned long wait_time, dht_time;
float humi, temp, heat;
boolean prox = false, vibr = false, wait = false;
void setup() {
pinMode(prox_pin, INPUT);
pinMode(vibr_pin, INPUT);
pinMode(led_r_pin, OUTPUT);
pinMode(led_g_pin, OUTPUT);
pinMode(led_b_pin, OUTPUT);
set_led(5, 100); // Magenta
Serial.begin(9600);
setup_bluetooth();
dht.begin();
set_led(4, 100); // Blau
#ifdef DEBUG
Serial.println("Board is alive");
#endif
}
void setup_bluetooth() {
#ifdef DEBUG_BLUE
Serial.println("Setting Bluetooth");
#endif
Bluetooth.begin(9600);
while (Bluetooth.available()) { delay(50); Bluetooth.read(); }
}
// LED-Funktionen identisch zu v1.1.0 (percent_to_bright, set_led)
void check_prox() {
if (!prox && digitalRead(prox_pin) == LOW) {
#ifdef DEBUG_PROX
Serial.println("Proximity detected");
#endif
set_led(0, 100); // Grün
send_data(2); // 2 = Treffer
prox = true;
if (!vibr) { wait = true; wait_time = millis() + wait_interval; }
}
}
void check_vibr() {
if (!prox && !vibr && digitalRead(vibr_pin) == HIGH) {
#ifdef DEBUG_VIBR
Serial.println("Vibration detected");
#endif
set_led(1, 100); // Gelb
vibr = true;
wait = true;
wait_time = millis() + wait_interval;
}
}
void check_wait() {
if (wait && millis() > wait_time) {
if (!prox) {
set_led(2, 100); // Rot
send_data(1); // 1 = Fehlwurf
}
reset();
}
}
void check_dht() {
if (!prox && !vibr && millis() > dht_time) {
humi = dht.readHumidity();
temp = dht.readTemperature();
heat = dht.computeHeatIndex(temp, humi, false);
#ifdef DEBUG_DHT
Serial.print("Humidity: "); Serial.print(humi); Serial.println("%");
Serial.print("Temperature: "); Serial.print(temp); Serial.println("C");
Serial.print("Heat Index: "); Serial.print(heat); Serial.println("C");
#endif
send_data(0); // 0 = Sensordaten ohne Wurf
dht_time = millis() + dht_interval;
}
}
void send_data(int shot) {
// shot: 0=Sensordaten, 1=Fehlwurf, 2=Treffer
Bluetooth.print(humi);
Bluetooth.print(temp);
Bluetooth.print(heat);
Bluetooth.print(shot);
#ifdef DEBUG_BLUE
Serial.println("Bluetooth sent");
#endif
}
void reset() {
vibr = false; prox = false; wait = false;
delay(1000);
set_led(4, 100); // Blau
}
void loop() {
check_prox();
check_vibr();
check_wait();
check_dht();
}
Hinweis: Die Android-App-Codes (MIT App Inventor .aia Dateien) für beide Versionen sind als Download verfügbar, aber nicht als Textvorschau darstellbar.
Schaltpläne
Herstellungsprozess
- Basketball: Von Naismiths Erfindung 1891 zu modernen Produktionstechniken
- Open-Source Smart Farming: Bauern mit erschwinglicher, interoperabler IoT-Technologie stärken
- ECM3532: Eta Computes erstes integriertes Ultra-Low-Power KI Sensor Board beschleunigt Edge Development
- Raspberry Pi Heimtemperaturmonitor mit MCP9808, InfluxDB & Grafana bauen
- Intelligenter Mülleimer: Zellulare IoT-Lösung für automatisiertes Abfallmanagement
- Smart Bartender: Eigenen Raspberry Pi Cocktail-Roboter bauen
- Emotionssensor & EEG: Günstige Hardware für Echtzeit-Emotionserkennung
- Revolutionärer ultraempfindlicher, langlebiger Dehnungssensor für Smart Textiles
- Revolutionärer ultra-dünner Sensor verbessert Smart-Contact-Lens-Funktionalität
- Sensorproduktion revolutioniert: Sensata nutzt Smart Mechatronics