树莓派4B——PWM输出控制详解(含舵机应用)
本文介绍了在树莓派4B上使用wiringPi库实现PWM(脉宽调制)输出的方法。主要内容包括:PWM基本原理讲解,重点说明占空比概念;通过C语言编程实现基础PWM输出控制LED亮度;重点演示了SG90舵机控制应用,详细解析了角度与PWM脉冲宽度的转换公式。文章提供了完整的代码示例,涵盖软硬件配置要点,并解释了PWM频率计算、舵机控制参数转换等关键技术细节。最后总结了使用注意事项,为树莓派电机控制、
一、PWM简介
PWM(脉宽调制,Pulse Width Modulation) 是一种通过调节数字脉冲信号的占空比来等效模拟输出电平的技术。它在数字系统(如单片机、树莓派)中广泛用于高效控制模拟电路,例如调节电机速度、LED亮度或电源电压等。
-
占空比(Duty Cycle): 指在一个PWM信号周期内,高电平持续时间占整个周期时间的百分比。
-
公式:
占空比 = (高电平时间 / 周期时间) × 100% -
示例: 50%占空比表示高电平和低电平持续时间各占周期的一半。
-
二、树莓派PWM输出实践
1. 基础PWM输出
-
创建程序文件:
使用nano编辑器创建C语言源代码文件:nano pwm_basic.c -
编写程序代码 (
pwm_basic.c):#include <stdio.h> #include <stdlib.h> // 添加 exit 函数声明 #include <wiringPi.h> #include <softPwm.h> #define PWM_PIN 29 // 使用 WiringPi 引脚编号 29 (对应 BCM GPIO 21) int main() { printf("树莓派 PWM 输出基础实验\n"); // 初始化 wiringPi 库 if (wiringPiSetup() == -1) { printf("初始化 wiringPi 失败!\n"); exit(1); // 退出程序 } // 创建软件 PWM // 参数: 引脚, 初始值, PWM范围 (Range) // 频率 = 100Hz (默认) / Range // 当前设置: Range=100 -> 频率 = 100Hz softPwmCreate(PWM_PIN, 0, 100); // 设置 PWM 输出占空比 // 占空比 = value / Range * 100% // value=50, Range=100 -> 占空比 = 50% softPwmWrite(PWM_PIN, 50); printf("PWM 输出已启动 (引脚 %d, 50%% 占空比)...\n", PWM_PIN); printf("按 Ctrl+C 退出程序。\n"); // 主循环,保持程序运行 while (1) { delay(1000); // 延时1秒,避免CPU空转占用过高 } return 0; // 实际不会执行到这里 }代码说明:
-
使用
softPwmCreate(PWM_PIN, 0, 100)初始化引脚为软件PWM输出。100是 PWM 范围 (pwmRange)。 -
PWM 频率计算: 软件PWM的默认基础频率约为100Hz。实际输出频率 = 100Hz /
pwmRange。-
pwmRange=100-> 频率 ≈ 100Hz / 100 = 1Hz -
pwmRange=50-> 频率 ≈ 100Hz / 50 = 2Hz -
pwmRange=2-> 频率 ≈ 100Hz / 2 = 50Hz
-
-
softPwmWrite(PWM_PIN, 50)设置输出值。占空比 =value/pwmRange* 100%。这里value=50,pwmRange=100, 占空比为50%。 -
添加了
delay(1000);在while(1)循环中,避免程序空转消耗过多CPU资源。 -
添加了退出提示信息。
-
-
保存文件:
-
在
nano中,按Ctrl + O写入文件,回车确认文件名。 -
按
Ctrl + X退出nano。
-
-
编译程序:
打开终端,进入程序文件所在目录,使用以下命令编译:gcc pwm_basic.c -o pwm_basic -lwiringPi-
gcc: C语言编译器 -
pwm_basic.c: 源代码文件 -
-o pwm_basic: 指定输出可执行文件名为pwm_basic -
-lwiringPi: 链接 wiringPi 库
-
-
运行程序:
sudo ./pwm_basic # 通常需要 root 权限访问 GPIO -
测试验证:
-
示波器: 最直接的方法是使用示波器探头连接到树莓派的 GPIO 21 (对应 WiringPi 29) 引脚和 GND 引脚,观察输出的PWM波形(周期应接近1s,占空比50%)。
-
LED: 将一个LED(带合适限流电阻,如220Ω-1kΩ)正极接GPIO 21,负极接GND。LED应呈现约50%的亮度(肉眼感知可能接近全亮,但用手机慢动作拍摄可观察到闪烁)。改变
softPwmWrite的值(0-100)可调节亮度。 -
舵机验证: 见下一节。
-
2. 应用:舵机控制 (SG90)
舵机(如常见的SG90 180°型号)通常使用周期为 20ms (50Hz)、高电平宽度在 0.5ms 到 2.5ms 之间的PWM信号来控制角度。
-
角度与控制脉冲宽度关系:
-
0.5ms -> 0°
-
1.0ms -> 45°
-
1.5ms -> 90°
-
2.0ms -> 135°
-
2.5ms -> 180°
-
-
硬件连接:
-
将舵机的 信号线(通常是橙色或黄色) 连接到树莓派的 GPIO 21 (WiringPi 29) 引脚。
-
将舵机的 电源线(红色) 连接到 5V 引脚。
-
将舵机的 地线(棕色或黑色) 连接到 GND 引脚。
注意: 如果控制多个舵机或大功率舵机,建议使用外部电源供电,并将外部电源地与树莓派GND相连。
-
-
修改程序 (
pwm_servo.c):#include <stdio.h> #include <wiringPi.h> #include <softPwm.h> #define PWM_PIN 29 // 使用 WiringPi 引脚编号 29 (对应 BCM GPIO 21) int main() { printf("树莓派 PWM 舵机控制实验\n"); // 初始化 wiringPi 库 if (wiringPiSetup() == -1) { printf("初始化 wiringPi 失败!\n"); return 1; } // 创建软件 PWM 用于舵机 // 目标周期: 20ms (50Hz) // 计算 PWM Range: Range ≈ 100Hz(基础) / 目标频率(50Hz) = 2 // 设置 Range = 200 可以获得更精细的角度控制 softPwmCreate(PWM_PIN, 0, 200); // Range=200, 频率≈100Hz/200=0.5Hz? 需要修正理解 // 修正: 软件PWM频率计算公式更正 // 实际 softPwm 底层使用 100μs 的时间片。 // 周期时间 (us) = Range * 100μs // 目标周期 20000us (20ms) = Range * 100us // => Range = 20000us / 100us = 200 // 因此: softPwmCreate(PWM_PIN, 0, 200); 设置后,周期=20ms (50Hz) 正确。 // 此时 value 范围 0-200, 对应高电平时间 = value * 100μs int angle = 0; // 初始角度设为 0° while (1) { // 将角度 (0°-180°) 转换为 PWM 值 (控制高电平时间) // 高电平时间范围: 500us (0°) - 2500us (180°) // 高电平时间 (us) = 500 + (angle * 2000 / 180) = 500 + (angle * 100 / 9) // 因为 value 代表 100μs 的个数: value = 高电平时间(us) / 100 // => value = (500 + (angle * 100 / 9)) / 100 = 5 + (angle / 9) // 更直观的写法: int pulseWidthUs = 500 + angle * (2000 / 180); // 计算所需高电平时间(us) int value = pulseWidthUs / 100; // 计算对应的PWM value (100us为单位) // 或者直接使用等效公式: value = 5 + (angle * 20) / 180; // 即 5 + angle/9 value = 5 + (angle * 20) / 180; // 结果相同 // 输出 PWM 信号控制舵机 softPwmWrite(PWM_PIN, value); printf("当前角度: %d° (Value=%d)\n", angle, value); // 打印角度和对应值 angle += 10; // 角度增加 10° if (angle > 180) { angle = 0; // 到达 180° 后归零 } delay(1000); // 延时 1 秒 } return 0; }代码说明:
-
核心公式: 控制舵机角度的关键在于生成对应宽度的高电平脉冲。
-
所需高电平时间 (
pulseWidthUs) =500 + angle * (2000 / 180)微秒 (μs)。简化计算:500 + angle * 100 / 9。 -
由于
softPwm底层以 100μs 为单位,value = pulseWidthUs / 100。 -
合并公式:
value = 5 + angle / 9。代码中使用了整数运算友好的value = 5 + (angle * 20) / 180(等价于5 + angle/9)。
-
-
PWM设置 (
softPwmCreate):-
设置
Range = 200。这是为了匹配舵机需要的 20ms (20000μs) 周期。 -
底层机制:
softPwm使用100μs时间片。周期 = Range * 100μs。 -
目标周期
20000μs=Range * 100μs=>Range = 200。设置正确。 -
value范围0-200,对应高电平时间0-20000μs。舵机只识别500-2500μs部分。
-
-
角度变化步长改为
10°并每秒移动一次,演示效果更明显。 -
输出信息包含当前角度和计算出的
value值,便于调试。
-
-
编译与运行:
gcc pwm_servo.c -o pwm_servo -lwiringPi sudo ./pwm_servo -
观察现象:
舵机会从 0° 开始,每秒钟转动 10°,到达 180° 后跳回 0° 重新开始转动。
三、总结
本文详细介绍了如何在树莓派4B上利用 wiringPi 库的 softPwm 功能实现 PWM 信号输出。从 PWM 的基础原理讲起,通过基础 LED 亮度控制示例演示了 PWM 的生成方法,并重点讲解了如何使用 PWM 精确控制 SG90 舵机的角度。关键点在于理解 PWM 周期(20ms) 和 高电平脉冲宽度(0.5ms-2.5ms) 与舵机角度的对应关系,并通过计算将其转换为 softPwmWrite 函数所需的 value 值。
提供的示例代码可以直接用于基础实验和舵机控制,读者可以根据需要修改引脚、角度范围和运动模式。掌握 PWM 技术是树莓派进行电机控制、LED调光等交互应用的重要基础。
温馨提示:
-
操作 GPIO 通常需要
sudo权限。 -
连接舵机时务必注意电源匹配,避免树莓派 5V 电源过载。
-
softPwm是软件模拟实现,其精度和实时性有一定限制。对精度和实时性要求极高的应用(如多路精确同步)可考虑使用树莓派硬件 PWM 引脚(BCM GPIO 12, 13, 18, 19),但这需要不同的库和配置。
希望这篇博客能帮助你顺利在树莓派上实现 PWM 控制!如有任何疑问或发现文中疏漏,欢迎在评论区留言讨论。
更多推荐



所有评论(0)