[具身智能-570]:RDK Hobot.GPIO PWM 渐变输出代码完整解析
·
#!/usr/bin/env python3
################################################################################
# Copyright (c) 2024,D-Robotics.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
################################################################################
import sys
import signal
import Hobot.GPIO as GPIO
import time
def signal_handler(signal, frame):
sys.exit(0)
# 支持PWM的管脚: 32 and 33, 在使用PWM时,必须确保该管脚没有被其他功能占用
output_pin = 33
GPIO.setwarnings(False)
def main():
# Pin Setup:
# Board pin-numbering scheme
GPIO.setmode(GPIO.BOARD)
# 支持的频率范围: 48KHz ~ 192MHz
p = GPIO.PWM(output_pin, 48000)
# 初始占空比 25%, 先每0.25秒增加5%占空比,达到100%之后再每0.25秒减少5%占空比
val = 25
incr = 5
p.ChangeDutyCycle(val)
p.start(val)
print("PWM running. Press CTRL+C to exit.")
try:
while True:
time.sleep(0.25)
if val >= 100:
incr = -incr
if val <= 0:
incr = -incr
val += incr
p.ChangeDutyCycle(val)
finally:
p.stop()
GPIO.cleanup()
if __name__ == '__main__':
signal.signal(signal.SIGINT, signal_handler)
main()
一、整体功能概述
该脚本基于地平线 Hobot.GPIO 库实现硬件 PWM 呼吸灯效果:
- 使用 BOARD 引脚 33(RDK 仅 32、33 支持硬件 PWM);
- PWM 固定频率 48000Hz,初始占空比 25%;
- 每 250ms 占空比 ±5%,从 25% 逐步升到 100%,再降到 0%,循环往复;
- 支持 Ctrl+C 安全退出,自动停止 PWM 并释放 GPIO 资源;
- 硬件 PWM 由 SOC 外设输出,不占用 CPU 循环翻转电平,精度高。
硬件接线:33 引脚串联限流电阻接 LED 正极,LED 负极接 GND,通过 PWM 平均电压实现亮度渐变呼吸效果。
二、逐段代码拆解
1. 头部、通用依赖与信号处理
python
运行
#!/usr/bin/env python3
# Apache2.0开源协议声明
import sys
import signal
import Hobot.GPIO as GPIO
import time
def signal_handler(signal, frame):
sys.exit(0)
#!/usr/bin/env python3:可直接./脚本名运行;signal:捕获Ctrl+C(SIGINT)信号,主动退出触发finally资源清理;Hobot.GPIO:地平线专用 GPIO 库,内置硬件 PWM 封装;signal_handler:中断回调,执行系统退出。
2. 硬件引脚定义与警告屏蔽
python
运行
# 支持PWM的管脚: 32 and 33, 在使用PWM时,必须确保该管脚没有被其他功能占用
output_pin = 33
GPIO.setwarnings(False)
- RDK 硬件限制:只有 BOARD 32、33 引脚具备硬件 PWM 外设,其余 IO 仅普通数字输入输出;
- 使用前必须确认该引脚未被设备树、其他程序复用;
setwarnings(False):屏蔽引脚重复初始化警告日志。
3. 主函数 main ()
3.1 PWM 对象初始化
python
运行
GPIO.setmode(GPIO.BOARD)
# 创建PWM实例:引脚 + 频率48000Hz
p = GPIO.PWM(output_pin, 48000)
val = 25 # 初始占空比 25%
incr = 5 # 每次变化步长 5%
p.ChangeDutyCycle(val)
p.start(val)
关键 API 说明:
GPIO.setmode(GPIO.BOARD):采用开发板物理丝印编号;GPIO.PWM(pin, freq)创建 PWM 对象- 频率范围文档标注:48KHz ~ 192MHz;示例选用最低 48KHz;
- 频率越高,人眼频闪感越弱,适合 LED 调光;
p.start(duty_cycle):启动 PWM 输出,参数为初始占空比(0~100);p.ChangeDutyCycle(val):动态修改占空比,val 取值区间0 ~ 100;- 0:完全低电平,LED 熄灭;
- 100:持续高电平,LED 最亮。
3.2 主循环:亮度渐变逻辑
python
运行
try:
print("PWM running. Press CTRL+C to exit.")
while True:
time.sleep(0.25) # 250ms更新一次亮度
# 到达上限100%,反向递减
if val >= 100:
incr = -incr
# 到达下限0%,反向递增
if val <= 0:
incr = -incr
val += incr
p.ChangeDutyCycle(val)
渐变逻辑流程:
- 初始 val=25,incr=5 → 每 0.25s +5:25→30→35…→100;
- val=100 时 incr 取反 =-5 → 开始递减:100→95→90…→0;
- val=0 时 incr 再次取反 = 5,重新递增,无限循环呼吸效果;
time.sleep(0.25)控制渐变速度,数值越大呼吸越慢。
3.3 finally 资源强制释放(核心规范)
python
运行
finally:
p.stop() # 关闭硬件PWM外设输出
GPIO.cleanup() # 重置引脚,释放GPIO内核资源
无论正常循环、Ctrl+C 中断、代码异常,finally 一定会执行:
p.stop():停止 PWM 波形输出,引脚变为普通 IO;不调用会持续输出 PWM;GPIO.cleanup():清空该引脚配置,防止下次运行报引脚占用。
4. 程序入口
python
运行
if __name__ == '__main__':
signal.signal(signal.SIGINT, signal_handler)
main()
提前注册 Ctrl+C 中断回调,保证退出流程完整执行资源回收。
三、PWM 核心原理补充
- PWM(脉冲宽度调制):固定周期内,高电平时间占比为占空比;
- 占空比越高,等效平均电压越高,LED 越亮;
- 本代码为硬件 PWM:波形由 SOC 硬件外设自动生成,主线程仅周期性修改占空比,CPU 无持续翻转开销;
- 频率 48kHz 远高于人眼闪烁感知阈值,肉眼看不到频闪,调光顺滑。
四、完整运行时序
- 启动脚本,注册 Ctrl+C 中断;
- 初始化 BOARD 模式,创建 48kHz PWM 实例,25% 占空比启动输出;
- 进入循环,每 250ms 增减 5% 占空比,自动升降亮度;
- 按下 Ctrl+C 触发信号处理函数,执行
sys.exit(); - 进入 finally,停止 PWM、清理 GPIO,程序安全退出。
五、开发注意事项 & 踩坑点
- 引脚限制:仅 32、33 支持硬件 PWM,其他引脚调用
GPIO.PWM会报错; - 频率范围约束:不可低于 48000Hz;
- 占空比范围:
0 ≤ val ≤ 100,超出区间无效果; - 权限问题:操作 GPIO 建议加
sudo python3 xxx.py; - 退出不执行 cleanup/p.stop:会导致引脚持续输出 PWM,占用硬件资源;
- 呼吸速度调节:修改
sleep(0.25)数值,调大渐变变慢,调小变快; - 步长控制:修改
incr=5,数值越大亮度变化跳跃感越强。
六、扩展修改示例
- 放慢呼吸速度:
time.sleep(0.5) - 亮度每次变化 10%:
incr = 10 - 更换 PWM 引脚为 33→32:仅修改
output_pin = 32即可。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)