磁铁、舵机、网页控制、通信协议

This commit is contained in:
kirl committed 2026-07-29 21:11:16 +08:00
1 parent 230ad1254a
commit 40ee976236
17 files changed
+1879 -32

No files matched your search

+89
View File
@@ -0,0 +1,89 @@
/**
* @file servo.c
* @brief 180° PWM 舵机控制实现 (LEDC, 50Hz, 0.5~2.5ms)
*/
#include "servo.h"
#include "driver/ledc.h"
#include "esp_log.h"
#define SERVO_FREQ_HZ 50
#define SERVO_TIMER LEDC_TIMER_0
#define SERVO_MODE LEDC_LOW_SPEED_MODE
#define SERVO_DUTY_RES LEDC_TIMER_16_BIT /* 0~65535 */
#define SERVO_MAX_DUTY 65535
/* 脉宽范围 (微秒) */
#define PULSE_MIN_US 500
#define PULSE_MAX_US 2500
#define PERIOD_US 20000 /* 50Hz = 20ms */
static const char *TAG = "SERVO";
static ledc_channel_t s_channel;
static float s_limit_up = 180.0f;
static float s_limit_down = 0.0f;
/* 角度 → 占空比 */
static uint32_t angle_to_duty(float angle)
{
if (angle < 0.0f) angle = 0.0f;
if (angle > 180.0f) angle = 180.0f;
float pulse_us = PULSE_MIN_US + (angle / 180.0f) * (PULSE_MAX_US - PULSE_MIN_US);
return (uint32_t)((pulse_us / PERIOD_US) * SERVO_MAX_DUTY);
}
void servo_init(int gpio)
{
/* 分配 LEDC 通道 */
static int chan_idx = 0;
s_channel = (chan_idx++ == 0) ? LEDC_CHANNEL_0 : LEDC_CHANNEL_1;
ledc_timer_config_t timer_cfg = {
.speed_mode = SERVO_MODE,
.duty_resolution = SERVO_DUTY_RES,
.timer_num = SERVO_TIMER,
.freq_hz = SERVO_FREQ_HZ,
.clk_cfg = LEDC_AUTO_CLK,
};
ESP_ERROR_CHECK(ledc_timer_config(&timer_cfg));
ledc_channel_config_t chan_cfg = {
.gpio_num = gpio,
.speed_mode = SERVO_MODE,
.channel = s_channel,
.intr_type = LEDC_INTR_DISABLE,
.timer_sel = SERVO_TIMER,
.duty = angle_to_duty(0), /* 初始: 0° */
.hpoint = 0,
.flags.output_invert = 0,
};
ESP_ERROR_CHECK(ledc_channel_config(&chan_cfg));
ESP_LOGI(TAG, "初始化完成 (GPIO%d, 50Hz, 通道%d)", gpio, s_channel);
}
void servo_set_angle(float angle)
{
uint32_t duty = angle_to_duty(angle);
ESP_ERROR_CHECK(ledc_set_duty(SERVO_MODE, s_channel, duty));
ESP_ERROR_CHECK(ledc_update_duty(SERVO_MODE, s_channel));
ESP_LOGD(TAG, "角度: %.1f° (duty=%lu)", angle, duty);
}
void servo_set_up(void)
{
servo_set_angle(s_limit_up);
}
void servo_set_down(void)
{
servo_set_angle(s_limit_down);
}
void servo_set_limits(float up, float down)
{
s_limit_up = up;
s_limit_down = down;
ESP_LOGI(TAG, "限位: 上=%.0f° 下=%.0f°", up, down);
}