-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver-control-flow.puml
More file actions
138 lines (130 loc) · 4.76 KB
/
Copy pathserver-control-flow.puml
File metadata and controls
138 lines (130 loc) · 4.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
@startuml server-control-flow
!theme plain
skinparam defaultFontName "DejaVu Sans"
skinparam defaultFontSize 11
skinparam backgroundColor #FAFAFA
skinparam activityBackgroundColor #EEF2FF
skinparam activityBorderColor #5566AA
skinparam activityDiamondBackgroundColor #FFF8E0
skinparam activityDiamondBorderColor #AA8833
skinparam swimlaneBorderColor #888888
skinparam noteBackgroundColor #FFFBE0
skinparam noteBorderColor #AAAAAA
title Server — FreeRTOS Task Control Flow
' ──────────────────────────────────────────────────────────────────
' SETUP
' ──────────────────────────────────────────────────────────────────
|#E8EEFF|setup()|
start
:Serial.begin(115200);
:NeoPixel init
red → purple → off;
:imu_data_mutex = xSemaphoreCreateMutex()
memset(&shared_imu_data, 0);
fork
:xTaskCreatePinnedToCore
**SensorDataTask** → Core 0;
fork again
:xTaskCreatePinnedToCore
**WebServerTask** → Core 1;
end fork
end
note right
setup() returns immediately.
All work is done in FreeRTOS tasks.
loop() is empty.
end note
' ──────────────────────────────────────────────────────────────────
' SENSOR TASK (Core 0)
' ──────────────────────────────────────────────────────────────────
|#DDEEFF|SensorDataTask (Core 0)|
start
:delay(2000ms)
I²C bus settle;
repeat
:lsm6dsox.begin_I2C()\n SDA=42, SCL=41;
backward:delay(1000ms);
repeat while (found?) is (no)
->yes;
:log "LSM6DSOX initialised";
repeat
:lsm6dsox.getEvent(&accel, &gyro, &temp);
note right
~50 Hz sample rate
(20 ms period)
end note
#lightgreen:**xSemaphoreTake**(imu_data_mutex, 5ms);
:shared_imu_data ← accel/gyro/temp;
#lightgreen:**xSemaphoreGive**(imu_data_mutex);
if (blinkCtr >= 20?) then (yes)
:NeoPixel green flash (30ms);
:blinkCtr = 0;
else (no)
:blinkCtr++;
endif
:delay(20ms);
repeat while (true) is (forever)
stop
' ──────────────────────────────────────────────────────────────────
' WEB SERVER TASK (Core 1)
' ──────────────────────────────────────────────────────────────────
|#D8F0FF|WebServerTask (Core 1)|
start
:CGrpcServer grpcServer(SSID, pass);
:grpcServer.SetupNetwork()
→ WiFi AP "MOONBASE-II";
:grpcServer.StartServer()
→ :50051 (cmd), :50052 (stream);
:grpcServer.SetStreamRate(20 Hz);
:CMotorController motorCtrl(5,6,9,10,11);
:motorCtrl.Begin()
ledcSetup/AttachPin ch4-7
Servo.attach(GPIO11);
repeat
#lightgreen:**xSemaphoreTake**(imu_data_mutex, 5ms);
:imu_copy ← shared_imu_data;
#lightgreen:**xSemaphoreGive**(imu_data_mutex);
:grpcServer.UpdateImuData(imu_copy);
:**HandleClients()**;
:joy ← grpcServer.GetJoystickData();
:motorCtrl.Update(joy);
:delay(1ms);
repeat while (true) is (forever)
stop
' ──────────────────────────────────────────────────────────────────
' HANDLE CLIENTS — called each loop iteration
' ──────────────────────────────────────────────────────────────────
|#E8FFE8|HandleClients() — non-blocking|
start
if (now − lastStreamTime >= 50ms?) then (yes)
:PushImuStream()
serializeMsgPack → writeStreamFrame(:50052);
:lastStreamTime = now;
endif
if (m_StreamServer.available()?) then (yes)
:Stop old stream client (if any);
:m_StreamClient = new subscriber;
endif
if (m_CommandServer.available()?) then (yes)
:Stop old command client (if any);
:m_CommandClient = new client;
endif
if (m_CommandClient.connected()\n&& available() >= 3?) then (yes)
:readCommandHeader()
→ method_id, payload_len;
:wait for full payload\n(max 10ms spin);
:readBytes(payload, len);
:ProcessCommand()
→ switch(method_id);
split
:LED ON/OFF;
split again
:IMU one-off query;
split again
:Joystick data update;
end split
else (no)
:—no-op—;
endif
stop
@enduml