Konzepte angepasst und erweitert
All checks were successful
Deploy Docs / build-and-deploy (push) Successful in 13s

This commit is contained in:
2026-01-03 11:20:42 +01:00
parent d7f004ee72
commit 06af540be3
10 changed files with 891 additions and 121 deletions

View File

@@ -1,3 +1,15 @@
# Eriks Lasertag
Das hier beschreibt das ganze Lasertag-Gedöns.
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.
- Planung: Zephyr-Workspace-Struktur und Roadmap.

View File

@@ -0,0 +1,172 @@
# 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), Vibrationsmotor, Audio (Schussgeräusche, "Leer"-Klicken).
* **Eingabe:** Abzug (Trigger), Nachladen (Taster), optionaler Schalter für Feuermodus.
* **Stromversorgung:** 2S LiPo (7.4V) mit Step-Down auf 3.3V.
### 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.
## 2. Energie & Verkabelung
* **Akkus:** 2S LiPo (7.4V) als Standard; 1S nur für Tests/Low-Power-Aufbau.
* **Spannungswandler:** Abwärtswandler auf 3.3V für Logik, separater Treiberpfad für IR-LEDs (hoher Pulsstrom, niedriger Duty-Cycle).
* **Verkabelung Weste:** Sternförmige Abgänge zu Sensorgürteln (Kopf, Brust/Rücken, Schultern) mit verriegelnden Steckern; Datensignal (LED) + Versorgung gebündelt.
* **Absicherung:** Polyfuse pro Ast empfohlen, Verpolschutz an jedem Modulanschluss.
## 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) | | ✓ | ✓ | 510 | Verteilt auf Kopf/Torso/Schulter |
| RGB-LED (WS2812B) | | ✓ | ✓ | 13 | Teamfarbe + Status |
| Vibrationsmotor | ✓ | | | | Taktiles Feedback Schuss |
| 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
### 4.1 LED-Treiber
#### Grundkonzept
Der LED-Treiber realisiert eine präzise Konstantstromquelle als Hybridschaltung aus PNP- und NPN-Transistoren. Diese Architektur ermöglicht eine stabile und effiziente Ansteuerung von Infrarot-Leuchtdioden mit definierten Stromwerten.
![LED DRIVER](../img/concept_hardware_led_driver.svg)
#### Stromeinstellung
Der Zielstrom wird über den Messwiderstand $R_{set}$ eingestellt. Die Berechnung folgt der Formel:
$$R_{set} = \frac{0,65V}{I_{LED}}$$
Die folgenden Tabelle zeigt typische Stromwerte, die erforderlichen Widerstände und die entsprechenden Anwendungsfälle:
| Stromstärke ($I_{LED}$) | Widerstand ($R_{set}$) | Ausgangsleistung ($P_{min}$) | Einsatzbereich |
| :--- | :--- | :--- | :--- |
| 0,5 A | 1,30 $\Omega$ | 0,5 W | Standard / Nahkampf |
| 1,0 A | 0,65 $\Omega$ | 1,0 W | Hohe Reichweite (SFH 4550) |
| 2,0 A | 0,33 $\Omega$ | 2,0 W | Extrem hohe Leistung (Pulsbetrieb) |
| 3,0 A | 0,22 $\Omega$ | 3,0 W | Scharfschützen-Modus (Oslon Black) |
#### Thermische Betrachtung
Im Lasertag-Betrieb werden die Infrarot-Signale hochfrequent moduliert (beispielsweise mit 38 kHz). Dies führt zu einem signifikant geringeren mittleren Wärmeeintrag in den Messwiderstand als eine kontinuierliche Strombelastung suggeriert:
$$P_{avg} = (R_{set} \cdot I_{LED}^2) \cdot \text{Duty Cycle}$$
!!! info "Bedeutung der Widerstandsspezifikation"
Obwohl die Duty-Cycle-Modulation die durchschnittliche Verlustleistung reduziert, müssen Widerstände für $R_{set}$ für die auftretenden Stromspitzen ausgelegt sein. Wir empfehlen impulsfeste Typen (Metallschicht- oder Drahtwiderständen), um die Stromspitzen bis zu 3 A ohne Materialermüdung zu verkraften.
#### Spannungsversorgung und Headroom-Anforderungen
Die Konstantstromquelle benötigt eine Mindestverspannung zwischen Versorgung und Ausgang, um präzise die Sollstromstärke zu halten. Diese sogenannte Headroom-Spannung errechnet sich aus:
$$V_{CC} > V_{f(\text{LED})} + 0,65V + 1,0V_{\text{Headroom}}$$
**Kritischer Aspekt bei Lithium-Ionen-Akkus:** Die Akkuspannung sinkt während der Entladung kontinuierlich. Unterschreitet $V_{CC}$ den erforderlichen Schwellwert, bricht die Regelung zusammen und der LED-Strom kann die Sollvorgabe nicht mehr erreichen. Dies führt zu einer drastischen Reduktion der Reichweite des Senders.
Die Minimalspannung für stabilen Betrieb wird bestimmt durch:
$$V_{CC,\text{min}} = V_{f(\text{LED})} + V_{R_{set}} + V_{\text{Headroom}}$$
Die folgende Tabelle zeigt die erforderlichen Minimalspannungen für verschiedene Stromvorgaben und die Eignung unterschiedlicher Akkusysteme:
| Stromstärke ($I_{LED}$) | Typ. LED-Spannung ($V_{f}$) | Erforderliche Spannung ($V_{CC,\text{min}}$) | Akku-Empfehlung |
| :--- | :--- | :--- | :--- |
| 0,5 A | ~2,0 V | 3,65 V | 1S (nur bei voller Ladung) |
| 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 |
!!! warning "1S-System: Einschränkungen unter Last"
Ein einzelner 1S Li-Po Akku sinkt unter hohen Stromlasten schnell auf 3,4 V bis 3,6 V ab. Für konstante Reichweite bei Strömen ab 1 A ist ein 2S-System daher technisch überlegen.
#### 2S-Akkusystem: Komplexität und Lösungsansätze
Ein 2S-Akkusystem bietet zwar Spannungsstabilität, erfordert jedoch anspruchsvollere Schutz- und Überwachungsfunktionen:
- **Laden:** Moderne 2S-Ladechips mit integriertem Balancing (beispielsweise der IP2326) ermöglichen vereinfachte Ladevorgänge.
- **Zellenschutz:** Ein Zellenschutz-IC wie der HY2120-CB in Kombination mit einem Dual-Channel MOSFET (beispielsweise FS8205A) verhindert Über- und Unterspannungszustände.
- **Fuel Gauge:** Spezielle Fuel-Gauge-ICs für 2S-Systeme sind selten oder komplex. Als praktische Alternative wird eine Spannungsteiler-ADC-Messung zur Ladezustandsabschätzung eingesetzt. Der Spannungsteiler muss durch ein Schaltgattersystem steuerbar sein.
### 4.2 Audio-Driver
Um Audio (z. B. Schussgeräusche, Sprachansagen) von einem externen Flash abzuspielen, ohne die CPU zu belasten, müssen wir auf Hardware-DMA-Transfer setzen.
Die beste Lösung für ein kompaktes, batteriebetriebenes System wie eine Lasertag-Waffe ist ein I2S Class-D Verstärker. Dieser kombiniert DAC und Verstärker in einem Chip und wird digital angesteuert.
Der "Industriestandard" für Mikrocontroller ist da der MAX98357A:
* **Schnittstelle**: I2S (Digital)
* **Leistung**: 3.2W an 4Ω (sollte mehr als genug laut sein)
* **Vortiele**:
* Kein externer DAC nötig
* Direkter Anschluss an den Lautsprecher
* Extrem Energieeffizient (schont die Akkus)
* Filterlose Class-D Architektur (wenige Bauteile)
* **CPU-Last**: Minimal, da der nRF52840 die Daten per EasyDMA schickt (zur Anpassung der Lautstärke wird etwas Rechenleistung benötigt)
### 4.3 Akku-Überwachung (Fuel Gauge)
#### Spannungsmessung bei 2S-Akkus
Für 2S-Akkusysteme mit Spannungen bis 8,4 V wird die Akkuspannung über einen Spannungsteiler auf den ADC-Eingangspegel reduziert. Dieser Messwert dient zur Ladezustandsabschätzung und Fehlerdiagnose.
#### Schaltungskomponenten
| Komponente | Wert | Funktion |
| :--- | :--- | :--- |
| $R_1$ | 100 k$\Omega$ | Spannungsteiler oberer Zweig |
| $R_2$ | 47 k$\Omega$ | Spannungsteiler unterer Zweig |
| $C_1$ | 100 nF | Glättungskondensator am ADC-Eingang |
#### Softwarelogik
Die Ladezustandsbestimmung erfolgt in drei Schritten:
1. **ADC-Konvertierung:** Der Rohwert des ADC-Eingangs wird eingelesen.
2. **Spannungsrückrechnung:** Die Realspannung wird aus dem ADC-Wert berechnet: $V_{\text{bat}} = V_{\text{adc}} \cdot \frac{R_1 + R_2}{R_2}$
3. **Ladezustand-Mapping:** Die Batteriespannung wird auf einen prozentualen Ladezustand abgebildet:
* **6,0 V** → 0 % (Entladungsschutz aktiv)
* **8,4 V** → 100 % (vollständig geladen)
* Für höhere Genauigkeit können mehrere Messpunkte verwendet und linear interpoliert werden.
*Stand: 03.04.2025*

View File

@@ -0,0 +1,322 @@
# 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.
### A. Leader Box (Game Controller)
* **Funktion:** Zentrale Spielsteuerung, Zeitgeber, Gateway zur Smartphone-App.
* **Modi (wählbar via DIP-Schalter):**
* `00` **Leader:** Spielleiter, BLE-Gateway, sammelt Punkte.
* `01` **Repeater:** Router im Mesh zur Reichweitenverlängerung (z.B. am Baum).
* `11` **Base:** 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:**
1. Spielleiter verbindet App via BLE mit **Leader Box**.
2. Leader Box öffnet das Thread-Netzwerk (Commissioning).
3. Neue Geräte (Waffe/Weste) werden in den Pairing-Modus versetzt (z.B. Tastenkombination).
4. Geräte erhalten Netzwerk-Credentials und treten dem Mesh bei.
### Schritt 2: Spieler-Konfiguration (Assignment)
* **Ziel:** Zuordnung von Hardware zu einer logischen `PlayerID` und einem `Team`.
* **Identifikation:** Jedes nRF52-Board hat eine eindeutige **EUI-64** (MAC).
* **Ablauf:**
1. App scannt **QR-Code** oder **NFC-Tag** an der Weste/Waffe (Payload: EUI-64 Adresse).
2. App sendet Konfiguration an Leader Box: `EUI-64 -> {PlayerID, Team, Name}`.
3. Leader Box löst EUI-64 in aktuelle IPv6-Adresse auf (Neighbor Table / Discovery).
4. 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.
5. Geräte speichern ID/Team im RAM (optional NVS für Persistenz bei Neustart).
### Provisioning Sequenzdiagramm
```mermaid
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):**
1. Waffe A schießt (sendet IR-Code mit `ShooterID` + `Damage`).
2. Weste B empfängt IR-Signal.
3. Weste B berechnet Schaden (unter Berücksichtigung von Trefferzone-Multiplikator).
4. Weste B zieht Lebenspunkte ab.
5. **Feedback:** Weste B leuchtet/vibriert/spielt Sound ("Ugh!").
6. **Speicherung:** Weste B speichert den Treffer im internen Flash-Log (`Timestamp, ShooterID, Zone, Damage`).
7. *(Optional)* Weste B sendet UDP-Paket an Leader für Live-Scoreboard (Best Effort).
### 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.
### Phase E: Spielende & Auswertung
* **Leader:** Sendet Multicast `GAME_STATE_FINISHED`.
* **Ablauf:**
1. Alle Spieler kommen zusammen.
2. Spielleiter drückt in App "Daten abrufen".
3. Leader Box fragt nacheinander (Unicast) alle bekannten Westen ab: `GET /game/log`.
4. Westen übertragen ihre Treffer-Historie.
5. App berechnet Highscores, MVP, Trefferquoten.
### Game Loop Zustandsautomat (Weste)
```mermaid
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?".
---
## 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[]` |
### 5.2 Datenstrukturen
#### Spielstatus (Multicast)
```c
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)
```c
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
```c
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)
```c
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;
```
---
## 6. IR-Protokoll (Physical Layer)
Das IR-Signal nutzt eine 38kHz Trägerfrequenz (NEC-ähnlich).
Payload (32-bit):
* `8 bit` Protokoll-ID (Magic Byte zur Unterscheidung von Fernbedienungen)
* `16 bit` Shooter ID
* `8 bit` Info (4 bit Team, 4 bit Damage Class)
## 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)
```mermaid
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_LOBBY` Multicast. Weste wechselt in Warte-Modus.
- **Lobby → Countdown:** Leader sendet `GAME_START_COUNTDOWN` mit 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.

View File

@@ -1,118 +0,0 @@
# Hardware-Konzept
## 1. Systemübersicht
Das Lasertag-System besteht aus einer hierarchischen Architektur, bei der ein Leader-Element mehrere Westeneinheiten mit zugeordneten Waffensystemen steuert.
```mermaid
graph TD
Leader((Leader))
Leader --> Weste1[Weste 1]
Leader --> Weste2[Weste 2]
Weste1 --> WaffeA(Waffe A)
Weste1 --> WaffeB(Waffe B)
Weste2 --> WaffeC(Waffe C)
%% Styling (Optional)
%% style Leader fill:#f96,stroke:#333,stroke-width:2px
%% style Weste1 fill:#bbf,stroke:#333
%% style Weste2 fill:#bbf,stroke:#333 -->
```
## 2. Schaltungskomponenten
### 2.1 LED-Treiber
#### Grundkonzept
Der LED-Treiber realisiert eine präzise Konstantstromquelle als Hybridschaltung aus PNP- und NPN-Transistoren. Diese Architektur ermöglicht eine stabile und effiziente Ansteuerung von Infrarot-Leuchtdioden mit definierten Stromwerten.
![LED DRIVER](img/concept_hardware_led_driver.svg)
#### Stromeinstelling
Der Zielstrom wird über den Messwiderstand $R_{set}$ eingestellt. Die Berechnung folgt der Formel:
$$R_{set} = \frac{0,65V}{I_{LED}}$$
Die folgenden Tabelle zeigt typische Stromwerte, die erforderlichen Widerstände und die entsprechenden Anwendungsfälle:
| Stromstärke ($I_{LED}$) | Widerstand ($R_{set}$) | Ausgangsleistung ($P_{min}$) | Einsatzbereich |
| :--- | :--- | :--- | :--- |
| 0,5 A | 1,30 $\Omega$ | 0,5 W | Standard / Nahkampf |
| 1,0 A | 0,65 $\Omega$ | 1,0 W | Hohe Reichweite (SFH 4550) |
| 2,0 A | 0,33 $\Omega$ | 2,0 W | Extrem hohe Leistung (Pulsbetrieb) |
| 3,0 A | 0,22 $\Omega$ | 3,0 W | Scharfschützen-Modus (Oslon Black) |
#### Thermische Betrachtung
Im Lasertag-Betrieb werden die Infrarot-Signale hochfrequent moduliert (beispielsweise mit 38 kHz). Dies führt zu einem signifikant geringeren mittleren Wärmeeintrag in den Messwiderstand als eine kontinuierliche Strombelastung suggeriert:
$$P_{avg} = (R_{set} \cdot I_{LED}^2) \cdot \text{Duty Cycle}$$
!!! info "Bedeutung der Widerstandsspezifikation"
Obwohl die Duty-Cycle-Modulation die durchschnittliche Verlustleistung reduziert, müssen Widerstände für $R_{set}$ für die auftretenden Stromspitzen ausgelegt sein. Wir empfehlen impulsfeste Typen (Metallschicht- oder Drahtwiderständen), um die Stromspitzen bis zu 3 A ohne Materialermüdung zu verkraften.
#### Spannungsversorgung und Headroom-Anforderungen
Die Konstantstromquelle benötigt eine Mindestverspannung zwischen Versorgung und Ausgang, um präzise die Sollstromstärke zu halten. Diese sogenannte Headroom-Spannung errechnet sich aus:
$$V_{CC} > V_{f(\text{LED})} + 0,65V + 1,0V_{\text{Headroom}}$$
**Kritischer Aspekt bei Lithium-Ionen-Akkus:** Die Akkuspannung sinkt während der Entladung kontinuierlich. Unterschreitet $V_{CC}$ den erforderlichen Schwellwert, bricht die Regelung zusammen und der LED-Strom kann die Sollvorgabe nicht mehr erreichen. Dies führt zu einer drastischen Reduktion der Reichweite des Senders.
Die Minimalspannung für stabilen Betrieb wird bestimmt durch:
$$V_{CC,\text{min}} = V_{f(\text{LED})} + V_{R_{set}} + V_{\text{Headroom}}$$
Die folgende Tabelle zeigt die erforderlichen Minimalspannungen für verschiedene Stromvorgaben und die Eignung unterschiedlicher Akkusysteme:
| Stromstärke ($I_{LED}$) | Typ. LED-Spannung ($V_{f}$) | Erforderliche Spannung ($V_{CC,\text{min}}$) | Akku-Empfehlung |
| :--- | :--- | :--- | :--- |
| 0,5 A | ~2,0 V | 3,65 V | 1S (nur bei voller Ladung) |
| 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 |
!!! warning "1S-System: Einschränkungen unter Last"
Ein einzelner 1S Li-Po Akku sinkt unter hohen Stromlasten schnell auf 3,4 V bis 3,6 V ab. Für konstante Reichweite bei Strömen ab 1 A ist ein 2S-System daher technisch überlegen.
#### 2S-Akkusystem: Komplexität und Lösungsansätze
Ein 2S-Akkusystem bietet zwar Spannungsstabilität, erfordert jedoch anspruchsvollere Schutz- und Überwachungsfunktionen:
- **Laden:** Moderne 2S-Ladechips mit integriertem Balancing (beispielsweise der IP2326) ermöglichen vereinfachte Ladevorgänge.
- **Zellenschutz:** Ein Zellenschutz-IC wie der HY2120-CB in Kombination mit einem Dual-Channel MOSFET (beispielsweise FS8205A) verhindert Über- und Unterspannungszustände.
- **Fuel Gauge:** Spezielle Fuel-Gauge-ICs für 2S-Systeme sind selten oder komplex. Als praktische Alternative wird eine Spannungsteiler-ADC-Messung zur Ladezustandsabschätzung eingesetzt. Der Spannungsteiler muss durch ein Schaltgattersystem steuerbar sein.
### 2.2 Akku-Überwachung (Fuel Gauge)
#### Spannungsmessung bei 2S-Akkus
Für 2S-Akkusysteme mit Spannungen bis 8,4 V wird die Akkuspannung über einen Spannungsteiler auf den ADC-Eingangspegel reduziert. Dieser Messwert dient zur Ladezustandsabschätzung und Fehlerdiagnose.
#### Schaltungskomponenten
| Komponente | Wert | Funktion |
| :--- | :--- | :--- |
| $R_1$ | 100 k$\Omega$ | Spannungsteiler oberer Zweig |
| $R_2$ | 47 k$\Omega$ | Spannungsteiler unterer Zweig |
| $C_1$ | 100 nF | Glättungskondensator am ADC-Eingang |
#### Softwarelogik
Die Ladezustandsbestimmung erfolgt in drei Schritten:
1. **ADC-Konvertierung:** Der Rohwert des ADC-Eingangs wird eingelesen.
2. **Spannungsrückrechnung:** Die Realspannung wird aus dem ADC-Wert berechnet:
$V_{\text{bat}} = V_{\text{adc}} \cdot \frac{R_1 + R_2}{R_2}$
3. **Ladezustand-Mapping:** Die Batteriespannung wird auf einen prozentualen Ladezustand abgebildet:
- **6,0 V** → 0 % (Entladungsschutz aktiv)
- **8,4 V** → 100 % (vollständig geladen)
Für höhere Genauigkeit können mehrere Messpunkte verwendet und linear interpoliert werden.