一、实验目标

使用 ESP32 开发板自带的 LED 灯(通常连接在 GPIO2),通过 PWM(脉冲宽度调制)技术实现呼吸灯效果。

二、实验器材

三、PWM 原理简介

什么是 PWM?

PWM (Pulse Width Modulation) 即脉冲宽度调制。它是一种通过快速开关数字信号来模拟模拟信号的技术。

核心概念:占空比 (Duty Cycle)

占空比是指在一个脉冲周期内,高电平(ON)持续时间占整个周期时间的百分比。

  • 100% 占空比: 信号一直是高电平 (3.3V),LED 最亮。
  • 50% 占空比: 一半时间高电平,一半时间低电平。LED 亮度约为一半。
  • 0% 占空比: 信号一直是低电平 (0V),LED 熄灭。

由于 LED 开关速度非常快(远超人眼识别频率),人眼看到的不是闪烁,而是平均亮度的变化。

四、实验步骤

步骤1:硬件确认

  1. 观察 ESP32 开发板,找到板载 LED。
  2. 确认 LED 位置(通常位于 USB 接口附近,标注为 "ON" 或 "LED")。
  3. 使用 USB 线连接 ESP32 和电脑。
  4. 观察板载 LED 是否亮起(电源指示灯)。

步骤2:软件准备

  1. 打开 Arduino IDE
  2. 设置开发板类型:工具 → 开发板 → ESP32 Arduino → ESP32 Dev Module
  3. 选择端口:工具 → 端口 → 选择对应的 COM 端口(Windows)

步骤3:编写呼吸灯程序

在 Arduino IDE 中输入以下代码:

// 定义LED引脚
const int ledPin = 2;  

// 设置PWM属性
const int freq = 5000;          // 频率 5000Hz
const int resolution = 8;       // 分辨率 8位 (0-255)

void setup() {
  Serial.begin(115200);

  // 【新版用法】直接将引脚、频率和分辨率绑定
  // 它会自动返回一个关联的通道(如果需要的话)
  ledcAttach(ledPin, freq, resolution);
}

void loop() {
  // 逐渐变亮
  for(int dutyCycle = 0; dutyCycle <= 255; dutyCycle++){   
    // 【新版用法】直接通过引脚号写入,不再需要指定通道
    ledcWrite(ledPin, dutyCycle);   
    delay(10);
  }

  // 逐渐变暗
  for(int dutyCycle = 255; dutyCycle >= 0; dutyCycle--){
    ledcWrite(ledPin, dutyCycle);   
    delay(10);
  }
  
  Serial.println("Breathing cycle completed");
}

步骤4:上传程序

  1. 点击上传按钮(→)。
  2. 观察上传过程:
    • 如果出现 "上传失败",尝试按住 BOOT 按钮再点击上传。
    • 等待直到看到 "上传成功" 提示。
  3. 观察板载 LED 是否开始呼吸闪烁。

步骤5:观察效果与调试

  1. 观察 LED 变化:
    • LED 应缓慢变亮再缓慢变暗。
    • 循环往复,形成呼吸效果。
  2. 打开串口监视器:
    • 点击右上角 "串口监视器" 图标。
    • 设置波特率为 115200。
    • 观察输出的呼吸周期计数。
  3. 修改呼吸速度:
    • 修改代码中 delay(10) 的数值。
    • 数值变大 → 呼吸变慢。
    • 数值变小 → 呼吸变快。
    • 重新上传观察效果变化。

五、常见问题及解决

问题1:LED不亮

问题2:呼吸效果不明显

问题3:上传失败

六、实验总结

知识点掌握

  1. PWM 原理: 通过调节占空比(Duty Cycle)控制 LED 平均亮度。
  2. ESP32 PWM 配置:
    • ledcSetup():配置 PWM 通道参数(频率、分辨率)。
    • ledcAttachPin():绑定引脚到 PWM 通道。
    • ledcWrite():设置通道的占空比值。
  3. 呼吸灯算法: 通过循环结构(for循环)逐渐递增和递减占空比,配合 delay() 实现平滑过渡。

七、课后思考

🤔 思考题:

  • 非线性呼吸: 目前的呼吸灯亮度变化是线性的(for 循环步长为 1)。但人眼对亮度的感知并非线性(对数关系)。如何修改代码,使得呼吸效果看起来更加自然柔和?(提示:使用正弦函数 sin() 或指数函数)
  • 多色呼吸: 如果你有 RGB LED(或三个独立 LED),如何利用 PWM 实现彩虹灯渐变效果(红变绿、绿变蓝、蓝变红)?