Eriks Laser Tag
| Repository | https://gitea.iten.pro/edi/lasertag |
Table of Contents
Eriks Lasertag
Kurzer Überblick über das DIY-Lasertag-System auf Basis von nRF52840, Thread und BLE.
Was dich hier erwartet
- Architektur & Spielablauf: siehe Konzept Software.
- Hardware-Ideen: Waffe, Weste, Leader, Stromversorgung.
- Roadmap & To-Dos: grobe Phasen und Module.
Schnelleinstieg
- Konzept Software: Rolle Leader/Weste/Waffe, Game Loop, CoAP-API.
- Konzept Hardware: Aufbau der Einheiten, LED-Treiber, Akku-Setup.
- Gameplay & Modi: concepts/gameplay.md – Kurz erklärt, Rollen, Power-Ups und Spielmodi.
- Planung: Zephyr-Workspace-Struktur und Roadmap.
Lizenz
- Inhalte stehen unter CC BY-NC-SA 4.0. Details unter license.md.
Konzept
Hardware-Konzept
Dieses Dokument beschreibt die physischen Komponenten des Lasertag-Systems. Alle Knoten basieren auf dem Nordic nRF52840 SoC.
Ziele: robuste Outdoor-Tauglichkeit, klare Rollen-Trennung (Waffe/Weste/Leader), einfache Wartung (Steckverbinder, modulare Boards) und reproduzierbare Reichweite über saubere Stromversorgung.
1. Geräteübersicht
1.1 Waffe (Weapon Unit)
Die Waffe ist das primäre Interaktionsgerät. Sie muss robust und reaktionsschnell sein.
- Controller: nRF52840 (Dongle oder Modul).
- IR-Sender: High-Power IR-LED (940nm oder 850nm) mit Optik/Linse und Treiberstufe (Reichweite > 50m).
- Feedback: Muzzle Flash (helle LED), Solenoid (6V Open Frame, Rückstoss), Audio (Schussgeräusche, "Leer"-Klicken).
- Eingabe: Abzug (Trigger), Nachladen (Taster), optionaler Schalter für Feuermodus.
- Stromversorgung: 2S LiPo (7.4V) mit Buck auf 5V, nRF52840 mit interner 3.3V-Regelung.
1.2 Weste (Player Hub)
Die Weste ist die zentrale Recheneinheit des Spielers und trägt die Sensorik.
- Controller: nRF52840 DK oder Custom Board.
- Sensorik (IR-Empfänger): Verteilte Sensoren für 360° Abdeckung (Kopf, Brust/Rücken, Schultern).
- Beleuchtung: Adressierbare RGB-LEDs (WS2812B) an den Sensor-Positionen für Teamfarbe/Treffer.
- Audio: Leistungsstarker Lautsprecher für Sprachausgabe.
- Verbindung: Zentrale Box am Rücken mit Steckverbindern zu den Sensorgruppen.
1.3 Leader Box (Game Controller)
Die Leader Box dient zur Spielsteuerung und als Infrastruktur-Knoten.
- Controller: nRF52840.
- Modi (Hardware-Schalter): 2 DIP-Schalter zur Wahl von Leader / Repeater / Base.
- Ausstattung: IR-Empfänger, RGB-LEDs, Bluetooth-Gateway zur Smartphone-App.
- Stromversorgung: Großer Akku für lange Laufzeit.
1.4 Power-Up-Stationen (Deckel-Boxen)
Physische Gegenstände, die Spieler aktivieren, um Power-Ups auszulösen.
- Controller: nRF52840 Modul oder DK.
- Sensoren: Magnetschalter oder Druckschalter (unter Deckel) zur Erkennung von "Deckel offen".
- Aktor: IR-LED-Treiber (ähnlich zur Waffe) – sendet Power-Up-Codes.
- Feedback: RGB-LED (Status: Idle grün, aktiv blinkend, Cooldown rot).
- Kommunikation: Optional Thread (CoAP) für Logging an Leader ("Station XYZ wurde von Spieler 3 aktiviert").
- Stromversorgung: 2S LiPo oder USB-betrieben (wenn stationär).
- Cooldown: Hardware oder Software gesteuert (z.B. 30s nach Aktivierung).
1.5 Buzzer-Power-Ups
Kompakte passive Power-Up-Geräte mit Druckschalter.
- Controller: nRF52840 Modul.
- Eingabe: Einfacher Druckschalter (Buzzer-Button).
- Aktor: Schwacher IR-LED-Sender (kurze Reichweite ~2-3m, breiter Strahl) für Power-Up-Code.
- Feedback: Cooldown-LED (Rot = kann nicht drücken, Grün = aktiv).
- Kommunikation: Optional Thread (nur für Admin-Logging, nicht kritisch für Gameplay).
- Stromversorgung: 2S LiPo mit Schutzschaltung.
- Cooldown: Intern gesteuert (z.B. 15s zwischen Aktivierungen).
2. Energieversorgung & Verkabelung
2.1 Akkusystem
Standard: 2S LiPo (7.4 V nominal, 8.4 V voll geladen, 6.0 V Entladungsschutz).
Alternative: 1S nur für Tests oder Low-Power-Prototypen – ungeeignet für hohe IR-LED-Ströme (siehe Abschnitt 4.1).
Schutz & Laden:
- Zellenschutz-IC: HY2120-CB + FS8205A (Dual-FET) – schützt vor Über-/Unterspannung, Überstrom, Kurzschluss.
- Lade-IC: IP2326 (2S Balancing, USB-C) – ermöglicht einfaches Laden ohne externe Balancer.
- Fuel Gauge: Spannungsteiler-basierte ADC-Messung (R1=100k, R2=47k) → Software-Mapping auf Ladestand (6.0 V = 0 %, 8.4 V = 100 %).
Warum 2S?
2S-Systeme bieten ausreichend Headroom für IR-LED-Konstantstromquellen (>4.8 V nötig bei 3A) und stabile Versorgung auch bei hoher Last. 1S-Zellen brechen unter 1A+ schnell auf 3.4–3.6 V ein.
2.2 Spannungsebenen & Wandler
Primär-Rail (Batterie, 6.0–8.4 V):
Direkt gespeist: IR-LED-Treiber, Muzzle-Flash-LED, Solenoid 6V (Open Frame, taktiles Feedback Rückstoss).
Sekundär-Rail (5.0 V, ~1.5 A):
Buck-Converter (z.B. MP2315, TPS62130) für Audio-IC (MAX98357A), adressierbare LEDs (WS2812B) und nachgeschalteten LDO. Hohe Schaltfrequenz gewünscht (geringe Induktivität, kompakte Bauform).
Tertiär-Rail (3.3 V, ~30 mA):
LDO (z.B. MCP1826, AMS1117-3.3) aus 5V Buck-Ausgang für nRF52840 und QSPI Flash. Geringer Dropout (5V → 3.3V = 1.7V) reduziert Wärmeentwicklung; Low-Noise-Design minimiert Störungen auf der RF-Schaltung.
IR-Empfänger (5V mit Level-Shift):
TSOP48xx-Module laufen an 5V (besserer SNR, robuster gegen Sonnenlicht). Output-Signal wird per AO4300A N-Channel MOSFET (Open-Drain) auf 3.3V gewandelt → invertierendes Level-Shifting. Software kompensiert Invertierung mit GPIO_ACTIVE_LOW.
Verkabelung Weste:
Sternförmige Abgänge zu Sensor-Modulen (Kopf/Brust/Schultern); jeweils 5V + GND + WS2812-Data; verriegelnde Stecker (JST-XH o.ä.), Polyfuse pro Ast, Verpolschutz (Diode/FET).
2.3 Leistungsbilanz (Weste)
Die Weste hat durch LEDs und Audio den höchsten Verbrauch; hier die Peak-Abschätzung:
5V-Rail (Buck-Converter):
| Komponente | Zustand | Strom | Leistung |
|---|---|---|---|
| Audio (MAX98357A) | Volllast (3W @ 90% η) | ~670 mA | 3.35 W |
| WS2812B LEDs (5×) | 100 % Weiß | 300 mA | 1.50 W |
| IR-Empfänger (5×) | Dauerbetrieb @ 5V | ~50 mA | 0.25 W |
| LDO 3.3V (Durchleitung) | 30 mA @ 3.3V | ~30 mA | 0.15 W |
| Gesamt 5V (Peak) | ~1.05 A | 5.25 W |
3.3V-Rail (LDO aus 5V Buck):
| Komponente | Zustand | Strom | Leistung |
|---|---|---|---|
| nRF52840 | BLE+Thread aktiv | ~15 mA | 0.05 W |
| QSPI Flash | Read/Write Burst | ~15 mA | 0.05 W |
| Gesamt 3.3V (Peak) | ~30 mA | 0.10 W |
Auslegung:
- Buck-Regler: 1.5 A Nennstrom (30 % Reserve), hohe Schaltfrequenz (>1 MHz) für kompakte Drossel/Kondensatoren.
- LDO: 100 mA Nennstrom ausreichend; Verlustleistung bei 30 mA: \(P_{loss} = (5V - 3.3V) \cdot 30mA = 51 mW\) (unkritisch). Low-Noise-Design (< 50 µVrms) für sauberen RF-Betrieb.
2.4 Blockschaltbild Energieversorgung
flowchart TD
BAT["2S LiPo<br/>6.0–8.4V"] <--> PROT["Zellenschutz<br/>HY2120+FS8205A"]
CHG["USB-C Lader<br/>IP2326"] --> PROT
PROT --> BUCK["Buck 5.0V<br/>MP2315/TPS62130<br/>1.5A"]
PROT --> IR_DRV["IR-LED<br/>Konstantstromquelle"]
PROT --> MUZZLE["Muzzle Flash<br/>LED-Treiber"]
PROT --> SOL["Solenoid 6V<br/>Open Frame"]
BUCK --> AUDIO["Audio Amp<br/>MAX98357A"]
BUCK --> LED["WS2812B LEDs<br/>mit Level Shift"]
BUCK --> IR_RX["IR-Empfänger<br/>TSOP48xx (5V)"]
BUCK --> LDO["LDO 3.3V<br/>MCP1826/AMS1117<br/>100mA"]
LDO --> NRF["nRF52840<br/>3.3V"]
LDO --> FLASH["QSPI Flash<br/>3.3V"]
IR_RX -->|"AO4300A<br/>MOSFET Shifter"| NRF
3. Stückliste (Übersicht)
Diese Tabelle gibt einen Überblick über die groben Komponenten pro Einheit. Detaillierte Part Numbers und Bezugsquellen folgen in separaten Docs.
| Komponente | Waffe | Weste | Leader | Menge | Anmerkung |
|---|---|---|---|---|---|
| nRF52840 (SoC/Modul) | ✓ | ✓ | ✓ | 1/Gerät | Zephyr SDK Support |
| IR-LED (High-Power) | ✓ | 940nm, > 50m Reichweite | |||
| IR-Empfänger (38kHz) | ✓ | ✓ | 5–10 | Verteilt auf Kopf/Torso/Schulter | |
| RGB-LED (WS2812B) | ✓ | ✓ | 1–3 | Teamfarbe + Status | |
| Solenoid (6V Open Frame) | ✓ | Taktiles Feedback Rückstoss | |||
| Lautsprecher | ✓ | ✓ | Schussgeräusche + Sprachausgabe | ||
| 2S LiPo Akku | ✓ | ✓ | ✓ | 1 | 7.4V, ggf. unterschiedliche Kapazität |
| Lade-IC (IP2326) | ✓ | ✓ | ✓ | 1 | 2S Balancing |
| Zellenschutz (FS8205A) | ✓ | ✓ | ✓ | 1 | Verpolschutz + OV/UV |
| Spannungsteiler-ADC | ✓ | ✓ | ✓ | 1 | Fuel Gauge (R1=100k, R2=47k) |
| Taster (Trigger/Reload) | ✓ | Auch optional Dip-Switch für Leader | |||
| USB-C / Pogo-Pad | ✓ | ✓ | ✓ | 1 | Laden + Debug-Konsole |
| Steckverbinder (JST-XH) | ✓ | ✓ | Modular aufgebaut |
4. Schaltungskomponenten (Detail)
4.1 IR-LED-Treiber (Konstantstromquelle)
Funktionsprinzip
Hybride PNP/NPN-Topologie für präzisen, modulierten IR-Puls (38 kHz). Die Stromquelle stellt sicher, dass bei wechselnder Batteriespannung der LED-Strom konstant bleibt (→ reproduzierbare Reichweite).
Stromeinstellung
Der Sollstrom wird über \(R_{set}\) definiert:
Beispiele:
| \(I_{\text{LED}}\) | \(R_{set}\) | Einsatz |
|---|---|---|
| 0,5 A | 1,30 Ω | Standard/Nahkampf |
| 1,0 A | 0,65 Ω | Hohe Reichweite (SFH 4550) |
| 2,0 A | 0,33 Ω | Pulsbetrieb (extreme Leistung) |
| 3,0 A | 0,22 Ω | Scharfschütze (Oslon Black) |
Thermik: Bei 38-kHz-Modulation (Duty-Cycle ~30 %) ist \(P_{\text{avg}} = R_{set} \cdot I^2_{\text{LED}} \cdot DC\) → deutlich unter Peak. \(R_{set}\) muss aber Spitzenstrom verkraften → impulsfeste Typen (Metallschicht, Drahtwiderstand).
Headroom & Akkuwahl
Minimalspannung für stabile Regelung:
| \(I_{\text{LED}}\) | \(V_f\) (typ.) | \(V_{\text{CC,min}}\) | Akku |
|---|---|---|---|
| 0,5 A | 2,0 V | 3,65 V | 1S (nur voll geladen) |
| 1,0 A | 2,4 V | 4,05 V | 2S empfohlen |
| 2,0 A | 2,8 V | 4,45 V | 2S erforderlich |
| 3,0 A | 3,2 V | 4,85 V | 2S erforderlich |
1S ungeeignet für >1A
1S-Akkus brechen unter Last auf 3,4–3,6 V ein → Regelung versagt, Reichweite bricht ein. 2S liefert auch bei Teilentladung (7,0 V) genug Headroom.
4.2 Adressierbare LEDs (WS2812B)
Anforderung: 5V-Versorgung, aber Daten-Pegel kompatibel mit nRF52840 (3.3V Logic).
Level-Shift: SN74AHCT1G125 (3.3V → 5V, Single-Gate); schnell genug für WS2812-Timing (800 kHz).
Serienwiderstand: ~330 Ω nach dem Shifter → dämpft Reflexionen auf der Data-Leitung, verhindert Überschwinger.
Layout: Data-Leitung kurz halten; bei mehreren LEDs in Serie: Bypass-Kondensator (100 nF + 10 µF) pro 3–5 LEDs.
4.3 Audio-Verstärker (MAX98357A)
Ziel: Klare Schuss- und Sprach-Ausgabe mit minimalem Aufwand und geringer CPU-Last.
Architektur: I2S Class-D Verstärker – DAC + Endstufe integriert, filterlose Topologie (wenige Bauteile).
- Schnittstelle: I2S (digital); Audio-Stream per EasyDMA vom nRF52840 → CPU bleibt frei für Game Logic.
- Leistung: ~3.2 W @ 4Ω – laut genug für Outdoor-Einsatz.
- Effizienz: ~90 % → Akku-schonend; geringer Ruhestrom im Idle.
- Layout: Kurze, symmetrische Leitungen zu Speaker-Terminals; separate Ground-Plane; Entkopplung (10 µF + 100 nF) nahe VDD-Pin.
4.4 Flash-Speicher (QSPI)
Aufgabe: Audio-Files (Schuss-FX, Ansagen) und Spiel-Logs (optional Treffer-Historie).
- Technik: QSPI-NOR-Flash (z.B. W25Q128JV, GD25Q16C); 1.8 V oder 3.3 V; XIP-fähig (Execute-in-Place für Code möglich).
- Kapazität: 8–16 MB; reicht für ~3 min @ 22 kHz oder ~1.5 min @ 44 kHz (16 bit mono). Empfehlung: 22 kHz – höhere Sample-Rate bringt bei Outdoor-Speaker kaum Mehrwert.
- Interface: QSPI (4-Bit parallel); nRF52840 unterstützt DMA-basierten Zugriff → schnelle Reads ohne CPU-Last.
- Layout: Flash nahe am MCU (< 5 cm Leitungslänge); Differenzen in Trace-Längen < 1 mm; saubere Ground-Plane; JEDEC-ID beim Boot prüfen.
4.5 Akku-Überwachung (Fuel Gauge)
Prinzip: Spannungsteiler + ADC für 2S-Akkus (0–8.4 V) → Software-basierte Ladezustandsschätzung (kein dediziertes Fuel-Gauge-IC nötig).
Schaltungskomponenten:
| Bauteil | Wert | Funktion |
|---|---|---|
| \(R_1\) | 100 kΩ | Spannungsteiler – oberer Zweig |
| \(R_2\) | 47 kΩ | Spannungsteiler – unterer Zweig (→ ADC) |
| \(C_1\) | 100 nF | Tiefpass-Glättung am ADC-Eingang |
Softwarelogik:
- ADC-Konvertierung: 12-bit ADC liest \(V_{\text{div}}\) (max. 3.3 V bei VRef = 3.3 V).
- Rückrechnung: \(V_{\text{bat}} = V_{\text{adc}} \cdot \frac{R_1 + R_2}{R_2} = V_{\text{adc}} \cdot 3.13\)
- Mapping: Lookup-Table oder linear interpoliert:
- 8.4 V → 100 % (voll geladen)
- 7.4 V → ~50 % (nominal)
- 6.0 V → 0 % (Schutzschaltung aktiv)
Kalibrierung: Einmalig bei Produktion: Spannung an bekanntem Referenzpunkt messen, Offset/Gain in NVS speichern.
5. Bauteil-Übersicht & Empfehlungen
Konsolidierte Liste der Schlüsselkomponenten mit konkreten Part-Vorschlägen. Detaillierte BOMs folgen in separaten Docs (Waffe/Weste/Leader).
| Kategorie | Bauteil/Funktion | Vorschlag | Alternativen | Anmerkung |
|---|---|---|---|---|
| MCU | Mikrocontroller | nRF52840 | — | Zephyr-Support, BLE+Thread |
| Energie | 2S-Akku | Li-Po 7.4V, 1000–2000 mAh | — | Kapazität je nach Gerät |
| Zellenschutz | HY2120-CB + FS8205A | DW01A + 8205A | OV/UV/OC-Protection | |
| Lade-IC | IP2326 (2S Balancing) | TP4056 (nur 1S) | USB-C, Balancing integriert | |
| Buck 5V | MP2315, TPS62130 | — | 1.5 A, >1 MHz Schaltfrequenz | |
| LDO 3.3V | MCP1826, AMS1117-3.3 | XC6206P332MR | Low-Noise für RF, < 0.5V Dropout | |
| IR | IR-LED | SFH 4550, Oslon Black | TSAL6400 | 940 nm, >50 m Reichweite |
| IR-Empfänger | TSOP4838, TSOP38438 | VS1838B | 38 kHz Demodulator, 5V Supply | |
| LED-Treiber | PNP/NPN diskret | IRL530 (Logic-FET) | Konstantstrom, PWM-fähig | |
| Level-Shifter IR | AO4300A (N-Ch MOSFET) | BSS138, 2N7002 | 5V → 3.3V, invertierend | |
| LED | Adressierbare | WS2812B (5050) | SK6812, APA102 | 5V, ~60 mA/LED @ weiß |
| Level-Shift | SN74AHCT1G125 | 74HCT245 (8-Kanal) | 3.3V → 5V, single-gate | |
| Audio | Class-D Amp | MAX98357A | PAM8302, TPA2005D1 | I2S, 3.2W @ 4Ω |
| Speaker | 4Ω, 3–5W | 8Ω (lower SPL) | Outdoor-tauglich | |
| Speicher | QSPI Flash | W25Q128JV (16 MB) | GD25Q16C (2 MB) | NOR-Flash, 3.3V |
| Feedback | Solenoid | 6V Open Frame | — | Rückstoss direkt ab Batterie |
| Muzzle LED | Weiß/Gelb, 1W+ | Cree XP-E2 | Sichtbar bei Tag | |
| Passiv | \(R_{\text{set}}\) (IR) | 0.22–1.3 Ω, 3W | Metallschicht, Draht | Impulsfest |
| Spannungsteiler | 100k + 47k, 1% | 0.1% für Präzision | Fuel Gauge | |
| Mechanik | Stecker | JST-XH (2.54mm) | Molex PicoBlade | Verriegelnd, 3–5 Pole |
| Taster | Omron B3F, Alps SKQG | Cherry MX (größer) | Trigger, Reload |
Hinweise:
- IR-LED: Oslon Black für extreme Reichweite (3A-Betrieb), SFH 4550 für Standard (1–2A).
- Audio: MAX98357A ist quasi-Standard; Alternativen (PAM8302) haben höheren THD, aber OK für SFX.
- Flash: 16 MB erlauben ~6 min Audio @ 22 kHz – gut für zukünftige Erweiterungen (z.B. mehrsprachige Ansagen).
- Stecker: JST-XH ist weit verbreitet und günstig; Molex PicoBlade kompakter, aber teurer.
5.1 IR-LEDs
| Typ | Leistung | Bemerkungen |
|---|---|---|
| SFH 4725S | 3W | Standardmodell für 940nm Vorteile: Sehr bewährt, gute Effizienz |
| SFH 4726S | 3W | Ähnlich wie die 4725S, aber oft mit einer leicht anderen internen Linsencharakteristik (breiterer Abstrahlwinkel ohne externe Optik). |
| SFH 4727AS | 5W | Das 940-nm-Gegenstück zu deiner 4715AS. Vorteil: Für deine 3-A-Pulse im Outdoor-Modus die stabilste Wahl. Sie verträgt die hohen Pulsströme thermisch am besten. |
| SFH 4725AS | 3W | Eine neuere "A"-Revision mit verbesserter Wärmeableitung. |
Es wird empfohlen, entsprechende "STAR"-Aluplatinen zu verwenden, um die Wärmeableitung zu garantieren.
IR-Empfänger
| Typ | Bemerkungen |
|---|---|
| TSOP34456 / TSOP38456 | Der Standard für 56 kHz. Charakteristik: Besitzt eine sehr agressive AGC (Automatic Gain Controll) Problem: Bei extrem starken Signalen im Nahbereich kann die AGC "zumachen" und die Hüllkurve verzerren. |
| TSSP4056 / TSSP77056 | Vorteil: Er hat eine feste Verstärkung (Fixed Gain). Er regelt also nicht ab, wenn das Signal stark wird. Nutzen: Das Signal bleibt viel konstanter als bei bei einem TSOP. |
Stand: 04.01.2026
Software-Konzept & Spielablauf
Dieses Dokument beschreibt die Software-Architektur, die Rollenverteilung und die Kommunikationsabläufe des Lasertag-Systems.
Überblick
- Architektur: Leader als BLE/Thread-Brücke, Westen als Spiel-Authority für Health/Regeln, Waffen als Sensor/Aktor.
- Funk: BLE für Provisionierung/App, Thread (CoAP/UDP) für Spielverkehr, IR für Treffer-Übertragung.
- Prinzip: Dezentraler Trefferentscheid (auf der Weste) mit optionalem Live-Ticker zum Leader; Leader hält Spielstatus und sammelt Logs.
1. System-Rollen & Hardware-Typen
Das System basiert auf nRF52840-Chips, die über OpenThread (802.15.4) kommunizieren. Am wichtigsten dabei ist die Kommunikation von der Weste zur Waffe, da die Waffe beim Death des Spielers sofort deaktiviert werden muss. Die OpenThread Message Priority soll verwendet werden, um die Weste-Waffe-Kommunikation zusätzlich zu optimieren. Multicasts: Low, Weste -> Waffe enable und disable: High, Rest normal.
A. Leader Box (Game Controller)
- Funktion: Zentrale Spielsteuerung, Zeitgeber, Gateway zur Smartphone-App.
- Modi (wählbar via DIP-Schalter):
00Leader: Spielleiter, BLE-Gateway, sammelt Punkte.01Repeater: Router im Mesh zur Reichweitenverlängerung (z.B. am Baum).11Base: Interaktives Ziel (z.B. für "Domination"-Modus).
- Hardware: IR-Empfänger, RGB-LEDs, BLE aktiv.
B. Weste (Player Hub)
- Funktion: Zentrale Einheit des Spielers. Verwaltet Lebenspunkte, empfängt Treffer, steuert Audio.
- Sensoren: Kopf (3x: Stirn, Links, Rechts), Brust/Rücken, Seiten (Schultern/Arme).
- Kommunikation: Hält die Verbindung zur Waffe (Pairing) und zum Leader.
C. Waffe
- Funktion: Aussenden der IR-Signale, haptisches Feedback, Muzzle-Flash.
- Typen: Pistole, Sniper, Shotgun (unterschiedliche IR-Leistung/Fokussierung).
- Logik: Sendet "Schuss"-Events, empfängt "Sperren"-Befehle von der Weste (wenn tot).
2. Provisionierung & Setup (Lobby-Phase)
Bevor das Spiel startet, müssen Geräte dem Netzwerk beitreten und Spielern zugeordnet werden.
Schritt 1: Netzwerk-Beitritt (Provisioning)
- Szenario: Neue Hardware wird zum ersten Mal verwendet.
- Ablauf:
- Spielleiter verbindet App via BLE mit Leader Box.
- Leader Box öffnet das Thread-Netzwerk (Commissioning).
- Neue Geräte (Waffe/Weste) werden in den Pairing-Modus versetzt (z.B. Tastenkombination).
- Geräte erhalten Netzwerk-Credentials und treten dem Mesh bei.
Schritt 2: Spieler-Konfiguration (Assignment)
- Ziel: Zuordnung von Hardware zu einer logischen
PlayerIDund einemTeam. - Identifikation: Jedes nRF52-Board hat eine eindeutige EUI-64 (MAC).
- Ablauf:
- App scannt QR-Code oder NFC-Tag an der Weste/Waffe (Payload: EUI-64 Adresse).
- App sendet Konfiguration an Leader Box:
EUI-64 -> {PlayerID, Team, Name}. - Leader Box löst EUI-64 in aktuelle IPv6-Adresse auf (Neighbor Table / Discovery).
- Leader sendet Konfigurations-Paket (CoAP Unicast) an das Gerät:
- Weste: Erhält PlayerID, TeamID, MaxHealth, evtl. Rolle.
- Waffe: Erhält Damage-Wert, Nachladezeit, Magazingröße, Waffentyp.
- Geräte speichern ID/Team im RAM (optional NVS für Persistenz bei Neustart).
Provisioning – Sequenzdiagramm
sequenceDiagram
actor User as Spielleiter
participant App
participant Leader
participant Weste
participant Waffe
User->>App: Verbindung via BLE
App->>Leader: Thread-Credentials (BLE)
Leader->>Leader: Öffne Mesh für Provisioning
User->>Weste: Pairing-Modus aktiviert
User->>Waffe: Pairing-Modus aktiviert
Weste->>Leader: Beitritt ins Thread-Netz
Waffe->>Leader: Beitritt ins Thread-Netz
User->>App: QR-Code Weste scannen
App->>Leader: PlayerID 1, Team=Rot, Name="Alice"
Leader->>Weste: Konfig (CoAP PUT /game/conf)
Weste->>Weste: Speichere PlayerID=1, Team=Rot
User->>App: QR-Code Waffe scannen
App->>Leader: PlayerID 1, Waffentyp=Pistol
Leader->>Waffe: Konfig (CoAP PUT /game/wconf)
Waffe->>Waffe: Speichere Damage=10, ReloadTime=500ms
App->>Leader: "Spieler bereit?"
Leader->>App: Ping alle Knoten → OK
3. Spielablauf (Game Loop)
Phase A: Vorbereitung
- Leader: Sendet Multicast
GAME_STATE_LOBBY. - Geräte: Spielen Idle-Animation ab, warten auf Start.
- Check: Leader kann "Ping" an alle senden, um Anwesenheit zu prüfen.
Phase B: Countdown
- Leader: Sendet Multicast
GAME_START_COUNTDOWN(Payload: 10 sek). - Westen: Zählen laut herunter: "10, 9, 8...".
Phase C: Spiel läuft (Running)
- Status:
GAME_STATE_RUNNING. - Aktion: Waffen sind entsperrt. Sensoren sind scharf.
- Treffer-Logik (Dezentral):
- Waffe A schießt (sendet IR-Frame mit
Type=Hit,ShooterID,Damage,CRC8). - Weste B empfängt IR-Signal über TSOP4838, validiert CRC.
- Weste B berechnet Schaden (unter Berücksichtigung von Trefferzone-Multiplikator).
- Weste B zieht Lebenspunkte ab.
- Feedback: Weste B leuchtet/vibriert/spielt Sound ("Ugh!").
- Speicherung: Weste B speichert den Treffer im internen Flash-Log (
Timestamp, ShooterID, Zone, Damage). - (Optional) Weste B sendet UDP-Paket an Leader für Live-Scoreboard (Best Effort).
- Waffe A schießt (sendet IR-Frame mit
Warum kein MilesTag2?
MilesTag2 wurde als Basis erwogen, ist aber mit ~40 ms Frame-Zeit und starren 8-Bit-IDs zu langsam und unflexibel. Unser Custom-Protokoll bietet:
- Kürzere Frames: ~36 ms vs. ~40 ms (weniger anfällig für Zittern/Bewegung)
- Flexible Type-Codes: Hit/Heal/PowerUp/Admin in einem Format
- CRC8-Prüfung: >99.5% Fehlerrate-Erkennung bei Sonnenlicht
- Variable Daten: 13-Bit-Payload anpassbar pro Type
Details siehe IR-Protokoll-Spezifikation.
- Heilquellen: Medic/Medipack-IR (breit gestreut, kurze Reichweite, negativer Damage) werden als Heilung interpretiert.
- Zonen-Effekte: Bases/Joiner senden
game/zone(Link-Local, Hop=1); Weste prüft RSSI-Schwelle und addiert HP-Deltas (friend/foe) nach optionalem Warn-Countdown.
Phase D: Spieler eliminiert
- Bedingung: Lebenspunkte <= 0.
- Weste B:
- Spielt "Dead"-Sound.
- Leuchtet dauerhaft in Teamfarbe (oder aus).
- Sendet CoAP Unicast an eigene Waffe:
CMD_DISABLE.
- Respawn (falls aktiv):
- Nach Zeitablauf (z.B. 30s) sendet Weste an Waffe:
CMD_ENABLE. - Lebenspunkte werden zurückgesetzt.
- Nach Zeitablauf (z.B. 30s) sendet Weste an Waffe:
Phase E: Spielende & Auswertung
- Leader: Sendet Multicast
GAME_STATE_FINISHED. - Ablauf:
- Alle Spieler kommen zusammen.
- Spielleiter drückt in App "Daten abrufen".
- Leader Box fragt nacheinander (Unicast) alle bekannten Westen ab:
GET /game/log. - Westen übertragen ihre Treffer-Historie.
- App berechnet Highscores, MVP, Trefferquoten.
Game Loop – Zustandsautomat (Weste)
stateDiagram-v2
[*] --> Idle
Idle --> Lobby: GAME_STATE_LOBBY empfangen
Lobby --> Countdown: GAME_START_COUNTDOWN empfangen
Countdown --> Running: Countdown = 0
Running --> Running: IR-Hit empfangen → Damage abzug, Log
Running --> Dead: Health <= 0
Dead --> Dead: Waffe CMD_DISABLE senden
Dead --> Running: Respawn aktiviert (CMD_ENABLE)
Running --> Finished: GAME_STATE_FINISHED
Dead --> Finished: GAME_STATE_FINISHED
Finished --> [*]
note right of Running
- Health-Tracking
- Treffer-Log
- LED/Audio-Feedback
end note
note right of Dead
- Waffe gesperrt
- LED dauerhaft an
- Optional Respawn-Timer
end note
4. Spielmodi
Die Logik für die Modi wird primär auf den Westen implementiert (Regelwerk), gesteuert durch Flags vom Leader.
Team Deathmatch
- Klassisch Rot gegen Blau.
- Friendly Fire konfigurierbar (an/aus).
- Siegbedingung: Meiste Kills oder wenigste Tode nach Zeitablauf.
Last Man Standing (Free-for-all)
- Jeder gegen Jeden.
- Keine Teams (oder jeder hat eigene Team-ID).
- Kein Respawn.
Zombie (Infected)
- Start: 1 Spieler ist "Zombie" (Team Grün), Rest "Mensch" (Team Rot).
- Regel:
- Zombie hat unendlich Leben (oder sehr viel).
- Mensch hat 1 Leben.
- Wird Mensch getroffen -> Wechselt Team zu Zombie (Weste leuchtet grün, Waffe sendet ab jetzt Zombie-ID).
- Wird Zombie getroffen -> "Stunned" (Waffe 5s gesperrt).
- Ziel: Überleben bis Zeitablauf.
Base Domination
- Hardware: Leader-Boxen im Modus
11(Base) verteilt im Gelände. - Ablauf:
- Spieler schießt auf Base-Box.
- Base-Box wechselt Farbe zu Teamfarbe des Schützen.
- Base-Box zählt Zeit für das haltende Team.
- Am Ende fragt Leader alle Base-Boxen ab: "Wie lange warst du Rot? Wie lange Blau?".
Medic & Heal Packs
- Rollen:
- Medic-Spieler: Rolle
Medicin der Spieler-Konfiguration; deren Waffe feuert ein "Heal-IR" mit breiter Streuung und sehr kurzer Reichweite. - Medipacks (Objekte): Aktiv durch Tastendruck; senden erst nach Button-Press ein Heal-IR mit breiter Streuung.
- Medic-Spieler: Rolle
- Wirkung:
- Heal-IR ist als eigene Damage-Class kodiert (negativer Schaden → Heilung).
- Reichweite absichtlich klein (< 2–3 m) und stark gestreut, damit Heilen ein Positionierungs-Feature bleibt.
- Treffer-Logik auf der Weste interpretiert diese Pakete als Heilung (+HP, begrenzt durch
health_max).
- Balancing:
- Heal pro Tick konfigurierbar; zusätzlich wählbar: max. Anzahl Heilungen, Mindest-Pause zwischen Heilungen oder beides.
- Friendly-only oder auch Self-Heal konfigurierbar.
- Hardware: Kann identisch zur Waffe sein (Trigger/Taster, Audio). Beispiele: "nääääääään" bei Cooldown, "Sorry, I am empty" wenn Magazin leer ist.
Zonen-Effekte (Bases/Joiner)
- Joiner/Base-Knoten können zusätzlich periodisch CoAP-Pakete auf Ressource
zonesenden (Link-Local, Hop-Limit=1). - Anwendungsfälle:
- Heal-Zonen: In Team-Homebase oder dominierten Bases → Team-Mitglieder werden geheilt, Gegner ggf. geschwächt.
- Kill-/Radiation-Zonen: Schadenszonen mit Warn-Countdown; Gegner müssen den Bereich verlassen.
- Respawn-Zonen: Spielmodi, in denen tote Spieler nur in der eigenen Home-Zone oder einer dominierten Base respawnen dürfen; die Zone validiert Präsenz (RSSI) und erlaubt dann Respawn.
- Paketfelder (Beispiel):
team: 2, friend: +20, foe: -10, rssi: -70, warn: 5team: Besitzer der Zone (z.B. 2 = Blau)friend: HP-Delta für eigenes Team (+20 Heal)foe: HP-Delta für andere Teams (-10 Schaden)rssi: Mindest-RSSI (dBm) für Wirksamkeit (z.B. -70 → nur nahe dran)warn: Anzahl Aussendungen als Warnung, bevor der Effekt scharf wird
- Instant-Death Beispiel:
team: 0, friend: -128, foe: -128, warn: 0, rssi: -60→ Jeder Empfänger mit RSSI besser als -60 dBm fällt sofort auf 0 HP.
5. Technische Spezifikation (API & Datenstrukturen)
Die Kommunikation erfolgt über CoAP (UDP). Alle Payloads sind binär (__packed C-Structs, Little Endian für nRF52, Network Byte Order für Interop optional).
5.1 CoAP Endpunkte
| Ressource | Methode | Typ | Beschreibung | Payload |
|---|---|---|---|---|
game/state |
PUT | Multicast | Globaler Spielstatus (Start/Stop/Zeit) | struct game_state_packet |
game/conf |
PUT | Unicast | Konfiguration für einen Spieler | struct player_config_packet |
game/wconf |
PUT | Unicast | Konfiguration für eine Waffe | struct weapon_config_packet |
game/hit |
POST | Unicast | Treffer-Meldung (Live-Ticker) | struct hit_report_packet |
game/log |
GET | Unicast | Abruf der gespeicherten Trefferdaten | struct flash_log_entry[] |
game/zone |
PUT | Multicast (Link-Local, Hop=1) | Zonen-Effekte (Heal/Kill) aus Bases/Joinern | struct zone_effect_packet |
| game/powerup | PUT | Unicast | Power-Up-Event von Weste zu Waffe | struct powerup_event_packet |
| game/pup_log | GET | Unicast | Abruf aller Power-Up-Aktivierungen | struct powerup_log_entry[] |
5.2 Datenstrukturen
Spielstatus (Multicast)
struct game_state_packet {
uint8_t state; // 0=Idle, 1=Lobby, 2=Running, 3=Paused, 4=Finished
uint8_t game_mode; // 0=TeamDeathmatch, 1=Zombie, 2=Base
uint16_t game_id; // Rolling Counter zur Deduplizierung
uint16_t remaining_sec; // Restzeit in Sekunden
uint8_t flags; // Bitmaske (z.B. FriendlyFire)
} __packed;
Spieler-Konfiguration (Provisioning)
struct player_config_packet {
uint16_t player_id; // Logische ID (1-65535)
uint8_t team_id; // 0=Rot, 1=Blau, 2=Grün (Zombie), ...
uint8_t role; // 0=Soldier, 1=Medic, 2=Sniper
uint8_t damage_out; // Basis-Schaden der Waffe
uint8_t health_max; // Maximale Lebenspunkte
char name[16]; // Anzeigename (null-terminated)
} __packed;
Waffen-Konfiguration
struct weapon_config_packet {
uint8_t base_damage; // Schaden pro Schuss
uint16_t reload_time_ms;// Zeit für Nachladen
uint8_t magazine_size; // Schuss pro Magazin
} __packed;
Treffer-Bericht (Live & Log)
struct hit_report_packet {
uint32_t timestamp; // ms seit Spielstart
uint16_t shooter_id; // ID des Schützen (aus IR)
uint16_t victim_id; // Eigene ID
uint8_t damage; // Erlittener Schaden
uint8_t hit_location; // 0=Unbekannt, 1=Kopf, 2=Brust, 3=Rücken
} __packed;
// Zonen-Effekte (link-local, Hop-Limit=1)
struct zone_effect_packet {
uint8_t team_id; // Besitzer der Zone (0=neutral)
int8_t friend_delta; // HP-Delta für eigenes Team (z.B. +20 Heal)
int8_t foe_delta; // HP-Delta für andere Teams (z.B. -10 Schaden)
int8_t rssi_thresh_dbm; // Mindest-RSSI für Wirksamkeit (z.B. -70 dBm)
uint8_t warn_count; // Anzahl Warn-Pakete vor scharfem Effekt
} __packed;
// Power-Up Event (von Weste zu Waffe nach IR-Empfang)
struct powerup_event_packet {
uint16_t player_id; // Betroffener Spieler
uint8_t powerup_type; // 0=SHIELD, 1=DAMAGE_BOOST, 2=HEAL, 3=SPEED, etc.
uint16_t duration_sec; // Dauer des Power-Ups in Sekunden
uint8_t persist_on_death; // 0=verfällt bei Death, 1=bleibt auch nach Respawn
uint16_t damage_multiplier;// Für Damage-Boost: z.B. 150 = 1.5x
int8_t health_delta; // Für Heal-Pack: z.B. +50
} __packed;
// Power-Up Log Entry (für Auswertung nach Spielende)
struct powerup_log_entry {
uint32_t timestamp; // ms seit Spielstart
uint16_t player_id; // Spieler, der Powerup aktiviert hat
uint8_t powerup_type; // Type des PU
uint8_t source; // 0=IR-Station, 1=Buzzer-Box, 2=Leader-Kommando, 3=Zone
} __packed;
6. IR-Protokoll (Physical Layer)
Das IR-Signal nutzt eine 38kHz Trägerfrequenz (NEC-ähnlich).
6.1 Standard-Shooting-Payload (32-bit)
Payloads von Waffen und Medics (Protokoll-ID 0xAA):
- Bits 24-31:
Protokoll-ID(0xAAfür Standard-Spiel-IRs) - Bits 8-23:
Shooter ID(16-bit, eindeutig für jeden Spieler) - Bits 4-7:
Team-Code(4-bit, 0=Rot, 1=Blau, 2=Grün, 3=Neutral) - Bits 0-3:
Damage Class(4-bit, 0-15, definiert Basis-Schaden; 0xFF = Healing)
Beispiel: ShooterID=42, Team=Rot, Damage=10 → 0xAA002A0A
6.2 Power-Up-Payload (32-bit)
Payloads von Power-Up-Stationen und Buzzer-Boxen (Protokoll-ID 0xBB):
- Bits 24-31:
Protokoll-ID(0xBBfür Power-Up-Signale) - Bits 16-23:
Power-Up-Type(0=SHIELD, 1=DAMAGE_BOOST, 2=HEAL_PACK, 3=SPEED, 4=WEAKNESS, 5=AMMO, etc.) - Bits 0-15:
Power-Up-Flags(optional: Duration-Encoding, Persist-Flag, etc.)
Beispiel (Shield): 0xBB000000 (Duration wird in CoAP-Paket übertragen)
7. Power-Ups & Items (erweitert)
Hardw are-Seite
- Power-Up-Stationen (Deckel-Boxen): nRF52840 + Magnetschalter + IR-Sender + Status-LED; Cooldown intern gesteuert (z.B. 30s).
- Buzzer-Power-Ups: nRF52840 + Druckschalter + schwacher IR-Sender (2-3m) + LED; optional Thread-Logging.
- Beide Typen können zentral über Leader konfiguriert werden.
Software-Seite
- IR-Dekodierung: Weste prüft Protokoll-ID (
0xAAvs.0xBB) und ruft Handler auf. - Weste: Speichert aktive Power-Ups lokal (Typ, Duration, Multiplier); sendet via
game/powerupUnicast zu Waffe; prüftpersist_on_deathbei Respawn. - Waffe: Empfängt
game/powerup, appliziert Damage-Multiplier auf nächste Schüsse. - Power-Up-Typen:
- SHIELD: Blockiert 1 Treffer
- DAMAGE_BOOST: Multipliziert ausgehenden Schaden (z.B. 1.5x)
- HEAL_PACK: Instant +HP
- SPEED: Schneller schießen (Cooldown-Reducer)
- WEAKNESS: Negativ, mehr Schaden empfangen
- AMMO: Medipack-Magazine aufladen
- Leader-Kommandos: Kann zentrale Power-Ups auslösen (Underdog-Bonus, Base-Schuss-Trigger, Turbo-Round) → Multicast/Unicast.
- Logging: Alle Power-Up-Aktivierungen in Flash-Log speichern, abrufbar via
game/pup_lognach Spielende.
8. Weste – Zustandsautomat (detailliert)
Übergangstabelle
| Von | Nach | Auslöser | Aktion | Bedingung |
|---|---|---|---|---|
| Idle | Lobby | CoAP GAME_STATE_LOBBY |
LED idle-Animation, warten auf Start | Multicast vom Leader |
| Lobby | Countdown | CoAP GAME_START_COUNTDOWN |
Audio-Countdown 10→1 sec, Countdown-Timer init | Payload: 10 sek |
| Countdown | Running | Countdown = 0 | Health reset, Treffer-Sensor aktivieren, Waffe unlock | Timer lokal abgelaufen |
| Running | Dead | Health <= 0 | LED rot/aus, Dead-Sound, CoAP CMD_DISABLE an Waffe | Nach IR-Hit-Verarbeitung |
| Dead | Running | Respawn-Timer = 0 | Health reset, CoAP CMD_ENABLE an Waffe, Sensor on | Optional; Config-abhängig |
| Running | Finished | CoAP GAME_STATE_FINISHED |
Alle Daten sichern, Logs speichern, LED Idle | Multicast vom Leader |
| Dead | Finished | CoAP GAME_STATE_FINISHED |
Logs speichern (optional), LED Idle | Multicast vom Leader |
Treffer-Verarbeitung im Running-State (Flowchart)
flowchart TD
A["IR-Signal empfangen"] --> B{"ShooterID prüfen"}
B -->|Friendly Fire off + eigenes Team| C["Signal verwerfen"]
B -->|Valid| D["Hit Location extrahieren"]
D --> E["Zone-Multiplikator anwenden"]
E --> F["Effektiven Schaden berechnen"]
F --> G["Health -= Damage"]
G --> H{"Health > 0?"}
H -->|Ja| I["LED blinken + Sound"]
I --> J["Hit ins Flash-Log schreiben"]
J --> K["Optional: CoAP Hit-Report an Leader"]
H -->|Nein| L["Health = 0"]
L --> M["LED rot, Dead-Sound"]
M --> N["CoAP CMD_DISABLE an Waffe"]
N --> O["Zustand → Dead"]
Übergangsbeschreibungen
- Idle → Lobby: App oder Spielleiter triggert über BLE. Leader sendet
GAME_STATE_LOBBYMulticast. Weste wechselt in Warte-Modus. - Lobby → Countdown: Leader sendet
GAME_START_COUNTDOWNmit Sekunden-Payload (z.B. 10). Weste zählt laut herunter. - Countdown → Running: Timer lokal = 0 → Weste aktiviert Sensoren, Health voll, Waffe freigegeben.
- Running → Dead: Health <= 0 nach Treffer-Verarbeitung → Waffe gesperrt, LED rot/aus, Respawn-Timer optional starten.
- Dead → Running: Optional nur wenn Respawn aktiv. Leader schickt evtl. Kommando oder Timer läuft ab.
- {Running|Dead} → Finished: Leader sendet
GAME_STATE_FINISHED→ Weste speichert finale Logs, bereit für Auswertung.
9. Offene Punkte & Annahmen
- Sicherheitsmodell: Keine Auth auf IR, minimale Auth/ACL auf BLE/Thread? (noch zu klären).
- Anti-Cheat: Debounce IR, Rate-Limit pro Waffe, Rolling Codes möglich.
- Telemetrie: Sampling-Intervall für Live-Ticker und Limit pro Sekunde definieren.
Gameplay & Spielmodi (für Spieltester)
Dieses Dokument ist bewusst leicht verständlich. Ziel: Euch zeigen, was wir vorhaben, und euer Feedback einsammeln. Welche Ideen habt ihr? Was macht am meisten Spaß?
Kurz erklärt
- Wir spielen draußen mit Westen (zeigen Treffer) und Waffen (schießen mit Infrarot-Licht, ungefährlich für Augen).
- Jede Weste gehört zu einem Team (z.B. Rot, Blau, Grün). Treffer werden von der Weste gezählt.
- Ein Spiel dauert meist 5–15 Minuten – danach gibt es Punkte/Statistiken.
Rollen
- Leader-Box: Startet/stoppt das Spiel, zeigt den Countdown, sammelt Punkte.
- Weste: Zeigt Treffer, Leben und Teamfarbe.
- Waffe: Schießt IR-Licht. Manche Waffen fühlen sich unterschiedlich an (z.B. Sniper = weiter, Shotgun = breiter Streukegel).
- Medic: Kann heilen (kurze Distanz, breiter Strahl). Hat begrenzte Heilungen oder eine Pause zwischen Heilungen.
- Medipack: Kleines Gerät, das per Taste eine Heilung auslöst (kurze Distanz, breite Streuung), mit Limit oder Cooldown. Kann Sounds abspielen (z.B. „nääääääään“ bei Cooldown, „Sorry, I am empty“ wenn leer).
Spielmodi (Ideen)
- Team Battle (Standard): Zwei Teams, wer mehr Treffer/Eliminierungen hat, gewinnt.
- Base Domination: Stationen auf dem Feld. Wer länger eine Station hält, sammelt Punkte.
- King of the Hill: Ein Spot in der Mitte – wer ihn hält, sammelt Punkte.
- Zombie: Wenige starten als Zombie. Wird ein Mensch getroffen, wird er zum Zombie. Menschen gewinnen, wenn sie bis zum Ende überleben; Zombies, wenn alle infiziert sind.
- Medic Rescue: Nur Medics können Teamkameraden wiederbeleben. Heilen geht nur aus nächster Nähe.
- Capture the Flag (leicht): Eine „Flagge“ (Box) muss ins eigene Lager gebracht werden. Treffer lassen dich die Flagge fallen.
- Stealth Runde: Wenig Licht, niedrige Lebenspunkte, kürzere Spielzeit – mehr Spannung.
Zonen-Ideen
- Heal-Zone: In der eigenen Basis heilt man langsam.
- Kill-/Radiation-Zone: Warnung, dann langsam Schaden, wenn man zu lange drin bleibt.
- Respawn-Zone: Tote Spieler müssen in ihre Home-Zone oder eine eroberte Base zurück, um neu zu starten.
Power-Ups & Items
Power-Ups können auf mehrere Arten ausgelöst werden – alle machen das Spiel strategischer und spannender!
Aktive Power-Up-Stationen (mit Deckel)
- Hardware: Box mit Deckel (Sensor), Status-LED, IR-Sender
- So funktioniert's:
- Spieler öffnet den Deckel → LED blinkt grün
- Spieler schießt drauf (mit Waffe oder Medipack)
- Box dekodiert den Schuss (Shooter-ID aus IR) und sendet das Power-Up per Thread Unicast an genau diesen Spieler (CoAP
game/powerup). - Weste des Schützen bekommt das Power-Up und schickt das Kommando an ihre Waffe: „20s kein Schaden" oder „20s doppel Damage". IR-Fallback nur, falls kein Mesh verfügbar.
- Box hat Cooldown (z.B. 30s), dann kann sie wieder aktiviert werden
- Beispiel-Power-Ups: 🛡️ Shield (1 Treffer blocken), ⚡ Damage-Boost (+50%), 🩹 Health-Pack, 🔫 Ammo-Reload (für Medics)
- Teamplay: Eine Person öffnet, die andere schießt drauf → beide profitieren
Passive Power-Up-Boxen (Buzzer)
- Hardware: Kleine Box mit Buzzer-Button, schwacher IR-Sender, Cooldown-LED
- So funktioniert's:
- Spieler drückt Buzzer → schwaches IR-Signal wird gesendet
- Weste in unmittelbarer Nähe empfängt es (z.B. nur 2m Reichweite)
- Power-Up gilt 15-30s, dann lädt es wieder auf
- Vorteil: Keine großen Boxen nötig, schneller zu nutzen, mehr Platz für Power-Ups auf dem Feld
Zonen-Effekte (von Basen/Joinern)
- Hardware: Leader-Box sendet periodisch ein Netzwerk-Signal (Thread)
- So funktioniert's:
- Base von Team Rot sendet: „Wer von Team Rot in 15m Reichweite? Ihr bekommt +50% Damage für 30s"
- Weste prüft: „Bin ich von Team Rot? Bin ich nah bei der Base (RSSI-Check)? → Ja, aktiviere +50% Damage"
- Weste sendet zu ihrer Waffe: „Nächste 30s: 1.5x Damage"
- Beispiele:
- Heal-Zone: In der eigenen Basis langsam heilen
- Danger-Zone: In gegnerischer Base nehmt ihr 1s Schaden
- Team-Präsenz-Effekt: Wenn alle Spieler eines Teams in Reichweite der eigenen Base sind → alle erhalten +100% Angriff für 10s
Strategische/zentrale Power-Ups (vom Spielleiter)
Der Spielleiter kann jederzeit per Tastendruck ein Team-weites Power-Up auslösen:
- Underdog-Bonus: Wenn ein Team unterliegt → 20s Unsterblichkeit (kein Schaden) für das schwächere Team
- Base-Schuss-Trigger: Wenn Spieler A die gegnerische Base beschießt → Team A erhält 30s Shield
- Turbo-Round: Alle Spieler beide Teams: 60s lang 2x Damage und 2x Speed
- Spannungs-Booster: Letzten 30s vor Spielende: Alle Spieler können nicht sterben (Shield-Dauerbuff)
Wie Power-Ups wirken
| Power-Up | Effekt auf Weste | Effekt auf Waffe | Dauer |
|---|---|---|---|
| 🛡️ Shield | 1 Treffer wird abgeblockt | — | 20–40s |
| ⚡ Damage-Boost | Weniger Schaden empfangen (Attacken weniger effektiv) | Doppelter Schaden beim Schießen | 20–60s |
| 🩹 Heal-Pack | +50 Health sofort | — | Sofort |
| 🏃 Speed | Schneller reagieren | Schneller schießen (kürzerer Cooldown) | 15–30s |
| 💀 Weakness | Mehr Schaden empfangen | Weniger Schaden beim Schießen | 10–20s |
| 🔫 Ammo | Medipack wird aufgeladen | — | 1 Magazin |
Wichtig: Power-Ups können so konfiguriert werden, dass sie:
- Bei Spieler-Death verfallen (Shield ist weg nach Tod)
- Oder beim Respawn erhalten bleiben (wichtig bei strategischen Boosts)
Regeln
- Nur eine Box pro Power-Up-Typ pro Spieler gleichzeitig
- Wenn zwei Power-Ups aktiv sind (z.B. Shield UND Damage-Boost) → beide wirken
- Fallen in Dead-State weg (Power-Up hat keine Wirkung, wenn Spieler schon tot ist)
Match-Ablauf (typisch)
1) Alle wählen Team/Waffe/Rolle (optional Medic).
2) Leader startet den Countdown (laut & Licht).
3) Spiel läuft 5–15 Minuten.
4) Am Ende sammelt die Leader-Box die Treffer-Logs.
5) Punkte/Statistik ansehen: Kills, Tode, Heals, wer die Base wie lange hielt.
Safety & Fair Play
- Kein Rennen auf rutschigem Boden; keine Schläge/Checks.
- Treffer zählen nur über IR (kein „Nachrufen“).
- Headshots sind erlaubt, aber vorsichtig zielen (IR ist ungefährlich, trotzdem fair bleiben).
- Respekt: Keine Beleidigungen, kein Schummeln (z.B. Sensor verdecken).
Was sagt ihr?
- Welche Modi gefallen euch am besten?
- Wollt ihr mehr Spannung (wenig HP) oder längere Matches (viel HP)?
- Mehr Action (Shotgun/Spread) oder mehr Taktik (Sniper/Shield/Medic)?
- Findet ihr Heal-/Kill-Zonen spannend oder nervig?
- Braucht es mehr Sounds/Lichter, oder ist es so schon genug?
Schreibt eure Ideen/Anmerkungen dazu – wir bauen das ein!
Mobile App
Um das Spiel zu steuern, wird eine mobile App entwickelt. Sie soll anfangs für Android verfügbar sein. Wenn die Hürden nicht zu groß sind, wird auch eine iOS-Version in Betracht gezogen. Dazu wird die Entwicklung in Flutter stattfinden.
Übersicht
Der grundsätzliche Ablauf sieht so aus:
flowchart TD
start([App-Start])
choose_mode{Modus wählen?}
choose_leader[Weg A: Leader (Spiel)]
maintenance[Weg B: Ausrüstung warten]
check_state{Leader-Status?}
lobby[2a. Lobby-Phase]
game[2b. Spiel-Phase]
evaluation[2c. Auswertungs-Phase]
start-->choose_mode
choose_mode-->|Leader / Spiel|choose_leader
choose_mode-->|Wartung|maintenance
maintenance-->|Zurück|choose_mode
choose_leader-->check_state
check_state-->|Kein Spiel läuft|lobby
check_state-->|Spiel läuft|game
check_state-->|Spiel abgeschlossen|evaluation
lobby-->|Spiel starten|game
game-->|Spiel abbrechen|lobby
game-->|Spielende|evaluation
evaluation-->|Neues Spiel|lobby
classDef phase fill:#eef4ff,stroke:#6c8be0,stroke-width:1px,color:#0d1b2a
class lobby,game,evaluation phase
1. Leader bestimmen
- Beim Start der App wird geschaut, ob der zuletzt gewählte Game-Leader über BLE erreichbar ist.
- Ist der nicht erreichbar, wird nach allen verfügbaren Leader-Knoten gescannt und zur Auswahl angeboten.
Startbildschirm: Zwei-Wege-Strategie
- Weg A (Spiel-Modus): Leader wählen, in die Lobby-Phase wechseln, Parameter verteilen und ein Spiel starten.
- Weg B (Wartungs-Modus): Waffe oder Weste direkt auswählen, um Standalone-Einstellungen vorzunehmen (Name ändern, Firmware prüfen, Batteriestand checken), ohne den Leader hochzufahren.
UI-Vorschlag Start-Screen - Oben: Spiel-Leiter finden (Primär): Fokus auf Leader-Knoten, großes Funkturm-Icon, Einstieg in den Game-Flow (Lobby -> Spiel -> Auswertung). - Unten: Meine Ausrüstung (Sekundär): Liste aller anderen gefundenen BLE-Geräte (Westen, Waffen), dezentere Darstellung, Ziel: Schnellkonfiguration einzelner Hardware-Komponenten.
2a. Lobby-Phase
In der Lobby-Phase wird das Spiel vorbereitet: Spielmodus wählen, Teams/Spieler zuordnen und Parameter konfigurieren.
Thread-Netzwerk & Provisionierung
- Thread-Parameter werden am Leader konfiguriert und über das Thread-Netzwerk an alle verbundenen Geräte verteilt
- Im Hintergrund läuft permanent ein BLE-Scan nach neuen Geräten
- Neu gefundene Geräte werden automatisch mit den Thread-Parametern provisioniert und dem Netzwerk hinzugefügt
Geräte-Discovery & Monitoring
- Die App triggert den Leader in regelmäßigen Abständen, eine "Who is there"-Multicast-Abfrage im Thread-Netzwerk auszuführen
- Zurückgemeldete Geräte werden in einer Liste erfasst
- Beim ersten Erscheinen eines Geräts werden dessen Parameter abgerufen: Name, Typ, spezifische Eigenschaften
- Geräte, die sich über einen bestimmten Zeitraum nicht mehr melden, werden ausgegraut
- Auto-Synchronisation: Meldet ein Gerät Spieler- oder Team-Zuordnungen (z.B. "Spieler 3, Team 2"), die in der App noch nicht existieren, werden diese automatisch angelegt (z.B. "Spieler 3" und "Team 2"), um Konfigurationskonflikte zu vermeiden
Benutzeroberfläche
Geräteliste:
- Zeigt alle verfügbaren Geräte an
- Antippen eines Geräts blendet zusätzliche Icons ein:
- Verbindungsstatus: Zeigt an, ob das Gerät kürzlich gesehen wurde
- Zuordnungsstatus: Ob das Gerät einem Spieler/Team zugeordnet ist
- Identifikation: Lässt das Gerät blinken (3x) oder LED atmen zur physischen Identifikation
- Entfernen: Nur aktiv bei ausgegrauten Geräten
- Einstellungen: Geräteeinstellungen bearbeiten
Teamliste:
- Zeigt alle Teams an
- Antippen erweitert die Ansicht mit den zugewiesenen Spielern
Spielerliste:
- Zeigt alle Spieler mit Teamzuordnungsstatus an
- Spieler können angelegt, gelöscht und umbenannt werden
Spielkonfiguration
- Spielkonfigurationen können gespeichert und später neu geladen werden
- Alle Spielparameter (Dauer, Respawns, etc.) sind hier einstellbar
Spielstart-Bedingungen
Das Spiel kann nur gestartet werden, wenn folgende Bedingungen erfüllt sind:
- Alle Westen und Waffen sind zugeordnet
- Jede Weste ist genau einem Spieler zugeordnet (und umgekehrt)
- Der Spielmodus ist gesetzt und konfiguriert
- Alle Basen, Power-Ups etc. sind konfiguriert
- Kein ausgegrautes Gerät ist vorhanden
- Je nach Spielmodus: Alle Spieler sind einem Team zugeordnet
Sind nicht alle Bedingungen erfüllt, werden die Gründe angezeigt.
Übergang zur Spiel-Phase
- Beim "Spiel starten" wird eine zufällige Spiel-ID generiert und an den Leader übermittelt
- Die aktuelle Spielkonfiguration wird gespeichert
- Dadurch kann das Spiel auch nach App-Neustart ausgewertet werden
2b. Spiel-Phase
- Laufendes Spiel: Status/Timer anzeigen, optional Live-Events (Treffer, Bases) und Admin-Aktionen wie "Spiel abbrechen".
- Spielende erfolgt je nach Modus (Timer, Score, Objective) und wechselt in die Auswertungs-Phase.
- Sollte die App während der Spielphase gestartet werden, wird geprüft, ob die Spiel-ID auf dem gewählten Leader-Knoten mit der gespeicherten ID zusammenpasst. Wenn ja, schaltet sich die App auf das Spiel auf. Wenn nein, meldet die App einen Fehler, dass eine Verbindung aufgrund eines laufenden Spieles nicht möglich ist. Je nach Spielmodus ist es der App möglich, in das Spielgeschehen einzugreifen (zum Beispiel Power-Ups senden etc.).
2c. Auswertungs-Phase
- Geräte auslesen, Scores sammeln, Rangliste erzeugen und anzeigen.
- Optionen: "Neues Spiel" führt zurück in die Lobby; Export/Share der Ergebnisse möglich.
- Sollte die App während der Auswertungsphase gestartet werden, wird geprüft, ob die Spiel-ID auf dem gewählten Leader-Knoten mit der gespeicherten ID zusammenpasst. Wenn ja, schaltet sich die App auf das Spiel auf. Wenn nein, meldet die App einen Fehler, dass die Spiel-ID unbekannt ist und somit eine Auswertung nicht möglich ist.
Eine Auswertung erfolgt erst, wenn alle Geräte, die zur Auswertung erforderlich sind, abgerufen werden konnten. Ist das innerhalb einer bestimmten Zeit nicht möglich, wird dem Benutzer angezeigt, welche fehlen. Er kann dann dafür sorgen, dass diese in Reichweite kommen und die Auswertung abschliessen.
Spezifikationen
IR-Kommunikationsprotokoll
Übersicht
Das Infrarot-Kommunikationsprotokoll basiert auf Pulse-Distance-Codierung mit 38 kHz Träger und ist ähnlich Sony SIRC, aber optimiert für die Anforderungen des Lasertag-Systems. Das Protokoll bietet robuste Übertragung mit CRC-Fehlerprüfung und kurzen Frame-Zeiten (~36 ms).
Physikalische Schicht
| Parameter | Wert | Anmerkung |
|---|---|---|
| Trägerfrequenz | 38 kHz | Standard für TSOP48xx Empfänger |
| Tastgrad (Duty Cycle) | 50 % | Konfigurierbar (25–75 %) |
| Modulation | PWM mit Pulse-Distance-Codierung | Hardware-basiert via nRF52 PWM-Peripheral |
| Empfänger | TSOP4838 (kompatibel) | Active-Low Ausgang, 38 kHz Bandpass |
Timing-Spezifikation
| Symbol | Dauer | Toleranz | Beschreibung |
|---|---|---|---|
| Start Burst | 4 × Basistakt (Standard 2400 µs) | ±200 µs | Träger AN, Frame-Synchronisations-Impuls |
| Gap | 1 × Basistakt (Standard 600 µs) | ±100 µs | Träger AUS nach Start (optional, konfigurierbar) |
| Mark | 1 × Basistakt (Standard 600 µs) | ±100 µs | Träger AN (konstant für alle Bits) |
| Space 0 | 1 × Basistakt (Standard 600 µs) | ±100 µs | Träger AUS für logisch 0 |
| Space 1 | 2 × Basistakt (Standard 1200 µs) | ±150 µs | Träger AUS für logisch 1 |
Basistakt: CONFIG_IR_PROTO_BASE_US (Standard 600 µs). Alle Zeiten ergeben sich daraus per Multiplikatoren (IR_PROTO_*_MULT).
Bit-Codierung
Bit 0: [Mark 600µs] + [Space 600µs] = 1.2 ms
Bit 1: [Mark 600µs] + [Space 1.2ms] = 1.8 ms
Beispiel-Wellenform (3 Bits: 101)
Träger-Timing für Bits 1-0-1:
| Segment | Dauer | State | Bit-Wert |
|---|---|---|---|
| Mark | 600 µs | AN | |
| Space 1 | 1200 µs | AUS | 1 (1.8 ms total) |
| Mark | 600 µs | AN | |
| Space 0 | 600 µs | AUS | 0 (1.2 ms total) |
| Mark | 600 µs | AN | |
| Space 1 | 1200 µs | AUS | 1 (1.8 ms total) |
Frame-Format
Alle Frames bestehen aus 24 Bits, übertragen MSB-first:
title Frame | Feld | Start Burst + Gap | Type | Data | CRC8 | |------|-------------------|------|------|------| | Dauer | (Start: 4× Basis) + (Gap: 1× Basis) | 3 Bits | 13 Bits | 8 Bits | | Funktion | Synchronisation | Frame-Typ | Payload | Fehlerprüfung | | Summe | – | – | – | 24 Bits |
Gesamte Frame-Zeit: ~39 ms bei Standardwerten (Start 2400 µs + Gap 600 µs + 24 × 1.5 ms Bit-Durchschnitt). Mit angepasstem Basistakt/Multi skaliert alles linear.
Type-Feld (3 Bits)
| Wert | Typ | Beschreibung |
|---|---|---|
000 |
Hit | Standard-Schuss |
001 |
Heal | Medic-Heilung oder Health Pack |
010 |
PowerUp | Station Power-Up Grant |
011 |
Admin | System-Steuerbefehle |
100–111 |
Reserviert | Zukünftige Nutzung |
Data-Feld (13 Bits) – Type-abhängig
Hit-Frame (000)
| Bit-Range | Feld | Wertbereich | Beschreibung |
|---|---|---|---|
| 0–7 | Shooter ID | 0–255 | ID des Schützen (256 mögliche Spieler) |
| 8–12 | Damage | 0–31 | Schadenpunkte (0 = kein Schaden, 31 = Maximum) |
Heal-Frame (001)
| Bit-Range | Feld | Wertbereich | Beschreibung |
|---|---|---|---|
| 0–7 | Healer ID | 0–255 | ID des Heilers (Medic oder Station) |
| 8–12 | Amount | 0–31 | Heilpunkte wiederhergestellt |
PowerUp-Frame (010)
| Bit-Range | Feld | Wertbereich | Beschreibung |
|---|---|---|---|
| 0–7 | Station ID | 0–255 | Stations-ID, die das Power-Up gewährt |
| 8–12 | PowerUp | 0–31 | Power-Up-Typ-Identifier |
Admin-Frame (011)
| Bit-Range | Feld | Wertbereich | Beschreibung |
|---|---|---|---|
| 0–12 | Command Data | 0–8191 | Implementierungsdefinierte Steuerbefehle |
CRC-Feld (8 Bits)
- Algorithmus: CRC-8-CCITT
- Polynom: 0x07 (x⁸ + x² + x + 1)
- Initialwert: 0x00
- Eingabe: Type (3 Bits) + Data (13 Bits) = 16 Bits
- Zweck: Fehlererkennung bei Bitfehlern durch Umgebungslicht oder Interferenzen
Erwartete Fehlererkennungsrate: >99.5 % für Einfach- oder Doppelbitfehler
Beispiel-Frame
Hit von Spieler 42 mit 10 Schaden:
Type: 000 (Hit)
Data: 00101010 01010 (ShooterID=42, Damage=10)
CRC8: [berechnet aus obigen Daten]
Kompletter Frame (24 Bits):
000 00101010 01010 CCCCCCCC
│ │ │ └─ CRC8
│ │ └─ Damage (10)
│ └─ Shooter ID (42)
└─ Type (Hit)
Übertragungsabfolge:
- Start Burst: 2400 µs Träger AN
- Bit 0 (Type): 600 µs Mark + 600 µs Space
- Bit 1 (Type): 600 µs Mark + 600 µs Space
- Bit 2 (Type): 600 µs Mark + 600 µs Space
- ... (21 weitere Bits)
- Ende: Träger AUS
Empfänger-Implementierung
Hardware-Anforderungen
- TSOP4838 verbunden mit GPIO mit Interrupt-Fähigkeit
- Steigende/fallende Flanken-Erkennung
- Timer zur Messung der Space-Dauern
Software-State-Machine
- IDLE: Auf Start Burst warten (2000–2800 µs)
- SYNC: Start Burst erkannt, Vorbereitung zur Bit-Empfang
- DATA: Space nach jedem Mark messen, 24 Bits dekodieren
- VALIDATE: CRC prüfen, Frame bei Gültigkeit verarbeiten
Timing-Toleranzen
- Breite Toleranzbereiche (±17–33 %) kompensieren Interrupt-Jitter und Träger-Drift
- Fehlgeschlagener CRC zeigt beschädigten Frame an → stille Verwerfung
- Empfänger resynchronisiert automatisch beim nächsten Start Burst
Konfigurierbare Parameter
Die Protokoll-Timing kann via Kconfig für verschiedene Umgebungen angepasst werden:
CONFIG_IR_SEND_CARRIER_HZ: Trägerfrequenz (30–45 kHz)CONFIG_IR_SEND_DUTY_CYCLE_PERCENT: PWM Tastgrad (25–75 %)CONFIG_IR_PROTO_BASE_US: Basistakt (300–1000 µs)CONFIG_IR_PROTO_START_MULT: Startburst-Faktor (2–8)CONFIG_IR_PROTO_GAP_MULT: Gap-Faktor (0–4; 0 = kein Gap)CONFIG_IR_PROTO_MARK_MULT: Mark-Faktor (1–2)CONFIG_IR_PROTO_SPACE0_MULT: Space0-Faktor (1–3)CONFIG_IR_PROTO_SPACE1_MULT: Space1-Faktor (1–4)
Die Standardwerte folgen Sony SIRC Timing-Konventionen für bewährte Zuverlässigkeit.
Leistungscharakteristiken
| Metrik | Wert |
|---|---|
| Frame-Zeit | ~39 ms |
| Datenrate | ~410 bit/s |
| Max. Spieler-IDs | 256 |
| Reichweite (Außen) | ~50–100 m (abhängig von Sender-Leistung und Umgebungslicht) |
| Fehler-Erkennung | >99.5 % via CRC-8 |
| Störfestigkeit | Hoch (Hardware-Bandpass 38 kHz) |
Bluetooth LE Protokoll
Zu dokumentieren: BLE-Charakteristiken für Spielstatus-Synchronisierung, Team-Zuordnung, etc.
Projekt: Lasertag Kommunikation (nRF52840)
Dieses Projekt beschreibt ein modulares Lasertag-System basierend auf dem nRF52840. Es nutzt Dynamic Multiprotocol (Bluetooth Low Energy & OpenThread), um eine nahtlose Kommunikation zwischen einer Weboberfläche (Game-Leader), Westen und Waffen zu ermöglichen.
System-Architektur
- Game-Leader: Fungiert als Brücke (Bridge). Er kommuniziert via BLE (Web Bluetooth) mit einem Smartphone/Laptop und via Thread (CoAP/UDP) mit den Spielgeräten.
- Westen/Waffen: Reine Thread-Knoten, die Befehle empfangen und Statusmeldungen (Treffer) senden.
- Bases: Stationäre Geräte, die Spielmodi wie "Capture the Base" ermöglichen.
Geplante Verzeichnisstruktur
Das Projekt ist als Zephyr-Workspace-Struktur angelegt, um Code-Redundanz zu vermeiden.
lasertag/
├── apps/ # Applikations-spezifischer Code (Binaries)
│ ├── leader_base/ # Kombinierte Firmware für Game-Leader & Bases
│ ├── weapon/ # Firmware für die Waffen-Einheit
│ └── vest/ # Firmware für die Westen-Einheit
├── libs/ # Gemeinsame Bibliotheken (Zephyr Module)
│ ├── ble_mgmt/ # BLE Services & Advertising Profile
│ ├── thread_mgmt/ # CoAP Server/Client & Thread Stack Setup
│ └── game_logic/ # Treffer-Logik & Spielstatus-Management
├── boards/ # Custom Board Definitions (PCBs)
├── common/ # Gemeinsame Header (UUIDs, CoAP-Pfade, IDs)
└── scripts/ # Hilfsskripte (Provisioning, Shell-Tools)
Roadmap
Entwicklungs-Roadmap (Schritt-für-Schritt)
Diese Roadmap führt vom nRF52840DK bis zum fertigen Produkt.
Phase 1: Die "Tisch"-Basis (PoC)
Ziel: Stabile Thread-Kommunikation und IR-Signalerzeugung verifizieren.
- Zephyr Setup: Installation des nRF Connect SDK (NCS) und VS Code.
- Custom Board Definition: Board-File anlegen, das die Pins des nRF52840DK auf die geplanten Funktionen mappt (PWM für IR, GPIO für Buttons).
- Thread Mesh: Minimalen OpenThread-Stack aufsetzen. Ein DK als Leader (FTD), einer als Child. UDP/CoAP-Ping bei Knopfdruck.
- IR-Engine: Custom IR-Protokoll (pulse-distance, 38 kHz) mit nrfx_pwm + PPI implementieren. Signal mit Oszilloskop/Logic Analyzer verifizieren. Sicherstellen, dass Funk die IR-Engine nicht stört. Hinweis: MilesTag2 wurde verworfen zugunsten eines eigenen, kürzeren Protokolls mit CRC8 (siehe Spezifikationen).
Phase 2: Der "Prototyp" (Integration)
Ziel: Einbindung von Audio und Solenoid.
- Audio: MAX98357A am I2S-Interface. WAV-Player, der Samples aus internem Flash abspielt.
- Solenoid-Treiber: MOSFET-Schaltung auf Breadboard. PWM-Logik für "Kick" (100% für 30ms) und "Hold" (30%). Thermik des Solenoids testen.
- Haptik-Sync: Audio ("Bang!") und Solenoid-Kick in der Software synchronisieren.
Phase 3: Die "Optik & Sensorik" (Physik)
Ziel: Reichweitentest.
- Linsen-Test: Oslon Black LED auf Star-Platine + Carclo/LEDiL-Linse justieren (Abstand exakt einhalten).
- Sensor-Array: TSOP-Sensoren für die Weste verdrahten. Outdoor-Test bei Sonne. Software-Filterung anpassen, um Reflexions-Fehler zu minimieren.
Phase 4: Die "App & Logik" (System)
Ziel: Spielsteuerung.
- BLE Gateway: Leader-Box sendet Thread-Statusdaten via BLE an Smartphone (Web Bluetooth API oder nRF Toolbox App).
- Web App: Einfache HTML/JS-Seite, die via Web Bluetooth API mit dem Leader spricht, um ein Spiel zu starten ("Start Game" als Thread Broadcast).
Phase 5: Das "Custom PCB" (Hardware)
Ziel: Miniaturisierung.
- Schaltplan: Schaltungen in KiCad übertragen. Trennung von Analog-GND (Sensoren) und Power-GND (Solenoid) beachten.
- Layout: Antennenplatzierung/Impedanz anpassen; Testpunkte für SWD vorsehen (Debug).
Grobe Zeitachsen (Richtwerte)
| Phase | Ziel | Dauer (Richtwert) | Abhängigkeiten |
|---|---|---|---|
| 1 | Thread + IR PoC | 1–2 Wochen | HW: nRF52840DK, Logic-Analyzer |
| 2 | Audio + Solenoid | 2 Wochen | Phase 1 abgeschlossen |
| 3 | Optik & Sensorik | 1–2 Wochen | Phase 2 abgeschlossen, Outdoor-Tests |
| 4 | App & Steuerung | 1–2 Wochen | Phase 2 abgeschlossen, BLE-Gateway vorhanden |
| 5 | Custom PCB | 3–4 Wochen | Phasen 1–3 verifiziert, Schaltplan stabil |
Technologie-Stack
- Hardware: nRF52840 (DK & Custom PCBs)
- OS: Zephyr RTOS via nRF Connect SDK
- Funk: OpenThread (Mesh) & BLE 5.x
- Protokolle: CoAP über UDP, GATT (BLE)
- Frontend: Web Bluetooth API (JavaScript)
Lizenz
Dieses Projekt steht unter der Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0).
- Kurzfassung: creativecommons.org/licenses/by-nc-sa/4.0/
- Volltext: creativecommons.org/licenses/by-nc-sa/4.0/legalcode
- Repo-Lizenzdatei: gitea.iten.pro/edi/lasertag/src/branch/main/LICENSE
Nutzung zu kommerziellen Zwecken ist nicht gestattet. Bearbeitungen muessen gleichartig geteilt werden und eine Namensnennung erfordern.