【树莓派学习】001 PWM实验
实验名称:树莓派PWM信号生成与示波器分析
实验目标
- 通过Python编程,让树莓派生成一个可调占空比的PWM信号。
- 用示波器捕捉并测量该PWM信号的频率和占空比,验证软件控制与硬件输出的一致性。
所需设备
- 硬件:
- 树莓派 (任何型号,已安装系统)
- MacBook
- 数字示波器
- 面包板、LED灯、220Ω电阻、杜邦线若干
- USB转TTL串口模块 (可选,用于串口调试)
- 软件:
- MacBook上的终端 (用于SSH或串口连接)
- 树莓派上的Python3及
RPi.GPIO库
具体步骤
第一步:硬件连接
- 树莓派GPIO连接:
- 将LED的正极(长脚)通过一个220Ω的限流电阻,连接到树莓派的 GPIO 18 (物理引脚12)。这是因为GPIO 18支持硬件PWM。
- 将LED的负极(短脚)连接到树莓派的 GND (物理引脚6)。
- 示波器连接:
- 将示波器探头的尖端钩在 GPIO 18 引脚上。
- 将示波器探头的接地夹夹在树莓派的 GND 引脚上。
- MacBook连接树莓派:
- 方法A
(推荐,使用SSH):确保MacBook和树莓派在同一个Wi-Fi下,在Mac终端输入:
ssh pi@<你的树莓派IP地址>,然后输入密码。 - 方法B
(使用串口):通过USB转TTL模块连接树莓派的UART引脚,在Mac上用
screen命令连接。
- 方法A
(推荐,使用SSH):确保MacBook和树莓派在同一个Wi-Fi下,在Mac终端输入:
连接示意图: 1
2
3树莓派 GPIO 18 ---[220Ω电阻]--- LED(+) --- LED(-) --- GND
|
+--- (连接至示波器探头)
1.
命令行工具:pinout
这是最直接、最推荐的方法。
在你的树莓派终端中,直接输入: 1
pinout
RPi.GPIO
库默认使用的编号。 - 电源引脚 (3.3V, 5V, GND) -
特殊功能引脚 (例如,我们实验要用到的GPIO 18)
示例输出(部分): 1
2
3
4
5
6
7
8
9
10
11
12
13 3V3 (1) ◉◉ (2) 5V
GPIO2 (3) ◉◉ (4) 5V
GPIO3 (5) ◉◉ (6) GND
GPIO4 (7) ◉◉ (8) GPIO14
GND (9) ◉◉ (10) GPIO15
GPIO17 (11) ◉◉ (12) GPIO18 <-- 我们要用的引脚!
GPIO27 (13) ◉◉ (14) GND
GPIO22 (15) ◉◉ (16) GPIO23
3V3 (17) ◉◉ (18) GPIO24
GPIO10 (19) ◉◉ (20) GND
GPIO9 (21) ◉◉ (22) GPIO25
GPIO11 (23) ◉◉ (24) GPIO8
GND (25) ◉◉ (26) GPIO7
从图中可以看到,物理引脚12 对应的就是 BCM GPIO 18。
2. GPIO库的Python命令
如果你已经在Python环境中,可以这样验证:
- 在树莓派终端输入
python3进入Python交互环境。 - 依次输入以下命令: 如果没有报错,说明GPIO 18是可用的。
1
2
3
4
5import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM) # 设置为BCM编号模式
# 将GPIO 18设置为输出模式,这会初始化该引脚
GPIO.setup(18, GPIO.OUT)
print("GPIO 18 设置成功!")
第二步:创建并运行Python脚本
在树莓派上,创建一个Python文件,例如
pwm_test.py:1
vi pwm_test.py
将以下代码复制进去:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51#!/usr/bin/env python3
import RPi.GPIO as GPIO
import time
import atexit
PWM_FREQUENCY = 1000 # 频率
PWM_DUTY_CYCLE = 50 # 占空比
# 全局变量跟踪PWM状态
pwm_active = False
pwm_instance = None
def cleanup_resources():
"""在程序退出时清理资源"""
global pwm_active, pwm_instance
if pwm_active and pwm_instance:
try:
pwm_instance.stop()
pwm_active = False
pwm_instance = None
except:
pass
try:
GPIO.cleanup()
except:
pass
# 注册退出处理函数
atexit.register(cleanup_resources)
try:
# 设置GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.OUT)
# 创建并启动PWM
pwm_instance = GPIO.PWM(18, PWM_FREQUENCY)
pwm_instance.start(PWM_DUTY_CYCLE)
pwm_active = True
print(f"PWM已启动,频率{PWM_FREQUENCY}Hz,占空比{PWM_DUTY_CYCLE}%。按 Ctrl+C 停止程序。")
# 主循环
while True:
time.sleep(1)
except KeyboardInterrupt:
print("\n程序被用户中断")
finally:
cleanup_resources()
print("资源清理完成")保存并退出 (在nano中按
Ctrl+X, 然后按Y, 最后按Enter)。运行脚本 (需要sudo权限来访问GPIO):
### 硬件PWM1
sudo python3 pwm_test.py
方法1:从源码编译安装pigpio
1 | # 安装编译依赖 |
1 | #!/usr/bin/env python3 |
**方法2:gpiozero
1 | # 安装gpiozero(通常已预装) |
1 | #!/usr/bin/env python3 |
1 | pwm_hw_test.py |
第三步:使用示波器测量
- 打开示波器。
- 将探头连接到 物理引脚12 (GPIO 18) 和 GND。
- 在示波器上执行 自动设置 或手动调整:
- 时基:调到 500μs/div 左右,以清晰看到1kHz的周期。
- 电压刻度:调到 1V/div 或 2V/div。
- 触发:设置为边沿触发,源选择你连接的通道,电平调到约1.6V (3.3V的一半)。
- 你应该能立即在屏幕上看到一个稳定的 方波。
- 进行测量:
- 频率:使用示波器的测量功能,选择“频率”,读数应接近 1.000 kHz。
- 占空比:选择“占空比”测量,读数应接近 50.0%。
- 电压:高电平应在 3.3V 左右,低电平在 0V。
软件PWM
硬件PWM 10MHz
树莓派PWM频率对比
软件PWM (RPi.GPIO)
- 最高频率:约 1-10kHz (实际使用建议 ≤1kHz)
- 限制因素:Python解释器性能、系统负载
- 特点:所有GPIO都可用,但精度差、抖动明显
硬件PWM (pigpio/gpiozero)
- 最高频率:理论上可达 125MHz (树莓派4)
- 实际可用频率:通常 1kHz - 30MHz
- 支持引脚:仅 GPIO12, GPIO13, GPIO18, GPIO19
具体频率对比表
| 方法 | 最高频率 | 推荐频率 | 精度 | 稳定性 |
|---|---|---|---|---|
| RPi.GPIO软件PWM | ~10kHz | ≤1kHz | 低 | 差 |
| pigpio硬件PWM | 125MHz | 1kHz-30MHz | 极高 | 优秀 |
| gpiozero硬件PWM | 125MHz | 1kHz-30MHz | 极高 | 优秀 |
| Linux PWM子系统 | 125MHz | 1kHz-30MHz | 极高 | 优秀 |
第四步:实验扩展
修改代码中的 pwm.start(50),将 50 改为
10 (10%占空比) 或 90
(90%占空比),重新运行程序。再次用示波器测量,你会看到波形的“高电平”部分明显变短或变长,但频率保持不变。
恭喜你! 你已经成功地用软件生成一个精确的硬件信号,并用示波器完成了验证。这是嵌入式系统调试中最基础的技能之一。