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

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

+3
View File
@@ -0,0 +1,3 @@
idf_component_register(SRCS "servo.c"
INCLUDE_DIRS "."
REQUIRES esp_driver_ledc esp_driver_gpio driver)
+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);
}
+49
View File
@@ -0,0 +1,49 @@
/**
* @file servo.h
* @brief 180° PWM 舵机控制 (LEDC)
*/
#ifndef SERVO_H
#define SERVO_H
#include <stdbool.h>
#include "driver/gpio.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief 初始化舵机 (50Hz PWM)
* @param gpio PWM 输出引脚
*/
void servo_init(int gpio);
/**
* @brief 设置舵机角度
* @param angle 角度 0.0 ~ 180.0
*/
void servo_set_angle(float angle);
/**
* @brief 设置舵机到上限位 (默认 180°)
*/
void servo_set_up(void);
/**
* @brief 设置舵机到下限位 (默认 0°)
*/
void servo_set_down(void);
/**
* @brief 自定义上下限位角度
* @param up 上限位角度 (默认 180°)
* @param down 下限位角度 (默认 0°)
*/
void servo_set_limits(float up, float down);
#ifdef __cplusplus
}
#endif
#endif /* SERVO_H */