diff --git a/flake.nix b/flake.nix index 0615a6b..6d17cd0 100644 --- a/flake.nix +++ b/flake.nix @@ -25,6 +25,7 @@ cargo-espflash espup mosquitto + mermaid-cli ]; shellHook = '' diff --git a/mqtt_display/docs/critical_data_flow_points.mermaid b/mqtt_display/docs/critical_data_flow_points.mermaid new file mode 100644 index 0000000..1ecc5bf --- /dev/null +++ b/mqtt_display/docs/critical_data_flow_points.mermaid @@ -0,0 +1,37 @@ +graph TD + START[MPU reads @50ms = 20 Hz] --> A{IMU_CHANNELtry_send} + + A -->|Full| DROP1[❌ DROP: Channel full16 slots @ 50ms = 800ms buffer] + A -->|OK| B[Main Loop receive] + + B --> C[Drain loop:Get freshest reading] + C --> D{Time check:≥3s since last?} + + D -->|No| E[Skip MQTT] + D -->|Yes| F{mqtt_set_imutry_lock IMU_LATEST} + + F -->|Locked| DROP2[❌ SKIP: Mutex busy] + F -->|OK| G[Store payload] + + E --> H[show_imu] + G --> H + + H --> I{DISPLAY_CHANNELtry_send} + I -->|Full| DROP3[❌ DROP: Display slow8 slots @ 100ms = 800ms buffer] + I -->|OK| J[Display renders] + + G --> K[MQTT Task loop] + K --> L{IMU_LATESTtry_lock} + + L -->|Empty/Locked| M[Skip this iteration] + L -->|Has data| N[Send to brokerQoS0 no retain] + + N --> O{TCP send result} + O -->|Fail| RECONNECT[❌ Session diesReconnect in 5s] + O -->|OK| P[✅ Data sent] + + style DROP1 fill:#ffcccc + style DROP2 fill:#ffcccc + style DROP3 fill:#ffcccc + style RECONNECT fill:#ffcccc + style P fill:#ccffcc diff --git a/mqtt_display/docs/critical_data_flow_points.mermaid.svg b/mqtt_display/docs/critical_data_flow_points.mermaid.svg new file mode 100644 index 0000000..9453639 --- /dev/null +++ b/mqtt_display/docs/critical_data_flow_points.mermaid.svg @@ -0,0 +1 @@ +FullOKNoYesLockedOKFullOKEmpty/LockedHas dataFailOKMPU reads @50ms = 20 HzIMU_CHANNELtry_send❌ DROP: Channel full16 slots @ 50ms = 800ms bufferMain Loop receiveDrain loop:Get freshest readingTime check:≥3s since last?Skip MQTTmqtt_set_imutry_lock IMU_LATEST❌ SKIP: Mutex busyStore payloadshow_imuDISPLAY_CHANNELtry_send❌ DROP: Display slow8 slots @ 100ms = 800ms bufferDisplay rendersMQTT Task loopIMU_LATESTtry_lockSkip this iterationSend to brokerQoS0 no retainTCP send result❌ Session diesReconnect in 5s✅ Data sent \ No newline at end of file diff --git a/mqtt_display/docs/mpu_data_flow.mermaid b/mqtt_display/docs/mpu_data_flow.mermaid new file mode 100644 index 0000000..59f1876 --- /dev/null +++ b/mqtt_display/docs/mpu_data_flow.mermaid @@ -0,0 +1,54 @@ +sequenceDiagram + participant HW as MPU6050 Hardware + participant MPU as MPU Task(Core 0) + participant CH as IMU_CHANNEL[16 slots] + participant MAIN as Main Loop(Core 0) + participant LATEST as IMU_LATEST(Mutex) + participant MQTT as MQTT Task(Core 1) + participant DISP as Display API + + Note over MPU: Every 50ms + MPU->>HW: Read sensor (I2C) + HW-->>MPU: Raw data + MPU->>MPU: Convert to ImuReading + MPU->>CH: try_send(reading) + + alt Channel full + CH--xMPU: Drop (log warning) + else Channel has space + CH-->>MPU: OK + end + + Note over MAIN: Continuous loop + MAIN->>CH: receive() [blocking] + CH-->>MAIN: reading + + Note over MAIN: Drain queue + loop While available + MAIN->>CH: try_receive() + CH-->>MAIN: newer reading + end + + MAIN->>DISP: show_imu(reading)[try_send] + + Note over MAIN: Every 3 seconds + alt Time >= 3s since last + MAIN->>MAIN: Format JSON payload + MAIN->>LATEST: mqtt_set_imu()[try_lock] + + alt Mutex available + LATEST-->>MAIN: Stored + else Mutex locked + LATEST--xMAIN: Skip + end + end + + Note over MQTT: Continuous loop + MQTT->>LATEST: try_lock() + + alt Data available + LATEST-->>MQTT: payload + MQTT->>MQTT: send_message("esp32/imu") + else No data + LATEST--xMQTT: None + end diff --git a/mqtt_display/docs/mpu_data_flow.mermaid.svg b/mqtt_display/docs/mpu_data_flow.mermaid.svg new file mode 100644 index 0000000..6c95931 --- /dev/null +++ b/mqtt_display/docs/mpu_data_flow.mermaid.svg @@ -0,0 +1 @@ +Display APIMQTT Task(Core 1)IMU_LATEST(Mutex)Main Loop(Core 0)IMU_CHANNEL[16 slots]MPU Task(Core 0)MPU6050 HardwareDisplay APIMQTT Task(Core 1)IMU_LATEST(Mutex)Main Loop(Core 0)IMU_CHANNEL[16 slots]MPU Task(Core 0)MPU6050 HardwareEvery 50msalt[Channel full][Channel has space]Continuous loopDrain queueloop[While available]Every 3 secondsalt[Mutex available][Mutex locked]alt[Time >= 3s since last]Continuous loopalt[Data available][No data]Read sensor (I2C)Raw dataConvert to ImuReadingtry_send(reading)Drop (log warning)OKreceive() [blocking]readingtry_receive()newer readingshow_imu(reading)[try_send]Format JSON payloadmqtt_set_imu()[try_lock]StoredSkiptry_lock()payloadsend_message("esp32/imu")None \ No newline at end of file diff --git a/mqtt_display/docs/overall_system_architecture.mermaid b/mqtt_display/docs/overall_system_architecture.mermaid new file mode 100644 index 0000000..799b3ce --- /dev/null +++ b/mqtt_display/docs/overall_system_architecture.mermaid @@ -0,0 +1,42 @@ +graph TB + subgraph "Core 0 - Application" + MPU[MPU Task50ms sampling] + DISPLAY[Display Task100ms refresh] + MAIN[Main Loop] + BUTTONS[Button Task] + end + + subgraph "Core 1 - Network" + WIFI[WiFi Connection Task] + NETWORK[Network Stack Runner] + MQTT[MQTT Task] + end + + subgraph "Shared Channels" + IMU_CH[(IMU_CHANNELsize: 16)] + DISP_CH[(DISPLAY_CHANNELsize: 8)] + CMD_CH[(CMD_CHANsize: 8)] + EVT_CH[(EVT_CHANsize: 8)] + IMU_LATEST[(IMU_LATESTMutex)] + end + + subgraph "Hardware" + MPU_HW[MPU6050I2C 0x68] + OLED[SSD1306I2C] + BROKER[MQTT Broker] + end + + MPU_HW -->|I2C Read| MPU + MPU -->|send| IMU_CH + IMU_CH -->|receive| MAIN + MAIN -->|try_send| DISP_CH + MAIN -->|mqtt_set_imu| IMU_LATEST + DISP_CH -->|receive| DISPLAY + DISPLAY -->|I2C Write| OLED + IMU_LATEST -->|try_lock| MQTT + MQTT <-->|TCP/IP| BROKER + BUTTONS -->|push_key| DISP_CH + + style IMU_CH fill:#ff9999 + style DISP_CH fill:#99ccff + style IMU_LATEST fill:#ffcc99 diff --git a/mqtt_display/docs/overall_system_architecture.mermaid.svg b/mqtt_display/docs/overall_system_architecture.mermaid.svg new file mode 100644 index 0000000..08a3328 --- /dev/null +++ b/mqtt_display/docs/overall_system_architecture.mermaid.svg @@ -0,0 +1 @@ +HardwareShared ChannelsCore 1 - NetworkCore 0 - ApplicationI2C Readsendreceivetry_sendmqtt_set_imureceiveI2C Writetry_lockTCP/IPpush_keyMPU Task50ms samplingDisplay Task100ms refreshMain LoopButton TaskWiFi Connection TaskNetwork Stack RunnerMQTT TaskIMU_CHANNELsize: 16DISPLAY_CHANNELsize: 8CMD_CHANsize: 8EVT_CHANsize: 8IMU_LATESTMutexMPU6050I2C 0x68SSD1306I2CMQTT Broker \ No newline at end of file
Full
OK
No
Yes
Locked
Empty/Locked
Has data
Fail
MPU reads @50ms = 20 Hz
IMU_CHANNELtry_send
❌ DROP: Channel full16 slots @ 50ms = 800ms buffer
Main Loop receive
Drain loop:Get freshest reading
Time check:≥3s since last?
Skip MQTT
mqtt_set_imutry_lock IMU_LATEST
❌ SKIP: Mutex busy
Store payload
show_imu
DISPLAY_CHANNELtry_send
❌ DROP: Display slow8 slots @ 100ms = 800ms buffer
Display renders
MQTT Task loop
IMU_LATESTtry_lock
Skip this iteration
Send to brokerQoS0 no retain
TCP send result
❌ Session diesReconnect in 5s
✅ Data sent
Hardware
Shared Channels
Core 1 - Network
Core 0 - Application
I2C Read
send
receive
try_send
mqtt_set_imu
I2C Write
try_lock
TCP/IP
push_key
MPU Task50ms sampling
Display Task100ms refresh
Main Loop
Button Task
WiFi Connection Task
Network Stack Runner
MQTT Task
IMU_CHANNELsize: 16
DISPLAY_CHANNELsize: 8
CMD_CHANsize: 8
EVT_CHANsize: 8
IMU_LATESTMutex
MPU6050I2C 0x68
SSD1306I2C
MQTT Broker