Added IR Lib, samples and specification
All checks were successful
Deploy Docs / build-and-deploy (push) Successful in 12s
All checks were successful
Deploy Docs / build-and-deploy (push) Successful in 12s
This commit is contained in:
@@ -107,13 +107,23 @@ sequenceDiagram
|
||||
* **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.
|
||||
1. Waffe A schießt (sendet IR-Frame mit `Type=Hit`, `ShooterID`, `Damage`, `CRC8`).
|
||||
2. Weste B empfängt IR-Signal über TSOP4838, validiert CRC.
|
||||
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).
|
||||
|
||||
!!! info "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](../specifications/ir_protocol.md).
|
||||
* **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.
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ Diese Roadmap führt vom nRF52840DK bis zum fertigen Produkt.
|
||||
- [ ] 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: MilesTag-Encoder mit nrfx_pwm + PPI implementieren. Signal mit Oszilloskop/Logic Analyzer verifizieren. Sicherstellen, dass Funk die IR-Engine nicht stört.
|
||||
- [ ] 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](specifications/ir_protocol.md)).
|
||||
|
||||
#### Phase 2: Der "Prototyp" (Integration)
|
||||
**Ziel:** Einbindung von Audio und Solenoid.
|
||||
|
||||
201
doc/docs/specifications/ir_protocol.md
Normal file
201
doc/docs/specifications/ir_protocol.md
Normal file
@@ -0,0 +1,201 @@
|
||||
# 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** | 2400 µs | ±200 µs | Frame-Synchronisations-Impuls |
|
||||
| **Mark** | 600 µs | ±100 µs | Träger AN (konstant für alle Bits) |
|
||||
| **Space 0** | 600 µs | ±100 µs | Träger AUS für logisch 0 |
|
||||
| **Space 1** | 1200 µs | ±150 µs | Träger AUS für logisch 1 |
|
||||
|
||||
### 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) |
|
||||
|
||||
```mermaid
|
||||
block-beta
|
||||
columns 8
|
||||
mark1["Mark<br>600 µs"] space1["Space 1<br>1200 µs"]:2 mark2["Mark<br>600 µs"] space2["Space 0<br>600 µs"] mark3["Mark<br>600 µs"] space3["Space 1<br>1200 µs"]:2
|
||||
bit1["<b>1</b>"]:3 bit2["<b>0</b>"]:2 bit3["<b>1</b>"]:3
|
||||
|
||||
style space1 fill:none
|
||||
style space2 fill:none
|
||||
style space3 fill:none
|
||||
```
|
||||
|
||||
## Frame-Format
|
||||
|
||||
Alle Frames bestehen aus 24 Bits, übertragen MSB-first:
|
||||
|
||||
| Feld | Start Burst | Type | Data | CRC8 |
|
||||
|------|-------------|------|------|------|
|
||||
| **Dauer** | 2400 µs | 3 Bits | 13 Bits | 8 Bits |
|
||||
| **Funktion** | Synchronisation | Frame-Typ | Payload | Fehlerprüfung |
|
||||
| **Summe** | – | – | – | **24 Bits** |
|
||||
|
||||
```mermaid
|
||||
packet-beta
|
||||
title Frame
|
||||
+3: "Typ"
|
||||
+13: "Payload"
|
||||
+8: "Fehlerprüfung"
|
||||
```
|
||||
|
||||
**Gesamte Frame-Zeit:** ~36 ms (Start + 24 × 1.5 ms durchschnittliche Bit-Zeit)
|
||||
|
||||
### 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:**
|
||||
|
||||
1. Start Burst: 2400 µs Träger AN
|
||||
2. Bit 0 (Type): 600 µs Mark + 600 µs Space
|
||||
3. Bit 1 (Type): 600 µs Mark + 600 µs Space
|
||||
4. Bit 2 (Type): 600 µs Mark + 600 µs Space
|
||||
5. ... (21 weitere Bits)
|
||||
6. 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
|
||||
|
||||
1. **IDLE:** Auf Start Burst warten (2000–2800 µs)
|
||||
2. **SYNC:** Start Burst erkannt, Vorbereitung zur Bit-Empfang
|
||||
3. **DATA:** Space nach jedem Mark messen, 24 Bits dekodieren
|
||||
4. **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_SEND_MARK_US`: Mark-Dauer (300–1000 µs)
|
||||
- `CONFIG_IR_SEND_SPACE0_US`: Space für Bit 0 (300–1000 µs)
|
||||
- `CONFIG_IR_SEND_SPACE1_US`: Space für Bit 1 (800–2000 µs)
|
||||
- `CONFIG_IR_SEND_START_BURST_US`: Start Burst (1500–4000 µs)
|
||||
|
||||
Die Standardwerte folgen Sony SIRC Timing-Konventionen für bewährte Zuverlässigkeit.
|
||||
|
||||
## Leistungscharakteristiken
|
||||
|
||||
| Metrik | Wert |
|
||||
|--------|------|
|
||||
| Frame-Zeit | ~36 ms |
|
||||
| Datenrate | ~670 bit/s |
|
||||
| Max. Spieler-IDs | 256 |
|
||||
| Reichweite (Außen) | ~5–10 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.*
|
||||
|
||||
@@ -8,6 +8,8 @@ nav:
|
||||
- Hardware: konzept/hardware.md
|
||||
- Software: konzept/software.md
|
||||
- Gameplay & Modi: konzept/gameplay.md
|
||||
- Spezifikationen:
|
||||
- IR-Protokoll: specifications/ir_protocol.md
|
||||
- Planung: planung.md
|
||||
- Lizenz: license.md
|
||||
|
||||
|
||||
Reference in New Issue
Block a user