第8课

ESP32 PWM与电机控制

掌握LEDC模块实现呼吸灯效果,学习驱动舵机和直流电机的基本方法

课程概述

本节课将介绍ESP32的PWM(脉冲宽度调制)功能及其在电机控制中的应用。我们将学习如何使用LEDC模块实现呼吸灯效果,并掌握驱动SG90舵机和直流电机的基本方法。

1. LEDC模块实现呼吸灯

PWM简介

脉冲宽度调制(PWM)是一种通过快速开关数字信号来模拟模拟信号的技术。通过改变占空比(高电平时间与周期时间的比例),我们可以控制设备的平均功率。

ESP32的LEDC模块

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() 可以更高效地实现呼吸灯效果。

2. 驱动舵机(SG90)

SG90舵机
SG90微型舵机

工作电压:4.8V-6V

扭矩:1.8kg·cm (4.8V)

转动角度:约180度

控制信号:50Hz PWM (周期20ms)

脉冲宽度:0.5ms-2.5ms对应0-180度

舵机控制原理

舵机通过PWM信号的脉冲宽度来确定转动角度。对于SG90舵机:

ESP32驱动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. 驱动直流电机

直流电机
直流电机

工作电压:3-12V(视型号而定)

控制方式:PWM调速 + 方向控制

需要驱动电路:H桥电机驱动模块(如L298N)

直流电机控制原理

直流电机控制需要两个要素:

  1. 速度控制:通过PWM占空比调节
  2. 方向控制:通过H桥电路改变电流方向

使用L298N驱动直流电机

L298N电机驱动模块
L298N电机驱动模块

驱动电压:5-35V

最大电流:2A(每通道)

可驱动2个直流电机或1个步进电机

需要3个控制信号:ENA(使能)、IN1、IN2

ESP32连接L298N驱动直流电机

#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等更现代的电机驱动芯片,它体积更小、效率更高、发热更低。

实验建议

  1. 尝试改变呼吸灯的渐变速度和PWM频率,观察效果变化
  2. 使用电位器作为输入,控制舵机角度
  3. 设计一个简单的遥控小车,使用PWM控制电机速度
  4. 尝试使用ESP32的LEDC渐变函数实现更平滑的呼吸灯效果
客服小姐姐(优先添加)
我们的电子元件店铺

扫描获取课程所需元件