Update FreeRTOS configuration and enhance upper computer AI documentation

- Increased total heap size in FreeRTOSConfig.h from 10000 to 18000.
- Modified stack sizes for various tasks in freertos.c to improve performance:
  - initTask: 128 to 256
  - CarCtrlTask: 256 to 1024
  - timerTask: 512 to 1024
  - sr04Task: 128 to 512
  - rc522Task: 128 to 512
- Added comprehensive upper computer AI guide for TCP client implementation, detailing protocol contracts, command sets, telemetry, architecture requirements, and error handling strategies.
- Introduced a Python web upper computer AI guide with a recommended tech stack and project structure.
- Created a Chinese version of the upper computer AI guide for local developers.
- Updated STM32 project configuration to reflect new task stack sizes and heap settings.
- Adjusted configuration files for various tools to ensure compatibility with the new project structure.
This commit is contained in:
2026-04-17 22:15:54 +08:00
parent 3eb63ade12
commit 48a443c6c1
14 changed files with 1259 additions and 29 deletions

View File

@@ -21,8 +21,11 @@ HAL_StatusTypeDef ESP12F_TCP_SendMessage(const char *data) {
return HAL_ERROR; // 数据为空 return HAL_ERROR; // 数据为空
} }
// 启动 DMA 传输 /*
return HAL_UART_Transmit_DMA(&huart1, (uint8_t *)data, size); * 这里使用阻塞发送而不是 DMA协议帧很短且发送缓冲区通常来自局部变量。
* 使用 DMA 会引入发送缓冲区生命周期问题,容易导致反馈丢失或数据不稳定。
*/
return HAL_UART_Transmit(&huart1, (uint8_t *)data, size, 50U);
} }
/* External DMA handle */ /* External DMA handle */

View File

@@ -40,6 +40,9 @@
#define OBSTACLE_STOP_DISTANCE_CM 18.0f #define OBSTACLE_STOP_DISTANCE_CM 18.0f
#define OBSTACLE_RECOVER_DISTANCE_CM 22.0f #define OBSTACLE_RECOVER_DISTANCE_CM 22.0f
/* 手动控制方向斜向速度缩放,避免斜向合速度过大 */
#define MANUAL_DIAG_SCALE 0.7071f
/* 电机位置定义 (基于用户规定) */ /* 电机位置定义 (基于用户规定) */
#define MOTOR_LR MOTOR_1 // 左后 (Left Rear) #define MOTOR_LR MOTOR_1 // 左后 (Left Rear)
#define MOTOR_LF MOTOR_2 // 左前 (Left Front) #define MOTOR_LF MOTOR_2 // 左前 (Left Front)
@@ -59,12 +62,75 @@ static uint8_t obstacle_locked = 0; // 避障锁1=有障碍锁定)
static track_ir_ctrl_output_t track_output = {0}; static track_ir_ctrl_output_t track_output = {0};
static uint8_t track_line_mask = 0; static uint8_t track_line_mask = 0;
static void CarCtrl_StopAll(void);
typedef enum {
CTRL_MODE_AUTO = 0,
CTRL_MODE_MANUAL
} ctrl_mode_t;
typedef enum {
MAN_DIR_STOP = 0,
MAN_DIR_FWD,
MAN_DIR_BWD,
MAN_DIR_LEFT,
MAN_DIR_RIGHT,
MAN_DIR_LF,
MAN_DIR_RF,
MAN_DIR_LB,
MAN_DIR_RB,
MAN_DIR_CW,
MAN_DIR_CCW
} manual_dir_t;
static ctrl_mode_t car_ctrl_mode = CTRL_MODE_AUTO;
static manual_dir_t manual_dir = MAN_DIR_STOP;
#define CAR_STATION_MIN ((uint16_t)STATION_1) #define CAR_STATION_MIN ((uint16_t)STATION_1)
#define CAR_STATION_MAX ((uint16_t)STATION_2) #define CAR_STATION_MAX ((uint16_t)STATION_2)
/* 4个电机的 PID 控制器 */ /* 4个电机的 PID 控制器 */
static PID_TypeDef motor_pid[MOTOR_COUNT]; static PID_TypeDef motor_pid[MOTOR_COUNT];
static const char *CarCtrl_ModeToString(ctrl_mode_t mode)
{
return (mode == CTRL_MODE_MANUAL) ? "MAN" : "AUTO";
}
static const char *CarCtrl_ManualDirToString(manual_dir_t dir)
{
switch (dir) {
case MAN_DIR_FWD: return "FWD";
case MAN_DIR_BWD: return "BWD";
case MAN_DIR_LEFT: return "LEFT";
case MAN_DIR_RIGHT:return "RIGHT";
case MAN_DIR_LF: return "LF";
case MAN_DIR_RF: return "RF";
case MAN_DIR_LB: return "LB";
case MAN_DIR_RB: return "RB";
case MAN_DIR_CW: return "CW";
case MAN_DIR_CCW: return "CCW";
case MAN_DIR_STOP:
default:
return "STOP";
}
}
static void CarCtrl_SetManualDirection(manual_dir_t dir)
{
manual_dir = dir;
if (dir == MAN_DIR_STOP) {
car_running = 0U;
target_v_x = 0.0f;
target_v_y = 0.0f;
target_v_w = 0.0f;
CarCtrl_StopAll();
} else {
car_running = 1U;
car_target_reached = 0U;
}
}
/** /**
* @brief 初始化闭环控制系统 * @brief 初始化闭环控制系统
*/ */
@@ -77,6 +143,8 @@ void CarCtrl_InitClosedLoop(void)
track_ir_algo_init(); track_ir_algo_init();
obstacle_locked = 0U; obstacle_locked = 0U;
car_ctrl_mode = CTRL_MODE_AUTO;
manual_dir = MAN_DIR_STOP;
BEEP_Off(); BEEP_Off();
} }
@@ -113,6 +181,10 @@ static void CarCtrl_CheckTargetStation(void)
rc522_card_info_t card; rc522_card_info_t card;
station_id_t station; station_id_t station;
if (car_ctrl_mode != CTRL_MODE_AUTO) {
return;
}
if (car_running == 0U || car_target_reached != 0U || car_target_station == 0U) { if (car_running == 0U || car_target_reached != 0U || car_target_station == 0U) {
return; return;
} }
@@ -168,8 +240,66 @@ void CarCtrl_UpdateClosedLoop(void)
BEEP_Off(); BEEP_Off();
track_line_mask = track_ir_get_line_mask_filtered(); if (car_ctrl_mode == CTRL_MODE_AUTO) {
track_ir_algo_step(track_line_mask, &track_output); track_line_mask = track_ir_get_line_mask_filtered();
track_ir_algo_step(track_line_mask, &track_output);
// 从前进速度分量计算基础速度(自动循迹)
target_v_x = (float)car_speed_percent * TARGET_MAX_RPM / 100.0f;
target_v_x = target_v_x * (float)track_output.speed_scale_percent / 100.0f;
target_v_y = 0.0f;
target_v_w = track_output.yaw_correction_rpm;
} else {
float base_rpm = (float)car_speed_percent * TARGET_MAX_RPM / 100.0f;
track_line_mask = 0U;
memset(&track_output, 0, sizeof(track_output));
/* 手动模式下,依据上位机方向指令生成 Vx/Vy/Vw */
switch (manual_dir) {
case MAN_DIR_FWD:
target_v_x = base_rpm; target_v_y = 0.0f; target_v_w = 0.0f;
break;
case MAN_DIR_BWD:
target_v_x = -base_rpm; target_v_y = 0.0f; target_v_w = 0.0f;
break;
case MAN_DIR_LEFT:
target_v_x = 0.0f; target_v_y = base_rpm; target_v_w = 0.0f; // 修正左移Vy为正
break;
case MAN_DIR_RIGHT:
target_v_x = 0.0f; target_v_y = -base_rpm; target_v_w = 0.0f; // 修正右移Vy为负
break;
case MAN_DIR_LF:
target_v_x = base_rpm * MANUAL_DIAG_SCALE;
target_v_y = -base_rpm * MANUAL_DIAG_SCALE;
target_v_w = 0.0f;
break;
case MAN_DIR_RF:
target_v_x = base_rpm * MANUAL_DIAG_SCALE;
target_v_y = base_rpm * MANUAL_DIAG_SCALE;
target_v_w = 0.0f;
break;
case MAN_DIR_LB:
target_v_x = -base_rpm * MANUAL_DIAG_SCALE;
target_v_y = -base_rpm * MANUAL_DIAG_SCALE;
target_v_w = 0.0f;
break;
case MAN_DIR_RB:
target_v_x = -base_rpm * MANUAL_DIAG_SCALE;
target_v_y = base_rpm * MANUAL_DIAG_SCALE;
target_v_w = 0.0f;
break;
case MAN_DIR_CW:
target_v_x = 0.0f; target_v_y = 0.0f; target_v_w = base_rpm;
break;
case MAN_DIR_CCW:
target_v_x = 0.0f; target_v_y = 0.0f; target_v_w = -base_rpm;
break;
case MAN_DIR_STOP:
default:
target_v_x = 0.0f; target_v_y = 0.0f; target_v_w = 0.0f;
break;
}
}
/* 麦克纳姆轮运动解算 (RPM单位) /* 麦克纳姆轮运动解算 (RPM单位)
* 根据你的电机位置规定: * 根据你的电机位置规定:
@@ -177,12 +307,6 @@ void CarCtrl_UpdateClosedLoop(void)
*/ */
float target_rpms[MOTOR_COUNT]; float target_rpms[MOTOR_COUNT];
// 从前进速度分量计算基础速度
target_v_x = (float)car_speed_percent * TARGET_MAX_RPM / 100.0f;
target_v_x = target_v_x * (float)track_output.speed_scale_percent / 100.0f;
target_v_y = 0.0f;
target_v_w = track_output.yaw_correction_rpm;
// 麦轮全向解算公式: // 麦轮全向解算公式:
// LF = Vx + Vy - Vw // LF = Vx + Vy - Vw
// RF = Vx - Vy + Vw // RF = Vx - Vy + Vw
@@ -332,6 +456,72 @@ static void CarCtrl_HandleCommand(const char *cmd_payload)
return; return;
} }
// 控制模式切换MD:AUTO / MD:MAN
if (strncmp(cmd_payload, "MD", 2) == 0) {
if (strcmp(arg + 1, "AUTO") == 0) {
car_ctrl_mode = CTRL_MODE_AUTO;
manual_dir = MAN_DIR_STOP;
car_running = 0U;
obstacle_locked = 0U;
track_ir_algo_reset();
CarCtrl_StopAll();
elog_i(Protocol_TAG, "已切换为自动循迹模式(AUTO)");
Protocol_SendFeedback("MD", 1);
} else if (strcmp(arg + 1, "MAN") == 0) {
car_ctrl_mode = CTRL_MODE_MANUAL;
obstacle_locked = 0U;
CarCtrl_SetManualDirection(MAN_DIR_STOP);
elog_i(Protocol_TAG, "已切换为手动麦轮模式(MAN)");
Protocol_SendFeedback("MD", 1);
} else {
elog_w(Protocol_TAG, "未知模式命令: %s", cmd_payload);
Protocol_SendFeedback("MD", 0);
}
return;
}
// 手动运动方向命令MV:FWD/BWD/LEFT/RIGHT/LF/RF/LB/RB/CW/CCW/STOP
if (strncmp(cmd_payload, "MV", 2) == 0) {
if (car_ctrl_mode != CTRL_MODE_MANUAL) {
elog_w(Protocol_TAG, "当前非手动模式拒绝执行MV。请先下发 MD:MAN");
Protocol_SendFeedback("MV", 0);
return;
}
if (strcmp(arg + 1, "FWD") == 0) {
CarCtrl_SetManualDirection(MAN_DIR_FWD);
} else if (strcmp(arg + 1, "BWD") == 0) {
CarCtrl_SetManualDirection(MAN_DIR_BWD);
} else if (strcmp(arg + 1, "LEFT") == 0) {
CarCtrl_SetManualDirection(MAN_DIR_LEFT);
} else if (strcmp(arg + 1, "RIGHT") == 0) {
CarCtrl_SetManualDirection(MAN_DIR_RIGHT);
} else if (strcmp(arg + 1, "LF") == 0) {
CarCtrl_SetManualDirection(MAN_DIR_LF);
} else if (strcmp(arg + 1, "RF") == 0) {
CarCtrl_SetManualDirection(MAN_DIR_RF);
} else if (strcmp(arg + 1, "LB") == 0) {
CarCtrl_SetManualDirection(MAN_DIR_LB);
} else if (strcmp(arg + 1, "RB") == 0) {
CarCtrl_SetManualDirection(MAN_DIR_RB);
} else if (strcmp(arg + 1, "CW") == 0) {
CarCtrl_SetManualDirection(MAN_DIR_CW);
} else if (strcmp(arg + 1, "CCW") == 0) {
CarCtrl_SetManualDirection(MAN_DIR_CCW);
} else if (strcmp(arg + 1, "STOP") == 0) {
CarCtrl_SetManualDirection(MAN_DIR_STOP);
} else {
elog_w(Protocol_TAG, "未知手动方向命令: %s", cmd_payload);
Protocol_SendFeedback("MV", 0);
return;
}
elog_i(Protocol_TAG, "手动方向=%s, speed=%u%%", CarCtrl_ManualDirToString(manual_dir),
car_speed_percent);
Protocol_SendFeedback("MV", 1);
return;
}
// 未知命令类型 // 未知命令类型
elog_w(Protocol_TAG, "未支持的控制命令: %s", cmd_payload); elog_w(Protocol_TAG, "未支持的控制命令: %s", cmd_payload);
} }
@@ -354,7 +544,7 @@ static void Protocol_SendPacket(const char *payload) {
size_t current_len = strlen(packet); size_t current_len = strlen(packet);
snprintf(packet + current_len, sizeof(packet) - current_len, ":%02X#", cs); snprintf(packet + current_len, sizeof(packet) - current_len, ":%02X#", cs);
// 4. 发送 // 4. 直接发送
ESP12F_TCP_SendMessage(packet); ESP12F_TCP_SendMessage(packet);
} }
@@ -363,7 +553,7 @@ static void Protocol_SendPacket(const char *payload) {
* 格式示例: STAT:SP:080,STA:001,RUN:1,DIS:12.5,TRK:0010,RPM:25:25:25:25 * 格式示例: STAT:SP:080,STA:001,RUN:1,DIS:12.5,TRK:0010,RPM:25:25:25:25
*/ */
void Protocol_SendStatusReport(void) { void Protocol_SendStatusReport(void) {
char payload[128] = {0}; char payload[160] = {0};
float dist = sr04_get_distance(); float dist = sr04_get_distance();
uint8_t trk_mask = track_line_mask; uint8_t trk_mask = track_line_mask;
@@ -371,8 +561,11 @@ void Protocol_SendStatusReport(void) {
// TRK 此时上报 4 位二进制掩码 (H4 H3 H2 H1) // TRK 此时上报 4 位二进制掩码 (H4 H3 H2 H1)
// RPM 为各个电机的实际 RPM保留整数 // RPM 为各个电机的实际 RPM保留整数
snprintf(payload, sizeof(payload), snprintf(payload, sizeof(payload),
"STAT:SP:%03u,STA:%03u,RUN:%u,DIS:%.1f,TRK:%u%u%u%u,DEV:%d,OBS:%u,RPM:%d:%d:%d:%d", "STAT:SP:%03u,STA:%03u,RUN:%u,MODE:%s,MAN:%s,DIS:%.1f,TRK:%u%u%u%u,DEV:%d,OBS:%u,RPM:%d:%d:%d:%d",
car_speed_percent, car_target_station, car_running, dist, car_speed_percent, car_target_station, car_running,
CarCtrl_ModeToString(car_ctrl_mode),
CarCtrl_ManualDirToString(manual_dir),
dist,
(trk_mask & TRACK_IR_H4_BIT) ? 1 : 0, (trk_mask & TRACK_IR_H4_BIT) ? 1 : 0,
(trk_mask & TRACK_IR_H3_BIT) ? 1 : 0, (trk_mask & TRACK_IR_H3_BIT) ? 1 : 0,
(trk_mask & TRACK_IR_H2_BIT) ? 1 : 0, (trk_mask & TRACK_IR_H2_BIT) ? 1 : 0,

View File

@@ -64,7 +64,7 @@
#define configTICK_RATE_HZ ((TickType_t)1000) #define configTICK_RATE_HZ ((TickType_t)1000)
#define configMAX_PRIORITIES ( 56 ) #define configMAX_PRIORITIES ( 56 )
#define configMINIMAL_STACK_SIZE ((uint16_t)128) #define configMINIMAL_STACK_SIZE ((uint16_t)128)
#define configTOTAL_HEAP_SIZE ((size_t)10000) #define configTOTAL_HEAP_SIZE ((size_t)18000)
#define configMAX_TASK_NAME_LEN ( 16 ) #define configMAX_TASK_NAME_LEN ( 16 )
#define configUSE_TRACE_FACILITY 1 #define configUSE_TRACE_FACILITY 1
#define configUSE_16_BIT_TICKS 0 #define configUSE_16_BIT_TICKS 0

View File

@@ -60,35 +60,35 @@
osThreadId_t initTaskHandle; osThreadId_t initTaskHandle;
const osThreadAttr_t initTask_attributes = { const osThreadAttr_t initTask_attributes = {
.name = "initTask", .name = "initTask",
.stack_size = 128 * 4, .stack_size = 256 * 4,
.priority = (osPriority_t) osPriorityNormal, .priority = (osPriority_t) osPriorityNormal,
}; };
/* Definitions for CarCtrlTask */ /* Definitions for CarCtrlTask */
osThreadId_t CarCtrlTaskHandle; osThreadId_t CarCtrlTaskHandle;
const osThreadAttr_t CarCtrlTask_attributes = { const osThreadAttr_t CarCtrlTask_attributes = {
.name = "CarCtrlTask", .name = "CarCtrlTask",
.stack_size = 256 * 4, .stack_size = 1024 * 4,
.priority = (osPriority_t) osPriorityNormal, .priority = (osPriority_t) osPriorityNormal,
}; };
/* Definitions for timerTask */ /* Definitions for timerTask */
osThreadId_t timerTaskHandle; osThreadId_t timerTaskHandle;
const osThreadAttr_t timerTask_attributes = { const osThreadAttr_t timerTask_attributes = {
.name = "timerTask", .name = "timerTask",
.stack_size = 512 * 4, .stack_size = 1024 * 4,
.priority = (osPriority_t) osPriorityBelowNormal, .priority = (osPriority_t) osPriorityBelowNormal,
}; };
/* Definitions for sr04Task */ /* Definitions for sr04Task */
osThreadId_t sr04TaskHandle; osThreadId_t sr04TaskHandle;
const osThreadAttr_t sr04Task_attributes = { const osThreadAttr_t sr04Task_attributes = {
.name = "sr04Task", .name = "sr04Task",
.stack_size = 128 * 4, .stack_size = 512 * 4,
.priority = (osPriority_t) osPriorityLow, .priority = (osPriority_t) osPriorityLow,
}; };
/* Definitions for rc522Task */ /* Definitions for rc522Task */
osThreadId_t rc522TaskHandle; osThreadId_t rc522TaskHandle;
const osThreadAttr_t rc522Task_attributes = { const osThreadAttr_t rc522Task_attributes = {
.name = "rc522Task", .name = "rc522Task",
.stack_size = 128 * 4, .stack_size = 512 * 4,
.priority = (osPriority_t) osPriorityBelowNormal, .priority = (osPriority_t) osPriorityBelowNormal,
}; };
/* Definitions for CmdQueue */ /* Definitions for CmdQueue */

View File

@@ -0,0 +1,331 @@
# Logistics Car Upper Computer AI Guide
## 1. Purpose
This document is written for an AI agent that will implement the upper computer application.
Goal: build a stable TCP client for the logistics car, with both auto mode and manual mecanum mode, based on the embedded protocol implemented in this repository.
Target users:
- AI coding agents (Copilot-like, AutoGen-like, etc.)
- Human developers who review AI-generated upper computer code
Out of scope:
- Modifying embedded firmware behavior
- Replacing transport protocol
---
## 2. Must-Follow Protocol Contract
### 2.1 Frame format
All commands and telemetry use ASCII text:
LOGI:<PAYLOAD>:<CS>#
Fields:
- LOGI: fixed header
- <PAYLOAD>: command or telemetry body
- <CS>: 2-digit uppercase hex checksum
- #: fixed frame tail
### 2.2 Checksum algorithm
Checksum is the low 8 bits of ASCII sum of all bytes from L in LOGI to the byte before the final colon before CS.
Pseudo:
1. base = "LOGI:" + payload
2. cs = sum(base bytes as ASCII) & 0xFF
3. frame = base + ":" + toHex2Upper(cs) + "#"
Python reference:
```python
def build_frame(payload: str) -> str:
base = f"LOGI:{payload}"
cs = sum(base.encode("ascii")) & 0xFF
return f"{base}:{cs:02X}#"
```
C# reference:
```csharp
static string BuildFrame(string payload)
{
string baseStr = $"LOGI:{payload}";
int sum = 0;
foreach (byte b in System.Text.Encoding.ASCII.GetBytes(baseStr))
sum = (sum + b) & 0xFF;
return $"{baseStr}:{sum:X2}#";
}
```
Important:
- Must use uppercase hex (for consistency)
- Do not append CRLF unless your socket tool requires it
- One frame can be sent as raw ASCII bytes directly
---
## 3. Command Set (PC -> Car)
### 3.1 Common control
- SP:xxx set speed 000..100
- ST:RUN start auto run
- ST:STOP stop run
- GS:xxx set target station (current firmware supports 001, 002)
### 3.2 Mode switch (new)
- MD:MAN switch to manual mecanum mode
- MD:AUTO switch to auto tracking mode
### 3.3 Manual movement (new, only valid in MAN mode)
- MV:FWD forward
- MV:BWD backward
- MV:LEFT strafe left
- MV:RIGHT strafe right
- MV:LF forward-left diagonal
- MV:RF forward-right diagonal
- MV:LB backward-left diagonal
- MV:RB backward-right diagonal
- MV:CW rotate clockwise
- MV:CCW rotate counterclockwise
- MV:STOP stop motion
If current mode is AUTO and you send MV:*:
- car returns FB:MV:0 (rejected)
- upper computer must first send MD:MAN
---
## 4. Telemetry and Feedback (Car -> PC)
### 4.1 Periodic status (every ~500ms)
Payload format:
STAT:SP:xxx,STA:xxx,RUN:x,MODE:mode,MAN:dir,DIS:d,TRK:b4b3b2b1,DEV:n,OBS:x,RPM:m1:m2:m3:m4
Fields:
- SP: speed percent
- STA: target station
- RUN: 1 running, 0 stopped
- MODE: AUTO or MAN
- MAN: STOP/FWD/BWD/LEFT/RIGHT/LF/RF/LB/RB/CW/CCW
- DIS: ultrasonic distance in cm
- TRK: 4-channel line mask, order H4 H3 H2 H1
- DEV: track deviation (auto mode meaningful)
- OBS: obstacle lock (1 blocked, 0 clear)
- RPM: 4 motor RPM, order M1:M2:M3:M4 (LR:LF:RF:RR)
### 4.2 Command feedback (immediate)
Payload format:
FB:<CMD>:<0|1>
Examples:
- FB:SP:1 speed accepted
- FB:GS:0 station invalid or parse fail
- FB:MV:0 movement rejected (for example mode mismatch)
Upper computer rule:
- Every button operation should wait for feedback timeout window
- If no feedback in timeout, mark command uncertain and retry policy applies
---
## 5. Upper Computer Architecture Requirements
AI must implement the upper computer with these modules.
### 5.1 Network module
Responsibilities:
- Maintain TCP connection lifecycle
- Auto reconnect with backoff
- Byte stream receive and frame extraction
Required behavior:
- Reconnect delay: 1s, 2s, 3s, then fixed 3s
- On reconnect success, UI state set to Connected
- On disconnect, all movement buttons should be disabled
### 5.2 Protocol module
Responsibilities:
- Build frames from payload
- Parse incoming frames
- Verify checksum before dispatch
Required behavior:
- Drop frame if checksum invalid
- Log invalid frame raw text for diagnostics
- Expose strongly typed events: StatusEvent, FeedbackEvent
### 5.3 Command dispatcher
Responsibilities:
- Serialize outbound commands (single queue)
- Attach request id locally (not in protocol) for UI correlation
- Wait feedback with timeout
Recommended defaults:
- Feedback timeout: 800 ms
- Max retries for idempotent commands (SP, MD, MV:STOP): 2
- No auto-retry for ST:RUN and GS:xxx unless user confirms
### 5.4 UI module
Required controls:
- Connection: IP, port, connect/disconnect
- Mode: AUTO / MAN toggle
- Speed: slider 0..100 with send button
- Auto controls: station selector (001/002), RUN, STOP
- Manual controls: directional keypad + rotation + STOP
- Status panel: parsed telemetry fields
- Logs panel: TX/RX raw frames + parsed result
### 5.5 Safety guard module
Required safety logic:
- If UI in MAN mode and mouse/touch release on direction button, auto send MV:STOP
- If no fresh status for >2s, show stale warning
- Emergency stop hotkey sends MV:STOP first; if in AUTO also send ST:STOP
---
## 6. Exact Button-to-Command Mapping
All below are complete frames with checksum, directly sendable.
### 6.1 Mode
- Switch to manual: LOGI:MD:MAN:0C#
- Switch to auto: LOGI:MD:AUTO:69#
### 6.2 Speed presets
- 30%: LOGI:SP:030:D5#
- 50%: LOGI:SP:050:D7#
- 80%: LOGI:SP:080:DA#
### 6.3 Auto mode
- Station 001: LOGI:GS:001:CA#
- Station 002: LOGI:GS:002:CB#
- Auto run: LOGI:ST:RUN:3B#
- Auto stop: LOGI:ST:STOP:8C#
### 6.4 Manual movement
- Forward: LOGI:MV:FWD:23#
- Backward: LOGI:MV:BWD:1F#
- Left strafe: LOGI:MV:LEFT:6D#
- Right strafe: LOGI:MV:RIGHT:C0#
- Forward-left: LOGI:MV:LF:D4#
- Forward-right: LOGI:MV:RF:DA#
- Backward-left: LOGI:MV:LB:D0#
- Backward-right: LOGI:MV:RB:D6#
- Rotate CW: LOGI:MV:CW:DC#
- Rotate CCW: LOGI:MV:CCW:1F#
- Stop: LOGI:MV:STOP:88#
---
## 7. Recommended Operation Sequences
### 7.1 Manual driving flow
1. Connect TCP
2. Send SP:xxx
3. Send MD:MAN
4. Hold direction button -> send MV:* repeatedly or once per state change
5. Release button -> send MV:STOP
Recommended send style for manual:
- Edge-triggered (on press send once, on release send stop) is preferred
- If network jitter is high, add keepalive send of same MV every 300 ms
### 7.2 Auto transport flow
1. Connect TCP
2. Send SP:xxx
3. Send MD:AUTO
4. Send GS:001 or GS:002
5. Send ST:RUN
6. Observe RUN and feedback/status until arrival
Arrival behavior in firmware:
- Car auto-stops on target RFID
- RUN becomes 0
- Next run requires sending GS again, then ST:RUN
---
## 8. Frame Parsing Strategy (Stream-safe)
TCP is stream-based, not message-based. AI must implement frame extraction correctly.
Required parser behavior:
- Keep a receive buffer string/byte array
- Search for header "LOGI:"
- Search for tail '#'
- Extract candidate frame from first valid header to first following '#'
- Validate checksum
- Dispatch valid frame; remove consumed bytes
- If garbage before header, discard garbage
Do not assume one recv equals one frame.
---
## 9. Error Handling and Recovery
### 9.1 Feedback timeout
If command has no FB within timeout:
- Mark as timeout in UI
- For safe idempotent commands, retry once or twice
- For movement commands, prefer fail-safe by sending STOP
### 9.2 Checksum mismatch in received data
- Drop frame
- Log as warning with raw text
- Keep connection alive (do not disconnect directly)
### 9.3 Mode conflict
If receiving FB:MV:0 after sending MV command:
- UI should hint: "Not in manual mode, switching to MAN"
- Auto-send MD:MAN then retry once
### 9.4 Connection loss during motion
On disconnect event:
- UI enters safe state
- disable movement controls
- after reconnect, require operator to re-confirm mode and speed
---
## 10. AI Implementation Checklist (Definition of Done)
Functional:
- Can connect/disconnect TCP manually
- Can parse status and feedback reliably
- All buttons send correct command frames
- Manual control works in all listed directions
- Auto mode flow works (GS + RUN + STOP)
Robustness:
- Stream parser handles sticky packets and split packets
- Reconnect works automatically
- Command timeout/retry policy implemented
- Logs include TX/RX and parse errors
Usability:
- Telemetry fields visible and updating
- Mode and direction state clearly shown
- Emergency stop is always accessible
Testing:
- Unit test for checksum build/verify
- Unit test for parser with mixed/fragmented frames
- Integration test with mock TCP server replaying status/feedback
---
## 11. Suggested Prompt for Coding AI
Use this prompt when asking another coding AI to generate the upper computer:
"Implement a production-ready TCP upper computer client for an STM32 logistics car protocol. Use ASCII frame format LOGI:<PAYLOAD>:<CS># with checksum as sum(base bytes) & 0xFF where base is LOGI:<PAYLOAD>. Support commands SP, ST, GS, MD, MV. Parse status payload STAT with fields SP, STA, RUN, MODE, MAN, DIS, TRK, DEV, OBS, RPM. Parse feedback payload FB:<CMD>:<0|1>. Build a stream-safe parser for sticky/fragmented TCP packets. Include reconnect, timeout/retry, and a UI with manual mecanum directional controls and auto mode controls."
---
## 12. Notes for Future Extension
If firmware adds fields later:
- Keep parser tolerant: unknown key-value pairs should not crash parser
- Preserve raw payload in logs for forward compatibility
- Version your app-side parser module (for example v1_2)

View File

@@ -0,0 +1,392 @@
# Python Web 上位机实施文档给开发AI直接执行
## 1. 目标与技术选型
目标:实现一个可运行、可联调、可扩展的上位机系统,满足以下要求:
- 与小车通过 TCP 协议通信
- 浏览器可视化控制(自动模式 + 手动麦轮模式)
- 实时状态显示500ms级
- 日志、重连、超时、错误恢复完整
推荐技术栈:
- 后端Python 3.11+
- Web框架FastAPI
- 实时推送WebSocket
- 异步asyncio
- 前端Vue3 或 React都可以本文给中立接口规范
- 部署Windows 本地运行(开发阶段)
建议架构:
- Browser UI <-> WebSocket/HTTP <-> Python Backend <-> TCP Socket <-> Car
---
## 2. 协议契约(必须严格一致)
帧格式:
LOGI:<PAYLOAD>:<CS>#
校验和:
- 对字符串 LOGI:<PAYLOAD> 做 ASCII 累加
- 取低8位
- 转 2位大写十六进制
Python函数必须实现并复用
```python
def build_frame(payload: str) -> str:
base = f"LOGI:{payload}"
cs = sum(base.encode("ascii")) & 0xFF
return f"{base}:{cs:02X}#"
```
已验证可直接发送的关键命令:
- LOGI:MD:MAN:0C#
- LOGI:MD:AUTO:69#
- LOGI:MV:FWD:23#
- LOGI:MV:BWD:1F#
- LOGI:MV:LEFT:6D#
- LOGI:MV:RIGHT:C0#
- LOGI:MV:LF:D4#
- LOGI:MV:RF:DA#
- LOGI:MV:LB:D0#
- LOGI:MV:RB:D6#
- LOGI:MV:CW:DC#
- LOGI:MV:CCW:1F#
- LOGI:MV:STOP:88#
- LOGI:SP:030:D5#
- LOGI:SP:050:D7#
- LOGI:SP:080:DA#
- LOGI:GS:001:CA#
- LOGI:GS:002:CB#
- LOGI:ST:RUN:3B#
- LOGI:ST:STOP:8C#
---
## 3. 项目目录AI生成代码必须遵循
```text
upper-computer-python-web/
backend/
app/
main.py
config.py
models.py
protocol.py
tcp_client.py
command_service.py
state_store.py
ws_hub.py
parser.py
logger.py
api/
http_routes.py
ws_routes.py
requirements.txt
frontend/
src/
main.ts
api.ts
ws.ts
store.ts
components/
ConnectionPanel.vue
ModePanel.vue
SpeedPanel.vue
AutoPanel.vue
ManualPad.vue
StatusPanel.vue
LogPanel.vue
package.json
README.md
```
---
## 4. 后端职责与实现要求
### 4.1 TCP客户端tcp_client.py
必须实现:
- connect(host, port)
- disconnect()
- send_frame(frame)
- background_read_loop()
- auto_reconnect_loop()
重连策略:
- 1s -> 2s -> 3s -> 3s循环
连接状态事件:
- connected
- disconnected
- reconnecting
- connect_failed
### 4.2 流式解析器parser.py
TCP是流必须做粘包拆包。
规则:
1. 维护 bytearray 缓冲区
2. 找 LOGI: 起点
3. 找 # 终点
4. 抽取候选帧
5. 校验和正确才分发
6. 错帧丢弃并记录日志
必须支持:
- 一次收多帧
- 一帧分多次收
- 帧前垃圾字节
### 4.3 协议服务protocol.py
必须提供:
- build_frame(payload)
- parse_frame(frame) -> dict
- verify_checksum(frame) -> bool
parse_frame 输出建议:
- type: status / feedback / unknown
- payload_raw
- fields: dict
### 4.4 命令服务command_service.py
必须实现命令队列与反馈匹配:
- send_command(payload, wait_feedback=True)
- 超时默认 800ms
- 可重试命令SP、MD、MV:STOP最多2次
- 非幂等命令 ST:RUN、GS 不自动重试
反馈格式:
- FB:<CMD>:<0|1>
### 4.5 状态存储state_store.py
维护全局状态对象:
- connection
- speed
- station
- run
- mode
- manual_dir
- distance
- trk
- dev
- obs
- rpm[4]
- last_status_ts
超过2秒无状态包
- 标记 stale = true
- 推送前端告警
### 4.6 WebSocket中枢ws_hub.py
前端订阅以下事件:
- conn_update
- status_update
- feedback_update
- tx_log
- rx_log
- warn
- error
---
## 5. HTTP 与 WebSocket 接口规范
### 5.1 HTTP
1) POST /api/connect
- body: {"host":"192.168.1.50","port":3456}
- resp: {"ok":true}
2) POST /api/disconnect
- resp: {"ok":true}
3) POST /api/cmd
- body: {"payload":"MV:FWD","waitFeedback":true}
- resp: {"ok":true,"feedback":{"cmd":"MV","status":1}}
4) GET /api/state
- resp: 全量状态JSON
5) GET /api/health
- resp: {"ok":true}
### 5.2 WebSocket
- ws://host:port/ws
消息统一格式:
- {"event":"status_update","data":{...}}
- {"event":"feedback_update","data":{...}}
- {"event":"tx_log","data":{"frame":"..."}}
- {"event":"rx_log","data":{"frame":"..."}}
---
## 6. 前端页面与按钮行为
页面最少包含:
- 连接面板IP、端口、连接/断开
- 模式面板AUTO / MAN
- 速度面板0-100滑条 + 发送按钮
- 自动面板站点001/002、RUN、STOP
- 手动面板8方向 + CW/CCW + STOP
- 状态面板SP/STA/RUN/MODE/MAN/DIS/TRK/DEV/OBS/RPM
- 日志面板TX/RX
按钮映射要求:
1) 切手动
- 发送 payload: MD:MAN
2) 切自动
- 发送 payload: MD:AUTO
3) 速度
- 发送 payload: SP:xxx补零3位
4) 自动站点
- 001 -> GS:001
- 002 -> GS:002
5) 自动运行控制
- RUN -> ST:RUN
- STOP -> ST:STOP
6) 手动方向
- 前进 MV:FWD
- 后退 MV:BWD
- 左移 MV:LEFT
- 右移 MV:RIGHT
- 左前 MV:LF
- 右前 MV:RF
- 左后 MV:LB
- 右后 MV:RB
- 顺时针 MV:CW
- 逆时针 MV:CCW
- 停止 MV:STOP
手动安全行为(必须):
- 按下方向键发对应MV
- 松开方向键:立即发 MV:STOP
---
## 7. 关键业务逻辑(必须实现)
### 7.1 模式冲突恢复
如果发送 MV:* 收到 FB:MV:0
1. 自动提示“当前不在手动模式”
2. 自动发送 MD:MAN
3. 重试一次原MV命令
### 7.2 断线保护
断线时:
- 禁用全部运动按钮
- UI状态置灰
- 重连成功后,不自动恢复运动,必须人工再次点方向
### 7.3 急停策略
急停按钮逻辑:
1. 先发 MV:STOP
2. 若当前模式是AUTO再发 ST:STOP
### 7.4 自动流程约束
自动流程推荐顺序:
- SP -> MD:AUTO -> GS -> ST:RUN
到站后固件会锁存,下一次运行前应:
- 重发 GS
- 再发 ST:RUN
---
## 8. 后端参考代码骨架(最小可运行)
main.py 示例:
```python
from fastapi import FastAPI, WebSocket
from app.api.http_routes import router as http_router
from app.api.ws_routes import router as ws_router
app = FastAPI(title="Car Upper Computer")
app.include_router(http_router, prefix="/api")
app.include_router(ws_router)
@app.get("/api/health")
async def health():
return {"ok": True}
```
command_service.py 的命令发送入口示例:
```python
async def send_payload(payload: str, wait_feedback: bool = True):
frame = build_frame(payload)
await tcp_client.send_frame(frame)
await ws_hub.broadcast("tx_log", {"frame": frame})
if not wait_feedback:
return {"ok": True}
fb = await feedback_waiter.wait(payload.split(":", 1)[0], timeout=0.8)
return {"ok": fb is not None, "feedback": fb}
```
---
## 9. 联调步骤(按此执行)
1. 启动后端
- uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
2. 启动前端
- npm install
- npm run dev
3. 页面连接到小车TCP
- 输入IP和端口
- 点击连接
4. 先测基础命令
- SP:050
- MD:MAN
- MV:FWD
- MV:STOP
5. 再测自动流程
- MD:AUTO
- GS:001
- ST:RUN
6. 检查状态面板字段是否持续刷新
---
## 10. 测试清单(必须通过)
单元测试:
- build_frame校验值正确
- verify_checksum正确拦截坏包
- parser支持粘包拆包
集成测试:
- 命令发送后能收到FB
- 状态包断流时 stale 告警出现
- 断线后自动重连并恢复状态展示
交互测试:
- 手动按钮按下/松开逻辑正确
- 急停在任意状态都可触发
---
## 11. 给开发AI的最终任务提示词
请实现一个 Python Web 上位机系统,后端用 FastAPI + asyncio TCP + WebSocket前端用 Vue3 或 React。协议为 LOGI:<PAYLOAD>:<CS>#CS 为 LOGI:<PAYLOAD> 的 ASCII 累加低8位。实现 SP/ST/GS/MD/MV 命令,解析 STAT 与 FB。支持手动麦轮方向控制8方向+旋转+STOP和自动模式控制。必须实现 TCP 粘包拆包解析、命令反馈超时处理、自动重连、状态实时推送、日志面板与安全急停逻辑。

View File

@@ -0,0 +1,311 @@
# 上位机开发AI执行文档物流小车 TCP 协议)
## 1. 文档目标
这份文档是写给“负责开发上位机的AI”的不是普通说明书。
目标是让AI按本文档直接产出可运行的上位机程序TCP客户端并且与当前固件协议完全兼容。
适用范围:
- Windows上位机Python / C# / C++ / Electron均可
- 控制模式:自动循迹 + 手动麦克纳姆
- 通信方式TCPASCII协议
不做的事情:
- 不修改单片机固件协议
- 不更换通信栈
---
## 2. 协议总规范(必须严格遵守)
### 2.1 帧格式
所有收发数据都使用:
LOGI:<PAYLOAD>:<CS>#
字段说明:
- LOGI: 固定帧头
- <PAYLOAD>: 有效载荷
- <CS>: 2位大写十六进制校验和
- #: 固定帧尾
### 2.2 校验和算法
计算范围是 LOGI:PAYLOAD 这一段(不含最后 :CS#)。
算法ASCII逐字节累加取低8位。
示例代码Python
```python
def build_frame(payload: str) -> str:
base = f"LOGI:{payload}"
cs = sum(base.encode("ascii")) & 0xFF
return f"{base}:{cs:02X}#"
```
示例代码C#
```csharp
static string BuildFrame(string payload)
{
string baseStr = $"LOGI:{payload}";
int sum = 0;
foreach (byte b in System.Text.Encoding.ASCII.GetBytes(baseStr))
sum = (sum + b) & 0xFF;
return $"{baseStr}:{sum:X2}#";
}
```
硬性要求:
- 十六进制统一大写
- 不要额外拼接换行(除非你的网络调试工具强制)
---
## 3. 下行指令(上位机 -> 小车)
### 3.1 通用控制
- SP:xxx 设置速度000~100
- ST:RUN 自动启动
- ST:STOP 自动停止
- GS:xxx 设置目标站点当前固件支持001/002
### 3.2 模式切换(新增)
- MD:MAN 切换手动麦轮模式
- MD:AUTO 切换自动循迹模式
### 3.3 手动方向新增仅MAN模式有效
- MV:FWD 前进
- MV:BWD 后退
- MV:LEFT 左平移
- MV:RIGHT 右平移
- MV:LF 左前
- MV:RF 右前
- MV:LB 左后
- MV:RB 右后
- MV:CW 原地顺时针
- MV:CCW 原地逆时针
- MV:STOP 停止
注意:
- 若处于AUTO模式直接发MV:*,固件会返回 FB:MV:0
- 上位机应先发 MD:MAN 再发 MV:*
---
## 4. 上行数据(小车 -> 上位机)
### 4.1 状态上报约500ms
PAYLOAD格式
STAT:SP:xxx,STA:xxx,RUN:x,MODE:mode,MAN:dir,DIS:d,TRK:b4b3b2b1,DEV:n,OBS:x,RPM:m1:m2:m3:m4
字段含义:
- SP: 当前速度百分比
- STA: 当前目标站点
- RUN: 1运行0停止
- MODE: AUTO 或 MAN
- MAN: STOP/FWD/BWD/LEFT/RIGHT/LF/RF/LB/RB/CW/CCW
- DIS: 超声距离cm
- TRK: 循迹4位掩码H4 H3 H2 H1
- DEV: 偏差值(自动模式更有意义)
- OBS: 避障锁1有障碍0无
- RPM: 4路电机转速顺序 M1:M2:M3:M4LR:LF:RF:RR
### 4.2 命令反馈(即时)
PAYLOAD格式
FB:<CMD>:<0|1>
示例:
- FB:SP:1 表示设置速度成功
- FB:MV:0 表示手动命令被拒绝(如模式不对)
上位机处理规则:
- 每个按钮操作都要等待反馈超时窗口
- 无反馈应标记为超时,按策略重试或提示用户
---
## 5. 上位机程序架构要求AI必须实现
### 5.1 网络层
功能:
- TCP连接/断开
- 自动重连
- 接收字节流
要求:
- 重连退避1s -> 2s -> 3s -> 3s...
- 断线后禁用运动按钮
- 重连成功后状态切到已连接
### 5.2 协议层
功能:
- 组帧payload -> frame
- 解帧frame -> typed message
- 校验和验证
要求:
- 校验失败帧丢弃并记录日志
- 提供结构化事件StatusEvent / FeedbackEvent
### 5.3 命令调度层
功能:
- 发送队列串行化
- 等待反馈
- 超时重试
建议默认:
- 反馈超时 800ms
- 可重试命令SP、MD、MV:STOP最多2次
- ST:RUN、GS:xxx不自动重试避免误动作
### 5.4 UI层
必须具备控件:
- 网络连接区IP、端口、连接/断开
- 模式区AUTO/MAN
- 速度区:滑条+发送
- 自动区站点选择、RUN、STOP
- 手动区方向盘8方向+旋转+STOP
- 状态区实时显示SP/STA/RUN/MODE/MAN/DIS/TRK/DEV/OBS/RPM
- 日志区TX/RX原始帧 + 解析结果
### 5.5 安全保护
必须实现:
- 手动方向按钮松开时自动发送 MV:STOP
- 2秒无状态包UI提示“状态超时”
- 急停键:优先发 MV:STOP若在AUTO再发 ST:STOP
---
## 6. 按钮与命令映射(可直接发送,含校验)
### 6.1 模式
- 手动模式LOGI:MD:MAN:0C#
- 自动模式LOGI:MD:AUTO:69#
### 6.2 速度快捷键
- 30%LOGI:SP:030:D5#
- 50%LOGI:SP:050:D7#
- 80%LOGI:SP:080:DA#
### 6.3 自动流程按钮
- 站点001LOGI:GS:001:CA#
- 站点002LOGI:GS:002:CB#
- 启动LOGI:ST:RUN:3B#
- 停止LOGI:ST:STOP:8C#
### 6.4 手动方向按钮
- 前进LOGI:MV:FWD:23#
- 后退LOGI:MV:BWD:1F#
- 左移LOGI:MV:LEFT:6D#
- 右移LOGI:MV:RIGHT:C0#
- 左前LOGI:MV:LF:D4#
- 右前LOGI:MV:RF:DA#
- 左后LOGI:MV:LB:D0#
- 右后LOGI:MV:RB:D6#
- 顺时针LOGI:MV:CW:DC#
- 逆时针LOGI:MV:CCW:1F#
- 停止LOGI:MV:STOP:88#
---
## 7. 操作时序AI实现时必须按此流程
### 7.1 手动控制时序
1. 连接TCP
2. 发速度 SP:xxx
3. 发 MD:MAN
4. 按下方向键发 MV:*
5. 松开方向键发 MV:STOP
建议:
- 优先“边沿发送”按下发一次松开发STOP
- 若网络抖动明显可每300ms补发一次当前MV松开必发STOP
### 7.2 自动运输时序
1. 连接TCP
2. 发速度 SP:xxx
3. 发 MD:AUTO
4. 发 GS:001 或 GS:002
5. 发 ST:RUN
6. 监控状态包直到到站
固件行为:
- 到站会自动停
- RUN变0
- 再次启动前需先重发GS再发ST:RUN
---
## 8. TCP粘包/拆包解析要求
TCP是流不能假设一次recv就是一帧。
必须实现:
- 维护接收缓存
- 搜索帧头 LOGI:
- 搜索帧尾 #
- 从有效头到尾提取候选帧
- 校验通过才分发
- 头前垃圾数据丢弃
如果不做这一层,上位机会出现随机解析错误。
---
## 9. 错误处理策略
### 9.1 超时
- 指令超时无反馈UI标红并记录日志
- 安全指令可重试
- 运动指令超时优先补发STOP
### 9.2 校验失败
- 丢弃该帧
- 记录原始帧日志
- 不要直接断线
### 9.3 模式冲突
收到 FB:MV:0 时:
1. 自动提示“当前非手动模式”
2. 自动发 MD:MAN
3. 重试一次原MV命令
### 9.4 断线
- 立刻禁用控制按钮
- 显示离线
- 重连成功后要求用户确认模式和速度后再控车
---
## 10. AI交付验收清单Definition of Done
功能通过:
- 能连接/断开TCP
- 能正确收发并解析状态和反馈
- 全部按钮命令可用
- 手动10方向可控
- 自动流程可用GS+RUN+STOP
稳定性通过:
- 粘包拆包处理正确
- 自动重连生效
- 超时重试策略生效
- 日志可追溯
可用性通过:
- 状态字段实时刷新
- 当前模式和方向显示清晰
- 急停入口明显且可用
测试通过:
- 校验和单元测试
- 解析器单元测试(粘包/拆包/坏包)
- 联调测试与真实小车或Mock服务
---
## 11. 给“上位机开发AI”的可直接任务描述
请将下面这段作为任务输入给编码AI
实现一个可发布的物流小车TCP上位机客户端。协议是ASCII帧 LOGI:<PAYLOAD>:<CS>#,校验算法为 sum(LOGI:<PAYLOAD>的ASCII字节) & 0xFF。实现命令 SP/ST/GS/MD/MV解析状态STAT和反馈FB。支持自动模式和手动麦克纳姆模式8方向+旋转+停止。必须实现TCP流式粘包拆包解析、自动重连、命令超时重试、原始日志和结构化状态显示。UI必须包含连接区、模式区、速度区、自动区、手动方向区、状态区和日志区。

View File

@@ -33,11 +33,11 @@ Dma.USART2_TX.2.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
Dma.USART2_TX.2.PeriphInc=DMA_PINC_DISABLE Dma.USART2_TX.2.PeriphInc=DMA_PINC_DISABLE
Dma.USART2_TX.2.Priority=DMA_PRIORITY_LOW Dma.USART2_TX.2.Priority=DMA_PRIORITY_LOW
Dma.USART2_TX.2.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority Dma.USART2_TX.2.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority
FREERTOS.FootprintOK=true FREERTOS.FootprintOK=false
FREERTOS.IPParameters=Tasks01,FootprintOK,Queues01,configTOTAL_HEAP_SIZE FREERTOS.IPParameters=Tasks01,FootprintOK,Queues01,configTOTAL_HEAP_SIZE
FREERTOS.Queues01=CmdQueue,16,16,1,Dynamic,NULL,NULL FREERTOS.Queues01=CmdQueue,16,16,1,Dynamic,NULL,NULL
FREERTOS.Tasks01=initTask,24,128,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL;CarCtrlTask,24,256,CarCtrl_Task,As weak,NULL,Dynamic,NULL,NULL;timerTask,16,512,speed_get,As weak,NULL,Dynamic,NULL,NULL;sr04Task,8,128,sr04_task,Default,NULL,Dynamic,NULL,NULL;rc522Task,16,128,rc522_task,Default,NULL,Dynamic,NULL,NULL FREERTOS.Tasks01=initTask,24,256,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL;CarCtrlTask,24,1024,CarCtrl_Task,As weak,NULL,Dynamic,NULL,NULL;timerTask,16,1024,speed_get,As weak,NULL,Dynamic,NULL,NULL;sr04Task,8,512,sr04_task,Default,NULL,Dynamic,NULL,NULL;rc522Task,16,512,rc522_task,Default,NULL,Dynamic,NULL,NULL
FREERTOS.configTOTAL_HEAP_SIZE=10000 FREERTOS.configTOTAL_HEAP_SIZE=18000
File.Version=6 File.Version=6
GPIO.groupedBy=Group By Peripherals GPIO.groupedBy=Group By Peripherals
KeepUserPlacement=false KeepUserPlacement=false

View File

@@ -32,7 +32,7 @@
<add key="super_send23hex_checked" value="0" /> <add key="super_send23hex_checked" value="0" />
<add key="super_send24hex_checked" value="0" /> <add key="super_send24hex_checked" value="0" />
<add key="super_send25hex_checked" value="0" /> <add key="super_send25hex_checked" value="0" />
<add key="super_text_send" value="你好啊啊" /> <add key="super_text_send" value="AT+RST #复位" />
<add key="super_text_send1" value="AT #测试" /> <add key="super_text_send1" value="AT #测试" />
<add key="super_text_send2" value="AT+CWMODE=1 #设置工作模式为STA" /> <add key="super_text_send2" value="AT+CWMODE=1 #设置工作模式为STA" />
<add key="super_text_send3" value="AT+CWJAP=&quot;ssid&quot;,&quot;password&quot; #配置WIFI" /> <add key="super_text_send3" value="AT+CWJAP=&quot;ssid&quot;,&quot;password&quot; #配置WIFI" />
@@ -60,7 +60,7 @@
<add key="super_text_send25" value="" /> <add key="super_text_send25" value="" />
<add key="super_num_time1" value="800" /> <add key="super_num_time1" value="800" />
<add key="super_num_time2" value="500" /> <add key="super_num_time2" value="500" />
<add key="super_rate" value="6" /> <add key="super_rate" value="5" />
<add key="super_parity" value="0" /> <add key="super_parity" value="0" />
<add key="super_databits" value="1" /> <add key="super_databits" value="1" />
<add key="super_stopbit" value="0" /> <add key="super_stopbit" value="0" />

View File

@@ -10,7 +10,7 @@ SendHex=0
[DlgCreateServer] [DlgCreateServer]
DlgServerPort=3456 DlgServerPort=3456
[Update] [Update]
Time=1775660879 Time=1776317344
[SysOptions] [SysOptions]
SendBlSZforFile=10240 SendBlSZforFile=10240
SendBlITforFile=1 SendBlITforFile=1

View File

@@ -62,7 +62,7 @@ file_sel13 = 0
file_path13 = file_path13 =
file_flag13 = False file_flag13 = False
file_offset13 = file_offset13 =
default_path = E:\My_Workpace\ÎïÁ÷С³µ\esp_12f\flash_download_tool_3.9.7 default_path = E:\My_Workpace\f103_car\ÎïÁ÷С³µ\esp_12f\flash_download_tool_3.9.7
[FLASH_CRYSTAL] [FLASH_CRYSTAL]
spicfgdis = 1 spicfgdis = 1

View File

@@ -7,7 +7,7 @@ multi_col = 2
[DOWNLOAD PATH] [DOWNLOAD PATH]
file_sel0 = 1 file_sel0 = 1
file_path0 = E:\My_Workpace\ÎïÁ÷С³µ\esp_12f\flash_download_tool_3.9.7\£¨1112£©ESP8266-4M.bin file_path0 = E:\My_Workpace\f103_car\ÎïÁ÷С³µ\esp_12f\£¨1112£©ESP8266-4M.bin
file_flag0 = False file_flag0 = False
file_offset0 = 0 file_offset0 = 0
file_sel1 = 0 file_sel1 = 0
@@ -62,7 +62,7 @@ file_sel13 = 0
file_path13 = file_path13 =
file_flag13 = False file_flag13 = False
file_offset13 = file_offset13 =
default_path = E:\My_Workpace\ÎïÁ÷С³µ\esp_12f\flash_download_tool_3.9.7 default_path = E:\My_Workpace\f103_car\ÎïÁ÷С³µ\esp_12f
[FLASH_CRYSTAL] [FLASH_CRYSTAL]
spicfgdis = 1 spicfgdis = 1

Binary file not shown.