掌握LEDC模块实现呼吸灯效果,学习驱动舵机和直流电机的基本方法
本节课将介绍ESP32的PWM(脉冲宽度调制)功能及其在电机控制中的应用。我们将学习如何使用LEDC模块实现呼吸灯效果,并掌握驱动SG90舵机和直流电机的基本方法。
脉冲宽度调制(PWM)是一种通过快速开关数字信号来模拟模拟信号的技术。通过改变占空比(高电平时间与周期时间的比例),我们可以控制设备的平均功率。
ESP32有一个专用的LED PWM控制器(LEDC),专门设计用于驱动LED,但也可用于其他PWM应用。主要特点包括:
#include <driver/ledc.h>
#define LED_PIN 2 // 使用GPIO2(ESP32开发板上的内置LED)
void setup() {
// 1. 配置定时器
ledc_timer_config_t timer_conf = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.duty_resolution = LEDC_TIMER_13_BIT, // 13位分辨率
.timer_num = LEDC_TIMER_0,
.freq_hz = 5000, // 5kHz频率
.clk_cfg = LEDC_AUTO_CLK
};
ledc_timer_config(&timer_conf);
// 2. 配置通道
ledc_channel_config_t channel_conf = {
.gpio_num = LED_PIN,
.speed_mode = LEDC_LOW_SPEED_MODE,
.channel = LEDC_CHANNEL_0,
.timer_sel = LEDC_TIMER_0,
.duty = 0, // 初始占空比为0
.hpoint = 0
};
ledc_channel_config(&channel_conf);
}
void loop() {
// 呼吸灯效果 - 渐亮
for (int duty = 0; duty < 8191; duty += 100) { // 8191是13位最大值
ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, duty);
ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0);
delay(10);
}
// 呼吸灯效果 - 渐暗
for (int duty = 8191; duty > 0; duty -= 100) {
ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, duty);
ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0);
delay(10);
}
}
注意: ESP32的LEDC模块提供了专门的渐变函数 ledc_fade_func_install() 和 ledc_set_fade_with_time() 可以更高效地实现呼吸灯效果。
工作电压:4.8V-6V
扭矩:1.8kg·cm (4.8V)
转动角度:约180度
控制信号:50Hz PWM (周期20ms)
脉冲宽度:0.5ms-2.5ms对应0-180度
舵机通过PWM信号的脉冲宽度来确定转动角度。对于SG90舵机:
#include <driver/ledc.h>
#define SERVO_PIN 13 // 舵机信号线连接的GPIO
void setup() {
// 配置50Hz PWM (舵机标准频率)
ledc_timer_config_t timer_conf = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.duty_resolution = LEDC_TIMER_13_BIT,
.timer_num = LEDC_TIMER_0,
.freq_hz = 50,
.clk_cfg = LEDC_AUTO_CLK
};
ledc_timer_config(&timer_conf);
ledc_channel_config_t channel_conf = {
.gpio_num = SERVO_PIN,
.speed_mode = LEDC_LOW_SPEED_MODE,
.channel = LEDC_CHANNEL_0,
.timer_sel = LEDC_TIMER_0,
.duty = 0,
.hpoint = 0
};
ledc_channel_config(&channel_conf);
}
// 设置舵机角度 (0-180度)
void setServoAngle(int angle) {
// 将角度转换为占空比
// 0.5ms (0度) = 0.5/20 * 8191 = 205
// 2.5ms (180度) = 2.5/20 * 8191 = 1024
int duty = map(angle, 0, 180, 205, 1024);
ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, duty);
ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0);
}
void loop() {
// 舵机从0度转到180度
for (int angle = 0; angle <= 180; angle += 10) {
setServoAngle(angle);
delay(200);
}
// 舵机从180度转回0度
for (int angle = 180; angle >= 0; angle -= 10) {
setServoAngle(angle);
delay(200);
}
}
警告: 舵机工作时需要较大电流,建议使用外部电源供电,不要直接从ESP32的3.3V引脚取电。
工作电压:3-12V(视型号而定)
控制方式:PWM调速 + 方向控制
需要驱动电路:H桥电机驱动模块(如L298N)
直流电机控制需要两个要素:
驱动电压:5-35V
最大电流:2A(每通道)
可驱动2个直流电机或1个步进电机
需要3个控制信号:ENA(使能)、IN1、IN2
#define ENA 14 // PWM使能引脚
#define IN1 12 // 方向控制1
#define IN2 13 // 方向控制2
void setup() {
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
// 配置PWM
ledcSetup(0, 5000, 8); // 通道0, 5kHz, 8位分辨率
ledcAttachPin(ENA, 0);
}
// 设置电机速度和方向
void setMotor(int speed, bool direction) {
// 方向控制
digitalWrite(IN1, direction);
digitalWrite(IN2, !direction);
// 速度控制 (0-255)
ledcWrite(0, abs(speed));
}
void loop() {
// 正转加速
for (int speed = 0; speed <= 255; speed += 10) {
setMotor(speed, true);
delay(100);
}
delay(1000);
// 反转加速
for (int speed = 0; speed <= 255; speed += 10) {
setMotor(speed, false);
delay(100);
}
delay(1000);
}
提示: 对于更简单的应用,可以使用TB6612FNG等更现代的电机驱动芯片,它体积更小、效率更高、发热更低。
扫描获取课程所需元件
