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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
|
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_log.h"
#include "driver/mcpwm_prelude.h"
#include "driver/gpio.h"
static const char *TAG = "dual_servo_433";
// GPIO配置
#define SERVO1_GPIO 12 // 舵机1 PWM信号GPIO
#define SERVO2_GPIO 13 // 舵机2 PWM信号GPIO
#define RF433_GPIO 14 // 433MHz接收器GPIO
// 舵机参数
#define SERVO_MIN_PULSEWIDTH_US 500
#define SERVO_MAX_PULSEWIDTH_US 2500
#define SERVO_MIN_DEGREE -90
#define SERVO_MAX_DEGREE 90
#define SERVO_TIMEBASE_RESOLUTION_HZ 1000000
#define SERVO_TIMEBASE_PERIOD 20000
// 舵机角度
#define SERVO_CLOSE_ANGLE -5 // 关闭角度
#define SERVO_OPEN_ANGLE 150 // 开启角度
// 控制命令
typedef struct {
int state; // 0=关闭, 1=开启
} servo_command_t;
// 全局变量
static mcpwm_cmpr_handle_t comparator1 = NULL;
static mcpwm_cmpr_handle_t comparator2 = NULL;
static QueueHandle_t servo_queue;
static int servo_state = 0;
static int last_rf433_state = 0;
// 角度转PWM值
static inline uint32_t angle_to_compare(int angle)
{
if (angle < SERVO_MIN_DEGREE) angle = SERVO_MIN_DEGREE;
if (angle > SERVO_MAX_DEGREE) angle = SERVO_MAX_DEGREE;
return (angle - SERVO_MIN_DEGREE) * (SERVO_MAX_PULSEWIDTH_US - SERVO_MIN_PULSEWIDTH_US) /
(SERVO_MAX_DEGREE - SERVO_MIN_DEGREE) + SERVO_MIN_PULSEWIDTH_US;
}
// 舵机控制任务
static void servo_control_task(void *arg)
{
servo_command_t cmd;
while (1) {
if (xQueueReceive(servo_queue, &cmd, portMAX_DELAY)) {
servo_state = cmd.state;
int target_angle = cmd.state ? SERVO_OPEN_ANGLE : SERVO_CLOSE_ANGLE;
uint32_t compare_value = angle_to_compare(target_angle);
// 设置两个舵机
mcpwm_comparator_set_compare_value(comparator1, compare_value);
mcpwm_comparator_set_compare_value(comparator2, compare_value);
ESP_LOGI(TAG, "Servos: %s (%d°)", cmd.state ? "OPEN" : "CLOSE", target_angle);
vTaskDelay(pdMS_TO_TICKS(500));
}
}
}
// 433MHz检测任务
static void rf433_task(void *arg)
{
servo_command_t cmd;
while (1) {
int current_rf433_state = gpio_get_level(RF433_GPIO);
if (last_rf433_state != current_rf433_state) {
vTaskDelay(pdMS_TO_TICKS(50)); // 防抖
if (gpio_get_level(RF433_GPIO) == current_rf433_state) {
int new_state = current_rf433_state ? 1 : 0;
if (new_state != servo_state) {
cmd.state = new_state;
xQueueSend(servo_queue, &cmd, pdMS_TO_TICKS(100));
}
}
}
last_rf433_state = current_rf433_state;
vTaskDelay(pdMS_TO_TICKS(20));
}
}
// 初始化单个舵机
static esp_err_t init_servo(int gpio_num, mcpwm_cmpr_handle_t *comparator, int group_id)
{
// 创建定时器
mcpwm_timer_handle_t timer = NULL;
mcpwm_timer_config_t timer_config = {
.group_id = group_id,
.clk_src = MCPWM_TIMER_CLK_SRC_DEFAULT,
.resolution_hz = SERVO_TIMEBASE_RESOLUTION_HZ,
.period_ticks = SERVO_TIMEBASE_PERIOD,
.count_mode = MCPWM_TIMER_COUNT_MODE_UP,
};
ESP_ERROR_CHECK(mcpwm_new_timer(&timer_config, &timer));
// 创建操作符
mcpwm_oper_handle_t oper = NULL;
mcpwm_operator_config_t operator_config = {
.group_id = group_id,
};
ESP_ERROR_CHECK(mcpwm_new_operator(&operator_config, &oper));
ESP_ERROR_CHECK(mcpwm_operator_connect_timer(oper, timer));
// 创建比较器
mcpwm_comparator_config_t comparator_config = {
.flags.update_cmp_on_tez = true,
};
ESP_ERROR_CHECK(mcpwm_new_comparator(oper, &comparator_config, comparator));
// 创建发生器
mcpwm_gen_handle_t generator = NULL;
mcpwm_generator_config_t generator_config = {
.gen_gpio_num = gpio_num,
};
ESP_ERROR_CHECK(mcpwm_new_generator(oper, &generator_config, &generator));
// 配置PWM
ESP_ERROR_CHECK(mcpwm_generator_set_action_on_timer_event(generator,
MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH)));
ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(generator,
MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, *comparator, MCPWM_GEN_ACTION_LOW)));
// 启动定时器
ESP_ERROR_CHECK(mcpwm_timer_enable(timer));
ESP_ERROR_CHECK(mcpwm_timer_start_stop(timer, MCPWM_TIMER_START_NO_STOP));
return ESP_OK;
}
// 初始化433MHz GPIO
static void init_rf433_gpio(void)
{
gpio_config_t io_conf = {
.intr_type = GPIO_INTR_DISABLE,
.mode = GPIO_MODE_INPUT,
.pin_bit_mask = (1ULL << RF433_GPIO),
.pull_down_en = GPIO_PULLDOWN_ENABLE,
.pull_up_en = GPIO_PULLUP_DISABLE,
};
ESP_ERROR_CHECK(gpio_config(&io_conf));
}
void app_main(void)
{
ESP_LOGI(TAG, "Starting Dual Servo 433MHz Control");
// 创建队列
servo_queue = xQueueCreate(10, sizeof(servo_command_t));
// 初始化GPIO
init_rf433_gpio();
// 初始化舵机
init_servo(SERVO1_GPIO, &comparator1, 0);
init_servo(SERVO2_GPIO, &comparator2, 1);
// 设置初始位置为关闭
uint32_t close_value = angle_to_compare(SERVO_CLOSE_ANGLE);
mcpwm_comparator_set_compare_value(comparator1, close_value);
mcpwm_comparator_set_compare_value(comparator2, close_value);
// 创建任务
xTaskCreate(servo_control_task, "servo_control", 4096, NULL, 5, NULL);
xTaskCreate(rf433_task, "rf433_task", 2048, NULL, 7, NULL);
ESP_LOGI(TAG, "System initialized - 433MHz HIGH=OPEN, LOW=CLOSE");
// 主循环
while (1) {
vTaskDelay(pdMS_TO_TICKS(10000));
}
}
|