Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
esp32c3-tank-remote-control
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
957dd
esp32c3-tank-remote-control
Commits
c73e2052
Commit
c73e2052
authored
Mar 16, 2026
by
957dd
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
加入了优化遥控器
parent
50a056cf
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
122 additions
and
5 deletions
+122
-5
hardware_ctrl.c
main/hardware_ctrl.c
+0
-1
mqttconf_commun.c
main/mqttconf_commun.c
+122
-4
No files found.
main/hardware_ctrl.c
View file @
c73e2052
...
@@ -217,7 +217,6 @@ esp_err_t hardware_init(){
...
@@ -217,7 +217,6 @@ esp_err_t hardware_init(){
}
}
static
void
pin_value
(
int
pin
,
int
val
){
static
void
pin_value
(
int
pin
,
int
val
){
if
(
val
>
1
)
val
=
1
;
if
(
val
>
1
)
val
=
1
;
for
(
int
i
=
0
;
i
<
6
;
i
++
){
for
(
int
i
=
0
;
i
<
6
;
i
++
){
...
...
main/mqttconf_commun.c
View file @
c73e2052
...
@@ -43,6 +43,37 @@ static esp_mqtt_client_handle_t client_list[MAX_MQTT_CLIENTS] = {NULL};
...
@@ -43,6 +43,37 @@ static esp_mqtt_client_handle_t client_list[MAX_MQTT_CLIENTS] = {NULL};
static
int
client_count
=
0
;
static
int
client_count
=
0
;
static
esp_timer_handle_t
g_hb_timer
=
NULL
;
static
esp_timer_handle_t
g_hb_timer
=
NULL
;
// 遥控保活:在“无人控制”一段时间后,周期性触发“左转脉冲 + 右转脉冲”心跳序列
static
esp_timer_handle_t
g_ctrl_hb_timer
=
NULL
;
static
int64_t
g_last_ctrl_msg_ms
=
0
;
// 最近一次收到 message_type=3/4 的时间(ms)
static
int64_t
g_last_ctrl_keepalive_ms
=
0
;
// 最近一次完成心跳“左+右”序列的时间(ms)
// g_ctrl_hb_phase:
// 0: 未触发; 1: 已发左转脉冲; 2: 已发右转脉冲(本轮完成)
static
int
g_ctrl_hb_phase
=
0
;
// 脉冲转向任务:发一次 mode(50),延时若干 ms,再发一次 mode(0)
static
void
steer_pulse_task
(
void
*
pvParameters
)
{
int
mode
=
(
int
)(
intptr_t
)
pvParameters
;
// 发一个 50 的转向
device_hardware_walk_control
(
mode
,
50
);
// 几百毫秒后回到 0(中位)
vTaskDelay
(
pdMS_TO_TICKS
(
300
));
device_hardware_walk_control
(
mode
,
0
);
vTaskDelete
(
NULL
);
}
static
void
start_steer_pulse
(
int
mode
)
{
xTaskCreate
(
steer_pulse_task
,
"steer_pulse"
,
2048
,
(
void
*
)(
intptr_t
)
mode
,
5
,
NULL
);
}
static
int
mqttabnormal_exit_count
=
0
;
static
int
mqttabnormal_exit_count
=
0
;
int
mqtt_send_deviceota_info
(
void
);
int
mqtt_send_deviceota_info
(
void
);
...
@@ -59,6 +90,13 @@ static void handle_remote_control(const char *data) {
...
@@ -59,6 +90,13 @@ static void handle_remote_control(const char *data) {
cJSON
*
m_type
=
cJSON_GetObjectItem
(
head
,
"message_type"
);
cJSON
*
m_type
=
cJSON_GetObjectItem
(
head
,
"message_type"
);
cJSON
*
body
=
cJSON_GetObjectItem
(
root
,
"body"
);
cJSON
*
body
=
cJSON_GetObjectItem
(
root
,
"body"
);
// 任意 message_type=3/4 认为是“有人在控制”,记录时间并重置心跳状态
if
(
m_type
&&
(
m_type
->
valueint
==
3
||
m_type
->
valueint
==
4
))
{
g_last_ctrl_msg_ms
=
esp_timer_get_time
()
/
1000
;
// us -> ms
g_ctrl_hb_phase
=
0
;
g_last_ctrl_keepalive_ms
=
g_last_ctrl_msg_ms
;
}
if
(
m_type
&&
m_type
->
valueint
==
4
&&
body
)
{
if
(
m_type
&&
m_type
->
valueint
==
4
&&
body
)
{
cJSON
*
pin_ctrl
=
cJSON_GetObjectItem
(
body
,
"pin_setctrl"
);
cJSON
*
pin_ctrl
=
cJSON_GetObjectItem
(
body
,
"pin_setctrl"
);
if
(
pin_ctrl
)
{
if
(
pin_ctrl
)
{
...
@@ -132,6 +170,64 @@ static void mqtt_heartbeat_timer_cb(void *arg) {
...
@@ -132,6 +170,64 @@ static void mqtt_heartbeat_timer_cb(void *arg) {
free
(
json
);
free
(
json
);
}
}
/**
* @brief 控制保活:只要持续无人控制,每隔 30s 发送一次“左转脉冲 + 右转脉冲”序列
* - 条件:距离最近一次 message_type=3/4 控制指令超过 30s
* - 并且:距离最近一次完成“左+右”心跳序列也超过 30s
* - 满足时:phase==0 -> 触发一次左转脉冲(50→0),phase->1
* 下一次定时器(2s 后) 且仍然无人控制时:phase==1 -> 触发一次右转脉冲(50→0),phase->2
* - phase==2:本轮完结,记录完成时间,等待下一个 30s 周期
*/
static
void
mqtt_ctrl_keepalive_timer_cb
(
void
*
arg
)
{
// 没有任何 MQTT 客户端时直接返回
if
(
client_count
==
0
)
{
return
;
}
int64_t
now_ms
=
esp_timer_get_time
()
/
1000
;
// us -> ms
int64_t
idle_ms
=
now_ms
-
g_last_ctrl_msg_ms
;
// 最近 30s 内收到过 message_type=3/4,则认为“有人在控制”,不发送心跳转向命令,
// 同时重置本轮心跳阶段和“最近心跳时间”
if
(
idle_ms
<=
30000
)
{
g_ctrl_hb_phase
=
0
;
g_last_ctrl_keepalive_ms
=
now_ms
;
return
;
}
// 已经超过 30s 无人控制:需要再看距离上次心跳是否超过 30s
if
(
g_last_ctrl_keepalive_ms
==
0
)
{
// 首次启动时,让它以“当前时间”为基准
g_last_ctrl_keepalive_ms
=
now_ms
;
}
// 如果上一轮“左+右”已经做完(phase>=2),且距离上次心跳已经超过 30s,则允许开启新一轮
if
(
g_ctrl_hb_phase
>=
2
&&
(
now_ms
-
g_last_ctrl_keepalive_ms
>=
30000
))
{
g_ctrl_hb_phase
=
0
;
}
// 如果还没有到下一次 30s 周期,且当前还没开始本轮(phase==0),则什么也不做
if
(
g_ctrl_hb_phase
==
0
&&
(
now_ms
-
g_last_ctrl_keepalive_ms
<
30000
))
{
return
;
}
// 超过 30s 无人控制,并且到了新的 30s 周期,根据阶段做一次性“左转脉冲 + 右转脉冲”序列
if
(
g_ctrl_hb_phase
==
0
)
{
// 第一次满足:触发一次左转脉冲(50→0)
start_steer_pulse
(
3
);
// 左转脉冲
g_ctrl_hb_phase
=
1
;
}
else
if
(
g_ctrl_hb_phase
==
1
)
{
// 第二阶段:触发一次右转脉冲(50→0),本轮结束
start_steer_pulse
(
4
);
// 右转脉冲
g_ctrl_hb_phase
=
2
;
// 本轮“左+右”已完成,记录完成时间,用于下一次 30s 计时
g_last_ctrl_keepalive_ms
=
now_ms
;
}
else
{
// phase >= 2,本轮已经做完左/右两个脉冲,不再发送
return
;
}
}
// 定时器句柄
// 定时器句柄
TimerHandle_t
ota_msg_timer
;
TimerHandle_t
ota_msg_timer
;
...
@@ -346,6 +442,17 @@ start_timer:
...
@@ -346,6 +442,17 @@ start_timer:
esp_timer_start_periodic
(
g_hb_timer
,
3000000
);
esp_timer_start_periodic
(
g_hb_timer
,
3000000
);
ESP_LOGI
(
TAG
,
"并发心跳群发机制已启动"
);
ESP_LOGI
(
TAG
,
"并发心跳群发机制已启动"
);
}
}
// 控制保活定时器:每 2s 检查一次是否需要自动左右转
const
esp_timer_create_args_t
ctrl_timer_args
=
{
.
callback
=
&
mqtt_ctrl_keepalive_timer_cb
,
.
name
=
"ctrl_hb_timer"
};
if
(
esp_timer_create
(
&
ctrl_timer_args
,
&
g_ctrl_hb_timer
)
==
ESP_OK
)
{
// 2s 触发一次
esp_timer_start_periodic
(
g_ctrl_hb_timer
,
2000000
);
ESP_LOGI
(
TAG
,
"遥控保活左右转机制已启动"
);
}
vTaskDelete
(
NULL
);
vTaskDelete
(
NULL
);
}
}
...
@@ -361,6 +468,13 @@ void mqtt_manager_stop(void) {
...
@@ -361,6 +468,13 @@ void mqtt_manager_stop(void) {
g_hb_timer
=
NULL
;
g_hb_timer
=
NULL
;
}
}
// 停止并删除控制保活定时器
if
(
g_ctrl_hb_timer
!=
NULL
)
{
esp_timer_stop
(
g_ctrl_hb_timer
);
esp_timer_delete
(
g_ctrl_hb_timer
);
g_ctrl_hb_timer
=
NULL
;
}
// 2. 销毁所有 MQTT 客户端
// 2. 销毁所有 MQTT 客户端
for
(
int
i
=
0
;
i
<
client_count
;
i
++
)
{
for
(
int
i
=
0
;
i
<
client_count
;
i
++
)
{
if
(
client_list
[
i
]
!=
NULL
)
{
if
(
client_list
[
i
]
!=
NULL
)
{
...
@@ -430,10 +544,14 @@ void mqtt_abnormal_exittask(void *pvParameters)
...
@@ -430,10 +544,14 @@ void mqtt_abnormal_exittask(void *pvParameters)
vTaskDelay
(
pdMS_TO_TICKS
(
1000
));
vTaskDelay
(
pdMS_TO_TICKS
(
1000
));
continue
;
continue
;
}
}
if
(
mqttabnormal_exit_count
>
5
){
// 只有在“曾经有过 MQTT 控制指令(3/4)”之后,才开启异常保护逻辑。
device_hardware_stop
();
// 否则还处在“纯心跳保活阶段”,此时应以心跳优先,不要随便拉 device_hardware_stop。
mqttabnormal_exit_count
=
6
;
if
(
g_last_ctrl_msg_ms
>
0
)
{
if
(
mqttabnormal_exit_count
>
5
){
device_hardware_stop
();
mqttabnormal_exit_count
=
6
;
}
}
}
vTaskDelay
(
pdMS_TO_TICKS
(
100
));
vTaskDelay
(
pdMS_TO_TICKS
(
100
));
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment