takeone-event-managment/doc/device-signals.md

8.7 KiB
Raw Blame History

📡 Taekwondo Scoring System Device Signals & Communication Protocol

Version: 2.0 (Full Device Coverage)
Last Updated: July 2025
Target Developer: Embedded (ESP32) & Android (.NET) Developers
Purpose: Define two-way communication for all battery-powered devices: joysticks, hogu, and headgear


📌 Table of Contents


1. Overview

All battery-powered devices in the system support two-way TCP communication:

  • Send: Sensor data, telemetry, events
  • Receive: Feedback commands, display updates, calibration
  • Device Types:
    • Referee Joysticks (4 units)
    • Hogu (Trunk Protector) Red & Blue
    • Headgear Red & Blue

Each device identifies itself with:

DEVICE:NAME=...,TYPE=...,MAC=...

2. Device Types

Device Type Key Features
Joystick JOYSTICK Button, OLED, vibration, LED, buzzer, battery telemetry
Hogu SENSOR Force sensor (FSR), MPU6050 (spinning), OLED, vibration, battery
Headgear SENSOR Force sensor, MPU6050, OLED, vibration, battery

All use ESP32-C3, LiPo battery, and I2C OLED (0x3C).


3. Communication Model (TCP Full-Duplex)

[All Devices] ↔ [Android Tablet: TCP Server (Port 5000)]
  • Devices connect to 192.168.4.1:5000 (hotspot mode)
  • First message: DEVICE:NAME=...,TYPE=...,MAC=...
  • Subsequent messages: JSON \n-terminated
  • Server can send commands at any time

Full-duplex: Send and receive on same connection.


4. Common Device Signals

4.1 Device Identity (Mandatory First Message)

DEVICE:NAME=HOGU_RED,TYPE=SENSOR,MAC=30:85:A9:12:34:56

4.2 Telemetry (Periodic, Every 60 sec)

{
  "type": "telemetry",
  "device": "HOGU_RED",
  "battery_level": 88,
  "battery_voltage": 4.02,
  "rssi": -65,
  "uptime": 3420,
  "timestamp": 1712345679000
}

4.3 Command Acknowledgment

{"ack": "vibrate", "time": 1712345679100}

5. Referee Joystick

📥 Outgoing

  • button press
  • telemetry

📤 Incoming Commands

  • vibrate tactile feedback
  • buzz audible alert
  • led status indication
  • display show text
  • ping liveness check

Example Button Press

{"type":"button","device":"JOYSTICK_CORNER_1","pressed":true,"time":1712345678905}

6. Hogu (Trunk Protector)

📥 Outgoing

6.1 Impact Detection

{
  "type": "impact",
  "device": "hogu_red",
  "force": 850,
  "spinning": true,
  "time": 1712345678901
}
  • force: 01023 (analog read)
  • spinning: from MPU6050 (rotation > 180°)

6.2 Telemetry

Same as joystick, includes sensor health.


📤 Incoming Commands

Command Effect
vibrate Confirm impact registered
led Flash green/red for status
display Show "HOGU RED", battery, status
calibrate Recalibrate force sensor
ping Liveness check

Example: Calibrate Command

{"cmd": "calibrate", "mode": "zero"}

7. Headgear

📥 Outgoing

7.1 Impact Detection

{
  "type": "impact",
  "device": "head_blue",
  "force": 720,
  "spinning": false,
  "time": 1712345678903
}

Lower force threshold (safety).

7.2 Telemetry

Same format, sent every 60 sec.


📤 Incoming Commands

Command Effect
vibrate Confirm head kick detected
led Status light (e.g., red = fault)
display Show "HEAD BLUE", battery
ping Liveness check

No calibrate — headgear is sealed.


8. OLED Display (128x64, I2C 0x3C)

All devices have the same OLED for status and feedback.

8.1 Display Modes

Device Normal Active Low Battery Error
Joystick CORNER 1
READY
PRESSED! ⚠️ BATT: 20% NO SIGNAL
Hogu HOGU RED
OK
IMPACT! ⚠️ BATT: 15% SENSOR FAULT
Headgear HEAD BLUE
ACTIVE
HIT DETECTED ⚠️ BATT: 10% DISCONNECTED

8.2 Server Command

{
  "cmd": "display",
  "lines": [
    {"text": "HOGU RED", "y": 0},
    {"text": "IMPACT!", "y": 30, "color": "green"}
  ],
  "refresh": true
}

9. Telemetry: Battery & Health Monitoring

9.1 Battery Measurement (All Devices)

float readBatteryVoltage() {
  int adc = analogRead(BATTERY_PIN);
  float voltage = (adc / 4095.0) * 3.3 * 2.0; // 2:1 divider
  return voltage;
}

int getBatteryLevel(float voltage) {
  if (voltage >= 4.2) return 100;
  if (voltage <= 3.3) return 0;
  return (int)((voltage - 3.3) / 0.9 * 100);
}

9.2 Telemetry Frequency

  • Every 60 seconds
  • Or on significant change (e.g., battery drop >5%)

10. Feedback: Vibration, LED, Buzzer

10.1 Pin Assignments (Shared)

Component GPIO
Vibration Motor 4
Buzzer 5
LED (RGB) 6 (R), 7 (G), 8 (B)
OLED (SDA) 21
OLED (SCL) 22
FSR (Hogu) 34
FSR (Head) 35
MPU6050 (SCL/SDA) 21, 22 (shared with OLED)

Use I2C multiplexer if needed.


10.2 Feedback Examples

Vibrate (200ms)

{"cmd": "vibrate", "duration": 200}
{"cmd": "led", "color": "#00FF00", "mode": "blink", "count": 3}

Buzzer: Short beep

{"cmd": "buzz", "tone": 1000, "duration": 150}

11. Command & Response Format

11.1 Outgoing (Device → Server)

{"type":"impact","device":"head_blue","force":720,"spinning":false,"time":1712345678903}
{"type":"telemetry","device":"HOGU_RED","battery_level":88,"rssi":-65,"timestamp":1712345679000}

11.2 Incoming (Server → Device)

{"cmd":"vibrate","duration":200}
{"cmd":"led","color":"#0000FF","mode":"solid"}
{"cmd":"display","lines":[{"text":"IMPACT!","y":30}]}
{"cmd":"ping"}

Device responds to ping with:

{"ack":"ping","time":1712345679100}

12. ESP32 Code Structure (Modular)

Use a modular design with shared components:

/src/
  ├── main.cpp
  ├── wifi_manager.cpp
  ├── tcp_client.cpp
  ├── oled_display.cpp
  ├── battery_monitor.cpp
  ├── sensors/
  │   ├── fsr.cpp
  │   └── mpu6050.cpp
  ├── feedback/
  │   ├── vibration.cpp
  │   ├── buzzer.cpp
  │   └── led.cpp
  └── device_config.h

Example: device_config.h

#define DEVICE_NAME "HOGU_RED"
#define DEVICE_TYPE "SENSOR"
#define OLED_ADDR 0x3C
#define BATTERY_PIN 35
#define VIBRO_PIN 4
#define BUZZER_PIN 5
#define LED_PIN 6

13. Android .NET Server Integration

Send Command to Any Device

void SendCommand(string mac, string commandJson)
{
    TcpClient client = GetDeviceByMac(mac);
    if (client?.Connected == true)
    {
        var stream = client.GetStream();
        var writer = new StreamWriter(stream);
        await writer.WriteLineAsync(commandJson);
        await writer.FlushAsync();
    }
}

Example: Confirm Impact

// After auto-scoring
SendCommand("30:85:A9:12:34:56", "{\"cmd\":\"vibrate\",\"duration\":200}");
SendCommand("30:85:A9:12:34:56", "{\"cmd\":\"led\",\"color\":\"#00FF00\",\"mode\":\"blink\",\"count\":2}");

Broadcast to All Sensors

foreach (var device in GetAllSensors())
{
    SendCommand(device.Mac, "{\"cmd\":\"display\",\"lines\":[{\"text\":\"MATCH START\"}]}");
}

14. Best Practices

Practice Why
Send telemetry every 60 sec Monitor battery and health
Debounce sensor inputs Prevent false triggers
Use I2C for OLED & MPU6050 Save pins
Add ping command Check device liveness
Log all commands Debugging and auditing
Low-power mode Extend battery life
Clear OLED on boot Avoid ghosting
Validate MAC before sending Prevent errors