编程技术分享

分享编程知识,探讨技术创新

0%

简介:此项目采用ESP8266主控,支持手机遥控,采用插件封装,非常适合新手焊接。

好的,收到你的需求。这是一个典型的基于 ESP8266 的嵌入式控制项目,看起来像是一个简单的四足机器人。我将从需求分析、系统设计、代码架构、具体实现和测试验证等方面,详细阐述一个可靠、高效、可扩展的系统平台,并提供大量注释的 C 代码。
关注微信公众号,提前获取相关推文

1. 需求分析

首先,我们需要明确这个项目的需求:

  • 基础功能:
    • 通过手机 App 进行无线遥控(使用 Wi-Fi)。
    • 控制四个舵机,实现机器人的前进、后退、转弯等基本运动。
    • 具备一定的可扩展性,方便后续增加传感器和功能。
  • 硬件要求:
    • 主控芯片:ESP8266。
    • 舵机:四个标准舵机。
    • 电源:合适的供电模块。
    • 通信模块:ESP8266 自带的 Wi-Fi。
  • 软件要求:
    • 使用 C 语言开发。
    • 采用模块化设计,方便维护和扩展。
    • 实现 Wi-Fi 连接和数据通信功能。
    • 提供 API 接口,方便上层应用调用。
    • 具备错误处理和异常恢复机制。
  • 额外考虑:
    • 简单易用,适合新手焊接和学习。
    • 功耗控制,提高电池续航。
    • 代码的可读性和可维护性。

2. 系统设计

基于以上需求,我将系统分为以下几个模块:

  • 硬件抽象层 (HAL):
    • 封装底层硬件操作,如 GPIO、PWM、定时器等。
    • 提供统一接口,屏蔽硬件差异。
    • 方便日后更换硬件平台。
  • Wi-Fi 模块:
    • 负责 Wi-Fi 连接、数据接收和发送。
    • 使用 ESP8266 的 SDK 提供的 Wi-Fi API。
    • 处理连接状态,重连等。
  • 舵机控制模块:
    • 封装舵机驱动逻辑。
    • 提供舵机控制接口,如设定角度、停止等。
    • 可扩展支持不同的舵机类型。
  • 运动控制模块:
    • 根据接收到的指令,控制舵机运动。
    • 实现前进、后退、转弯等运动模式。
    • 可扩展支持更多运动姿态。
  • 协议解析模块:
    • 解析从手机 App 发送过来的控制指令。
    • 将指令转换为舵机控制动作。
    • 实现命令校验、参数提取等功能。
  • 应用层:
    • 整合各模块,实现具体功能。
    • 提供配置选项,如 Wi-Fi SSID 和密码等。
    • 处理程序初始化和主循环。
  • 系统模块:
    • 处理全局错误和状态管理。
    • 提供日志和调试功能。
  • 插件模块:
    • 为了满足新手焊接的需求,采用插件式的设计,方便用户扩展功能。

3. 代码架构

我将采用分层架构面向对象的设计思想来实现此系统,其优点包括:

  • 高内聚低耦合: 每个模块功能单一,模块间依赖性低,方便维护和复用。
  • 可扩展性好: 可以灵活地添加或修改模块,而不影响其他模块。
  • 易于理解: 模块化结构使代码层次清晰,方便阅读和调试。
  • 方便单元测试: 各模块可以独立进行测试,确保代码质量。

4. 具体实现 (C 代码)

下面是详细的 C 代码实现,包括每个模块的头文件和源文件。代码中会添加大量注释,帮助理解。

4.1. hardware_abstraction_layer (HAL) 模块

  • hal.h:
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
#ifndef HAL_H
#define HAL_H

#include <stdint.h>
#include <stdbool.h>

// 定义 GPIO 引脚号,根据实际硬件连接修改
#define SERVO_PIN1 12
#define SERVO_PIN2 13
#define SERVO_PIN3 14
#define SERVO_PIN4 15

// 定义PWM的频率和分辨率
#define PWM_FREQUENCY 50
#define PWM_RESOLUTION 10 // 10位分辨率, 0~1023

// 初始化 GPIO 引脚
void hal_gpio_init(int pin, int mode);
// 写入 GPIO 电平
void hal_gpio_write(int pin, bool value);

// 初始化 PWM
void hal_pwm_init(int pin);
// 设置 PWM 占空比
void hal_pwm_set_duty(int pin, int duty);

// 初始化定时器
void hal_timer_init(uint32_t ms, void (*callback)(void));

// 启动定时器
void hal_timer_start();

// 停止定时器
void hal_timer_stop();

// 延迟函数
void hal_delay_ms(uint32_t ms);


#endif
  • hal.c:
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
#include "hal.h"
#include <esp8266.h>
#include <gpio.h>
#include <pwm.h>
#include <osapi.h>
#include <ets_sys.h>

#include <user_interface.h>



// 初始化 GPIO 引脚
void hal_gpio_init(int pin, int mode) {
if(mode == 1) {
gpio_output_set(0, (1 << pin), (1 << pin), 0); //设置为输出模式
} else {
gpio_output_set((1 << pin), 0, 0, (1 << pin)); //设置为输入模式
}
}

// 写入 GPIO 电平
void hal_gpio_write(int pin, bool value) {
if (value) {
gpio_output_set((1 << pin), 0, (1 << pin), 0); //设置为高电平
} else {
gpio_output_set(0, (1 << pin), 0, 0); //设置为低电平
}
}


// 初始化 PWM
void hal_pwm_init(int pin) {
pwm_init(PWM_FREQUENCY, &pin, 1); //初始化 PWM 模块, 只有一个PWM输出
pwm_start();
}

// 设置 PWM 占空比
void hal_pwm_set_duty(int pin, int duty) {
// 占空比范围 0-1023
if (duty < 0) duty = 0;
if (duty > 1023) duty = 1023;
uint32_t pwm_duty_val[1] = {duty};
pwm_set_duty(pwm_duty_val);

}

static os_timer_t hal_timer;
static void (*hal_timer_callback)(void);

// 定时器回调函数
static void hal_timer_cb(void *arg) {
if(hal_timer_callback) {
hal_timer_callback();
}
}

// 初始化定时器
void hal_timer_init(uint32_t ms, void (*callback)(void)) {
hal_timer_callback = callback;
os_timer_disarm(&hal_timer);
os_timer_setfn(&hal_timer, (os_timer_func_t *)hal_timer_cb, NULL);
os_timer_arm(&hal_timer, ms, 1);
}

// 启动定时器
void hal_timer_start() {
os_timer_arm(&hal_timer, 0, 1);
}

// 停止定时器
void hal_timer_stop() {
os_timer_disarm(&hal_timer);
}


// 延迟函数
void hal_delay_ms(uint32_t ms) {
os_delay_us(ms * 1000);
}

4.2. wifi 模块

  • wifi_module.h:
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
#ifndef WIFI_MODULE_H
#define WIFI_MODULE_H

#include <stdbool.h>

// Wi-Fi 状态枚举
typedef enum {
WIFI_DISCONNECTED,
WIFI_CONNECTING,
WIFI_CONNECTED,
WIFI_ERROR
} wifi_state_t;

// 初始化 Wi-Fi 模块
bool wifi_module_init(const char *ssid, const char *password);

// 获取 Wi-Fi 连接状态
wifi_state_t wifi_get_state();

// 发送数据
bool wifi_send_data(const char *data, uint16_t len);

// 接收数据,返回接收到的长度,接收数据放在buffer里,buffer的长度为maxlen
int wifi_receive_data(char *buffer, uint16_t maxlen);


#endif
  • wifi_module.c:
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#include "wifi_module.h"
#include "esp8266.h"
#include <espconn.h>
#include <osapi.h>
#include <user_interface.h>
#include <mem.h>
#include <stdio.h>
#include "hal.h"
#include "system_module.h"

#define WIFI_SERVER_PORT 8080

static wifi_state_t wifi_state = WIFI_DISCONNECTED;
static struct espconn *tcp_server = NULL;
static char recv_buf[256];
static uint16_t recv_len = 0;

static void ICACHE_FLASH_ATTR wifi_connect_cb(System_Event_t *evt);

static void ICACHE_FLASH_ATTR tcp_server_recvcb(void *arg, char *pdata, unsigned short len) {
if (len > 0) {
if(len > sizeof(recv_buf)) {
len = sizeof(recv_buf);
}
memcpy(recv_buf, pdata, len);
recv_len = len;

}
}


static void ICACHE_FLASH_ATTR tcp_server_sentcb(void *arg) {
// 发送完成回调,可以添加发送日志等
}



// 创建TCP Server
static void ICACHE_FLASH_ATTR tcp_server_init() {
tcp_server = (struct espconn *)os_zalloc(sizeof(struct espconn));
if (tcp_server == NULL) {
system_log("tcp_server_init: Memory allocation failed!");
return;
}

tcp_server->type = ESPCONN_TCP;
tcp_server->state = ESPCONN_NONE;
tcp_server->proto.tcp = (esp_tcp *)os_zalloc(sizeof(esp_tcp));
if(tcp_server->proto.tcp == NULL) {
system_log("tcp_server_init: Memory allocation failed!");
os_free(tcp_server);
tcp_server = NULL;
return;
}

tcp_server->proto.tcp->local_port = WIFI_SERVER_PORT;
espconn_regist_recvcb(tcp_server, tcp_server_recvcb);
espconn_regist_sentcb(tcp_server, tcp_server_sentcb);
sint8 ret = espconn_accept(tcp_server);

if (ret != 0) {
system_log("tcp_server_init: espconn_accept failed!");
os_free(tcp_server->proto.tcp);
os_free(tcp_server);
tcp_server = NULL;
return;
}


espconn_regist_connectcb(tcp_server, wifi_connect_cb);
system_log("TCP server started on port %d.", WIFI_SERVER_PORT);


}


static void ICACHE_FLASH_ATTR wifi_connect_cb(System_Event_t *evt) {
if (evt == NULL) {
return;
}

switch (evt->event_id) {
case EVENT_STAMODE_CONNECTED:
system_log("Wi-Fi connected to AP");
wifi_state = WIFI_CONNECTED;
break;
case EVENT_STAMODE_DISCONNECTED:
system_log("Wi-Fi disconnected from AP");
wifi_state = WIFI_DISCONNECTED;
if(tcp_server != NULL) {
espconn_delete(tcp_server);
os_free(tcp_server->proto.tcp);
os_free(tcp_server);
tcp_server = NULL;
}
break;
case EVENT_STAMODE_AUTHMODE_CHANGE:
system_log("Wi-Fi authentication mode changed.");
break;
case EVENT_STAMODE_GOT_IP:
system_log("Got IP address, starting TCP server");
tcp_server_init();
break;
case EVENT_SOFTAPMODE_STACONNECTED:
system_log("Wi-Fi client connected to softAP.");
break;
case EVENT_SOFTAPMODE_STADISCONNECTED:
system_log("Wi-Fi client disconnected from softAP.");
break;
default:
break;
}
}

// 初始化 Wi-Fi 模块
bool wifi_module_init(const char *ssid, const char *password) {

wifi_state = WIFI_CONNECTING;

wifi_set_opmode(STATION_MODE);

struct station_config stationConf;
os_memset(&stationConf, 0, sizeof(struct station_config));
os_sprintf((char*)stationConf.ssid, "%s", ssid);
os_sprintf((char*)stationConf.password, "%s", password);
wifi_station_set_config(&stationConf);

wifi_set_event_handler_cb(wifi_connect_cb);
wifi_station_connect();
system_log("WiFi module initialized, connecting to %s...", ssid);
return true;
}

// 获取 Wi-Fi 连接状态
wifi_state_t wifi_get_state() {
return wifi_state;
}

// 发送数据
bool wifi_send_data(const char *data, uint16_t len) {
if (wifi_state != WIFI_CONNECTED || tcp_server == NULL || tcp_server->state != ESPCONN_CONNECT ) {
return false;
}
if(data == NULL || len == 0) {
return true;
}
sint8 ret = espconn_send(tcp_server, (uint8_t*)data, len);
return ret == ESPCONN_OK;
}


// 接收数据
int wifi_receive_data(char *buffer, uint16_t maxlen) {
if (recv_len > 0) {
uint16_t len = recv_len > maxlen ? maxlen : recv_len;
memcpy(buffer, recv_buf, len);
recv_len = 0; //数据读取完成,清空缓存
return len;
} else {
return 0;
}
}

4.3. servo_control 模块

  • servo_control.h:
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
#ifndef SERVO_CONTROL_H
#define SERVO_CONTROL_H

#include <stdint.h>
#include <stdbool.h>

// 舵机编号枚举
typedef enum {
SERVO1 = 0,
SERVO2,
SERVO3,
SERVO4,
SERVO_MAX // 表示舵机的最大数量
} servo_id_t;

// 初始化舵机控制模块
bool servo_init();

// 设置舵机角度
bool servo_set_angle(servo_id_t servo_id, uint16_t angle);

// 设置所有舵机角度
bool servo_set_angles(uint16_t angles[SERVO_MAX]);

// 获取舵机当前角度
int servo_get_angle(servo_id_t servo_id);

// 停止所有舵机运动
void servo_stop_all();

#endif
  • servo_control.c:
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
#include "servo_control.h"
#include "hal.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "system_module.h"

#define SERVO_MIN_PULSE 500 // 0度对应的 PWM 脉宽
#define SERVO_MAX_PULSE 2500 // 180度对应的 PWM 脉宽
#define SERVO_ANGLE_RANGE 180 // 舵机的角度范围

static int servo_angle[SERVO_MAX];

static int servo_pins[] = {SERVO_PIN1, SERVO_PIN2, SERVO_PIN3, SERVO_PIN4};

// 将角度转换为 PWM 占空比
static int angle_to_duty(int angle) {
if (angle < 0) angle = 0;
if (angle > SERVO_ANGLE_RANGE) angle = SERVO_ANGLE_RANGE;

int pulse_width = SERVO_MIN_PULSE + (angle * (SERVO_MAX_PULSE - SERVO_MIN_PULSE)) / SERVO_ANGLE_RANGE;
return pulse_width; // 返回占空比,需要根据实际情况调整,此处的计算不准确
}

// 初始化舵机控制模块
bool servo_init() {
for(int i=0; i < SERVO_MAX; i++) {
hal_pwm_init(servo_pins[i]);
servo_angle[i] = 0; //初始角度设置为0度
}
system_log("Servo module initialized.");
return true;
}


// 设置舵机角度
bool servo_set_angle(servo_id_t servo_id, uint16_t angle) {
if (servo_id >= SERVO_MAX) {
system_log("Invalid servo ID: %d.", servo_id);
return false;
}
if (angle < 0 || angle > SERVO_ANGLE_RANGE) {
system_log("Invalid servo angle: %d.", angle);
return false;
}

int duty = angle_to_duty(angle);
hal_pwm_set_duty(servo_pins[servo_id], duty);
servo_angle[servo_id] = angle;
return true;
}



// 设置所有舵机角度
bool servo_set_angles(uint16_t angles[SERVO_MAX]) {
bool result = true;
for (int i = 0; i < SERVO_MAX; i++) {
result &= servo_set_angle(i, angles[i]);
}
return result;
}



// 获取舵机当前角度
int servo_get_angle(servo_id_t servo_id) {
if (servo_id >= SERVO_MAX) {
system_log("Invalid servo ID: %d.", servo_id);
return -1;
}
return servo_angle[servo_id];
}

// 停止所有舵机运动
void servo_stop_all() {
// 这里没有停止PWM输出的功能,如果舵机有停止功能,可以添加相关代码
}

4.4. motion_control 模块

  • motion_control.h:
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
#ifndef MOTION_CONTROL_H
#define MOTION_CONTROL_H

#include <stdbool.h>
#include "servo_control.h"

// 定义运动模式
typedef enum {
MOTION_FORWARD,
MOTION_BACKWARD,
MOTION_TURN_LEFT,
MOTION_TURN_RIGHT,
MOTION_STOP,
MOTION_CUSTOM
} motion_mode_t;

// 初始化运动控制模块
bool motion_init();

// 执行指定运动模式
bool motion_execute(motion_mode_t mode, int speed);

// 设置自定义运动姿态
bool motion_set_custom(uint16_t angles[SERVO_MAX]);

#endif
  • motion_control.c:
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
#include "motion_control.h"
#include "servo_control.h"
#include "hal.h"
#include "system_module.h"

#define DEFAULT_SPEED 100 // 默认速度,可根据实际情况调整
#define STEP_DELAY_MS 50 // 每一步的延迟时间,可根据实际情况调整

// 初始化运动控制模块
bool motion_init() {
if(!servo_init()) {
system_log("motion_init: Servo initialization failed.");
return false;
}
system_log("Motion control module initialized.");
return true;
}

// 执行指定运动模式
bool motion_execute(motion_mode_t mode, int speed) {
int delay = STEP_DELAY_MS;
if (speed < 0) speed = 0;
if (speed > 100) speed = 100;
delay = STEP_DELAY_MS * (100 - speed + 1) / 100 ;// 根据速度计算延迟时间

uint16_t angles[SERVO_MAX] = {0};
switch (mode) {
case MOTION_FORWARD:
// 前进
angles[SERVO1] = 90; // 舵机1, 前进
angles[SERVO2] = 90; // 舵机2, 前进
angles[SERVO3] = 90; // 舵机3, 前进
angles[SERVO4] = 90; // 舵机4, 前进
servo_set_angles(angles);
hal_delay_ms(delay);

angles[SERVO1] = 80; // 舵机1, 前进
angles[SERVO2] = 100; // 舵机2, 前进
angles[SERVO3] = 100; // 舵机3, 前进
angles[SERVO4] = 80; // 舵机4, 前进
servo_set_angles(angles);
hal_delay_ms(delay);

angles[SERVO1] = 100; // 舵机1, 前进
angles[SERVO2] = 80; // 舵机2, 前进
angles[SERVO3] = 80; // 舵机3, 前进
angles[SERVO4] = 100; // 舵机4, 前进
servo_set_angles(angles);
hal_delay_ms(delay);

break;
case MOTION_BACKWARD:
// 后退
angles[SERVO1] = 90; // 舵机1, 后退
angles[SERVO2] = 90; // 舵机2, 后退
angles[SERVO3] = 90; // 舵机3, 后退
angles[SERVO4] = 90; // 舵机4, 后退
servo_set_angles(angles);
hal_delay_ms(delay);


angles[SERVO1] = 100; // 舵机1, 后退
angles[SERVO2] = 80; // 舵机2, 后退
angles[SERVO3] = 80; // 舵机3, 后退
angles[SERVO4] = 100; // 舵机4, 后退
servo_set_angles(angles);
hal_delay_ms(delay);

angles[SERVO1] = 80; // 舵机1, 后退
angles[SERVO2] = 100; // 舵机2, 后退
angles[SERVO3] = 100; // 舵机3, 后退
angles[SERVO4] = 80; // 舵机4, 后退
servo_set_angles(angles);
hal_delay_ms(delay);
break;
case MOTION_TURN_LEFT:
// 左转
angles[SERVO1] = 0; // 舵机1, 左转
angles[SERVO2] = 180; // 舵机2, 左转
angles[SERVO3] = 0; // 舵机3, 左转
angles[SERVO4] = 180; // 舵机4, 左转
servo_set_angles(angles);
hal_delay_ms(delay);
break;
case MOTION_TURN_RIGHT:
// 右转
angles[SERVO1] = 180; // 舵机1, 右转
angles[SERVO2] = 0; // 舵机2, 右转
angles[SERVO3] = 180; // 舵机3, 右转
angles[SERVO4] = 0; // 舵机4, 右转
servo_set_angles(angles);
hal_delay_ms(delay);
break;
case MOTION_STOP:
// 停止
angles[SERVO1] = 90;
angles[SERVO2] = 90;
angles[SERVO3] = 90;
angles[SERVO4] = 90;
servo_set_angles(angles);
break;
case MOTION_CUSTOM:
// 自定义运动已经在motion_set_custom函数实现
break;
default:
system_log("Invalid motion mode: %d.", mode);
return false;
}

return true;
}

// 设置自定义运动姿态
bool motion_set_custom(uint16_t angles[SERVO_MAX]) {
return servo_set_angles(angles);
}

4.5. protocol_parser 模块

  • protocol_parser.h:
1
2
3
4
5
6
7
8
9
10
#ifndef PROTOCOL_PARSER_H
#define PROTOCOL_PARSER_H

#include <stdbool.h>
#include "motion_control.h"

// 解析控制指令
bool protocol_parse_command(const char *command, uint16_t len);

#endif
  • protocol_parser.c:
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
#include "protocol_parser.h"
#include "motion_control.h"
#include <string.h>
#include <stdio.h>
#include "system_module.h"
#include <stdlib.h>

// 解析控制指令
bool protocol_parse_command(const char *command, uint16_t len) {
if (command == NULL || len == 0) {
return false;
}

if (strncmp(command, "FORWARD", len) == 0) {
motion_execute(MOTION_FORWARD, 100);
system_log("Received command: FORWARD");
} else if (strncmp(command, "BACKWARD", len) == 0) {
motion_execute(MOTION_BACKWARD, 100);
system_log("Received command: BACKWARD");
} else if (strncmp(command, "LEFT", len) == 0) {
motion_execute(MOTION_TURN_LEFT, 100);
system_log("Received command: LEFT");
} else if (strncmp(command, "RIGHT", len) == 0) {
motion_execute(MOTION_TURN_RIGHT, 100);
system_log("Received command: RIGHT");
} else if (strncmp(command, "STOP", len) == 0) {
motion_execute(MOTION_STOP, 0);
system_log("Received command: STOP");
} else if (strncmp(command, "CUSTOM", 6) == 0) {
//自定义指令格式 CUSTOM:angle1,angle2,angle3,angle4
char* token;
char * cmd_str = strdup(command); // 复制字符串,因为strtok会修改原字符串
token = strtok(cmd_str, ":");
token = strtok(NULL, ",");
if(token == NULL) {
free(cmd_str);
system_log("CUSTOM command format error.");
return false;
}
int angle[SERVO_MAX] = {0};
for(int i=0; i < SERVO_MAX; i++) {
angle[i] = atoi(token); // 提取角度
token = strtok(NULL, ",");
if(token == NULL && i != SERVO_MAX - 1) {
free(cmd_str);
system_log("CUSTOM command format error.");
return false; // 数据不完整
}
}
motion_set_custom(angle);
free(cmd_str);
system_log("Received command: CUSTOM: %d,%d,%d,%d", angle[0], angle[1], angle[2], angle[3]);
} else {
system_log("Unknown command received: %s.", command);
return false;
}
return true;
}

4.6. application 模块

  • application.h:
1
2
3
4
5
6
7
8
9
10
11
12
#ifndef APPLICATION_H
#define APPLICATION_H

#include <stdbool.h>

// 初始化应用程序
bool application_init();

// 执行应用程序主循环
void application_run();

#endif
  • application.c:
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
#include "application.h"
#include "wifi_module.h"
#include "motion_control.h"
#include "protocol_parser.h"
#include "hal.h"
#include "system_module.h"
#include "user_config.h"
#include <string.h>
#include <osapi.h>

#define RECV_BUF_SIZE 256 // 接收缓存大小


static void system_timer_callback(void);
static char recv_buffer[RECV_BUF_SIZE];

// 初始化应用程序
bool application_init() {

system_init(); // 初始化系统模块
hal_delay_ms(1000); // 稍微延迟一下
if (!wifi_module_init(USER_WIFI_SSID, USER_WIFI_PASSWORD)) {
system_log("Application init failed: WiFi initialization error.");
return false;
}

if(!motion_init()){
system_log("Application init failed: Motion initialization error.");
return false;
}
system_log("Application initialized.");
hal_timer_init(100, system_timer_callback); // 初始化定时器,100ms执行一次回调
hal_timer_start(); // 启动定时器
return true;
}

//定时器回调
static void system_timer_callback(void){
// 定时执行的任务
if (wifi_get_state() == WIFI_CONNECTED) {
int len = wifi_receive_data(recv_buffer, RECV_BUF_SIZE);
if (len > 0) {
protocol_parse_command(recv_buffer, len);
}

} else if(wifi_get_state() == WIFI_DISCONNECTED) {
wifi_module_init(USER_WIFI_SSID, USER_WIFI_PASSWORD); // wifi断开后重新连接
}
}

// 执行应用程序主循环
void application_run() {
// 主循环,这里通常为空,大部分工作都在定时器回调里执行
while(1) {
os_delay_us(1000);
}
}

4.7. system 模块

  • system_module.h:
1
2
3
4
5
6
7
8
9
10
11
12
#ifndef SYSTEM_MODULE_H
#define SYSTEM_MODULE_H

#include <stdio.h>

// 初始化系统模块
void system_init();

// 打印日志
void system_log(const char *format, ...);

#endif
  • system_module.c:
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
#include "system_module.h"
#include <stdio.h>
#include <stdarg.h>
#include <time.h>
#include "user_config.h"

void system_init() {
uart_div_modify(0, UART_CLK_FREQ / 115200); // 初始化串口

system_log("System module initialized.");
}

void system_log(const char *format, ...) {
if (USER_LOG_ENABLE) {
char buffer[256];
va_list args;
va_start(args, format);
vsnprintf(buffer, sizeof(buffer), format, args);
va_end(args);

printf("[%ld] %s\r\n", system_get_time(), buffer);
//os_printf("[%d] %s\r\n", (int)system_get_time(), buffer);
}
}

4.8. plugin 模块

  • plugin.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#ifndef PLUGIN_H
#define PLUGIN_H

#include <stdint.h>
#include <stdbool.h>

// 插件类型枚举
typedef enum {
PLUGIN_LED,
PLUGIN_SENSOR,
PLUGIN_MAX // 表示插件的最大数量
} plugin_type_t;

// 初始化插件
bool plugin_init(plugin_type_t plugin_type);
// 插件控制功能
bool plugin_control(plugin_type_t plugin_type, int data);

#endif
  • plugin.c
#include "plugin.h"
#include "hal.h"
#include "system_module.h"
#include <stdint.h>
#include <stdbool.h>


#define PLUGIN_LED_PIN 2 //LED灯的引脚
#define PLUGIN_SENSOR_PIN 4 //模拟传感器的引脚


// 初始化插件
bool plugin_init(plugin_type_t plugin_type) {
     if(plugin_type >= PLUGIN_MAX) {
          system_log("plugin_init: Invalid plugin type %d.", plugin_type);
          return false;
     }

     switch (plugin_type) {
        case PLUGIN_LED:
             hal_gpio_init(PLUGIN_LED_PIN, 1); //设置为输出模式
             hal_gpio_write(PLUGIN_LED_PIN, 0); // 初始状态设置为关闭
            system_log("Plugin LED initialized.");
            break;
         case PLUGIN_SENSOR:
           hal_gpio_init(PLUGIN_SENSOR_PIN, 0); //设置为输入模式
            system_log("Plugin Sensor initialized.");

欢迎关注我的其它发布渠道