Skip to content

第 9 章:看懂 PWM 调光代码

本章任务

看懂"呼吸灯"的 Arduino C++ 代码——对应第一册第 9 章的实验,和第二册第 9 章是同一个任务。

接线回顾

元件Pico 引脚说明
LED 长脚(正极)GP0PWM 信号
LED 短脚(负极)经 100Ω 电阻接 GND限流保护

RP2040 的所有 GPIO 都支持 PWM(不像 Arduino UNO 只有带 ~ 的引脚才能用),所以代码里换哪个引脚都行。

Mind+ 生成的典型代码

cpp
const int LED_PIN = 0;   // LED 接在 GP0

void setup() {
  pinMode(LED_PIN, OUTPUT);   // 设为输出模式
}

void loop() {
  // 吸气:亮度从 0 慢慢升到 255(最亮)
  for (int duty = 0; duty <= 255; duty += 4) {
    analogWrite(LED_PIN, duty);   // 输出当前亮度
    delay(5);                     // 每一档停 5 毫秒,肉眼才能看到渐变
  }

  // 呼气:亮度从 255 慢慢降到 0(熄灭)
  for (int duty = 255; duty >= 0; duty -= 4) {
    analogWrite(LED_PIN, duty);
    delay(5);
  }
}

代码讲解

核心就一个新"单词":analogWrite(引脚, 亮度)——输出 PWM 信号,亮度范围 0~255(0 全灭、128 半亮、255 全亮)。

两个 for 循环分别负责"吸气"和"呼气":

  • for (int duty = 0; duty <= 255; duty += 4):亮度变量 duty 从 0 开始,每次加 4,一直加到 255——灯越来越亮
  • for (int duty = 255; duty >= 0; duty -= 4):反过来每次减 4——灯越来越暗
  • 每变一档停 5 毫秒,变化足够慢,眼睛看到的就是平滑的"呼吸"

和第二册对照:Python 版亮度范围是 0~65535(duty_u16),这里是 0~255,换算关系是"× 257"。原理完全一样:占空比决定等效亮度。频率不用管,Arduino 默认约 1kHz,人眼看不出闪烁。

运行效果

LED 缓慢变亮再变暗,循环往复,像呼吸一样——和积木版、Python 版的效果完全一致。

常见坑

  • analogWrite 的亮度值是 0~255,看到代码里写 65535 那一定是 Python 版,别搞混
  • for 循环的三段之间是分号for (int duty = 0; duty <= 255; duty += 4),写成逗号编译就报错
  • 如果灯在"闪"而不是"渐变":检查代码里是不是误用了 digitalWrite(它只会全开全关,没有中间亮度)

想一想

  1. 步长从 4 改成 1,呼吸会更细腻还是更粗糙?delay(5) 要不要跟着改?

    💡 查看答案

    步长改小 → 档位变多 → 更细腻,但一次完整呼吸也会变慢(约 4 倍)。如果想保持原来的速度,要把 delay(5) 跟着调小(比如 delay(1))。

  2. 想让呼吸快一倍,最少要改哪几个数字?

    💡 查看答案

    最少改一个:把两个 delay(5) 都改成 delay(2)(约快一倍多),或者把两处步长 4 都改成 8。注意两处要一起改,不然"吸气"和"呼气"速度不一样。

  3. 打开第二册第 9 章,对比 for (int duty = 0; duty <= 255; duty += 4)for duty in range(0, 65536, 1024)——同一件事,两种语言的循环写法差别在哪?

    💡 查看答案

    三要素(起点、终点、步长)都在,只是摆放方式不同:C++ 把"初始化;继续条件;每轮步进"写在一行括号里,用分号隔开;Python 把三要素交给 range() 函数。另外范围不同(0~255 vs 0~65535),但"从暗到亮逐档加"的思路完全一样。

不积跬步,无以至千里;万里之行,始于当下。