在 ESP32S3 开发板中,MCPWM 定时器 和LEDC 定时器的数量及配置如下:
1. MCPWM 定时器数量
ESP32S3 集成了 2 个 MCPWM 单元 ,每个单元包含 3 个独立定时器 ,因此总共有 6 个 MCPWM 定时器。
- 每个定时器可独立配置频率、计数模式(向上 / 向下计数)等参数。
- 每个定时器可驱动 2 个 PWM 输出通道(如
MCPWM0A和MCPWM0B),因此 2 个 MCPWM 单元共支持 6 个定时器 × 2 通道 = 12 路 PWM 输出。
用途:主要用于需要复杂控制的场景(如电机正反转、舵机角度控制等)。
2. LEDC 定时器数量
ESP32S3 集成了 2 个 LEDC 定时器组 (低速组和高速组),每组包含 8 个定时器 ,因此总共有 16 个 LEDC 定时器。
- 定时器分为 低速模式(LEDC_LOW_SPEED_MODE) 和 高速模式(LEDC_HIGH_SPEED_MODE),低速模式通常用于 GPIO 矩阵引脚,高速模式用于专用外设引脚。
- 每个定时器可绑定多个 LEDC 通道(最多 8 个通道共享 1 个定时器),因此 16 个定时器可支持 16 通道 PWM 输出(每个通道独立控制占空比,但共享定时器的频率)。
用途:适合简单 PWM 场景(如 LED 调光、背光调节等)。
总结
| 外设 | 定时器数量 | 通道数量(最大) | 典型用途 |
|---|---|---|---|
| MCPWM | 6 个 | 12 路 | 舵机、直流电机控制 |
| LEDC | 16 个 | 16 路 | LED 调光、简单 PWM 输出 |
实际使用时,需根据引脚功能(专用引脚 / 矩阵引脚)和场景需求选择定时器和通道,避免与其他外设(如摄像头、显示屏)的引脚冲突。
在 ESP32S3 上控制舵机的常见做法是使用 MCPWM 外设(因舵机需要稳定的 50Hz PWM 信号),以下是参考网上开源实现的舵机控制代码,可集成到你的项目中:
1. 舵机控制类(servo_controller.h)
#ifndef __SERVO_CONTROLLER_H__
#define __SERVO_CONTROLLER_H__
#include "driver/mcpwm.h"
#include "esp_err.h"
class ServoController {
private:
mcpwm_unit_t mcpwm_unit_; // MCPWM 单元(0 或 1)
mcpwm_timer_t timer_num_; // 定时器编号(0-2)
mcpwm_io_signals_t io_signal_; // 信号输出通道(如 MCPWM0A、MCPWM0B 等)
gpio_num_t gpio_num_; // 控制引脚
uint32_t min_pulse_width_; // 最小脉冲宽度(对应 0°,单位:us)
uint32_t max_pulse_width_; // 最大脉冲宽度(对应 180°,单位:us)
uint32_t freq_hz_; // PWM 频率(通常 50Hz)
public:
/**
* 构造函数:初始化舵机参数
* @param unit MCPWM 单元(MCPWM_UNIT_0 或 MCPWM_UNIT_1)
* @param timer 定时器编号(MCPWM_TIMER_0 等)
* @param signal 输出通道(MCPWM0A 等)
* @param gpio 控制引脚(需未被占用)
* @param min_us 最小脉冲宽度(默认 500us,对应 0°)
* @param max_us 最大脉冲宽度(默认 2500us,对应 180°)
* @param freq 频率(默认 50Hz)
*/
ServoController(
mcpwm_unit_t unit,
mcpwm_timer_t timer,
mcpwm_io_signals_t signal,
gpio_num_t gpio,
uint32_t min_us = 500,
uint32_t max_us = 2500,
uint32_t freq = 50
) : mcpwm_unit_(unit),
timer_num_(timer),
io_signal_(signal),
gpio_num_(gpio),
min_pulse_width_(min_us),
max_pulse_width_(max_us),
freq_hz_(freq) {}
/**
* 初始化 MCPWM 外设和引脚
*/
esp_err_t Init() {
// 1. 配置 MCPWM 定时器
mcpwm_config_t pwm_config = {
.frequency = freq_hz_, // 舵机标准频率 50Hz
.cmpr_a = 0, // 初始占空比(通道 A)
.counter_mode = MCPWM_UP_COUNTER, // 向上计数模式
.duty_mode = MCPWM_DUTY_MODE_0, // 占空比模式
};
ESP_ERROR_CHECK(mcpwm_init(mcpwm_unit_, timer_num_, &pwm_config));
// 2. 绑定引脚到 MCPWM 信号
ESP_ERROR_CHECK(mcpwm_gpio_init(mcpwm_unit_, io_signal_, gpio_num_));
// 3. 初始化为 0°
return SetAngle(0);
}
/**
* 设置舵机角度
* @param angle 角度(0-180°)
*/
esp_err_t SetAngle(uint8_t angle) {
if (angle > 180) return ESP_ERR_INVALID_ARG;
// 计算脉冲宽度:从角度映射到 [min_us, max_us]
uint32_t pulse_width = min_pulse_width_ +
(max_pulse_width_ - min_pulse_width_) * angle / 180;
// 计算占空比(占空比 = 脉冲宽度(us) / 周期(us) * 100)
// 周期(us) = 1e6 / 频率(Hz)(50Hz 时周期为 20000us)
float duty_cycle = (float)pulse_width * 100 / (1000000.0f / freq_hz_);
// 设置占空比
mcpwm_set_duty(mcpwm_unit_, timer_num_, io_signal_, duty_cycle);
mcpwm_set_duty_type(mcpwm_unit_, timer_num_, io_signal_, MCPWM_DUTY_MODE_0);
return ESP_OK;
}
};
#endif // __SERVO_CONTROLLER_H__
2. 使用示例(集成到项目中)
在 InitializeIot() 或其他初始化函数中添加舵机控制:
#include "servo_controller.h"
// 在 config.h 中添加舵机引脚定义(选择未被占用的引脚,如 GPIO_NUM_2)
#define SERVO_GPIO GPIO_NUM_2
// 初始化舵机
void InitializeServo() {
// 实例化舵机控制器(使用 MCPWM 单元 0、定时器 0、通道 A,引脚 GPIO2)
static ServoController servo(
MCPWM_UNIT_0,
MCPWM_TIMER_0,
MCPWM0A,
SERVO_GPIO
);
// 初始化舵机(默认 0°)
if (servo.Init() != ESP_OK) {
ESP_LOGE(TAG, "Servo initialization failed");
}
// 示例:通过 MCP 协议暴露舵机控制接口
auto& mcp_server = McpServer::GetInstance();
mcp_server.AddTool("self.servo.set_angle",
"Set the angle of the servo motor (0-180 degrees)",
PropertyList({
Property("angle", kPropertyTypeInteger, 0, 180) // 角度参数(0-180)
}),
[&servo](const PropertyList& properties) -> ReturnValue {
uint8_t angle = properties["angle"].value<int>();
esp_err_t ret = servo.SetAngle(angle);
return ret == ESP_OK ? true : false;
}
);
}
3. 关键说明
- 引脚选择 :需在
config.h中定义SERVO_GPIO,且该引脚未被摄像头、LCD 等其他外设占用(参考项目中已用引脚,避免冲突)。 - 脉冲参数 :不同舵机的
min_pulse_width_和max_pulse_width_可能不同(通常 500-2500us),需根据舵机 datasheet 调整。 - MCP 集成 :通过
AddTool注册self.servo.set_angle命令后,即可通过 MCP 协议发送指令控制舵机角度(如self.servo.set_angle(90)控制到 90°)。
4. 硬件连接
舵机通常有 3 根线:
- 棕色 / 黑色:GND(接 ESP32S3 的 GND)
- 红色:电源(通常 5V,不可直接接 ESP32S3 的 3.3V,需外接电源)
- 橙色 / 黄色:信号线(接定义的
SERVO_GPIO,如 GPIO2)
通过以上代码,即可在你的项目中实现舵机控制,并通过小智 AI 的 MCP 协议远程调节角度。