更新日志: 2013 年 6 月 4 日更新:根据官方文档完成了初步翻译。 本文会在适当的时间里进行增删改等操作,如果您对该文感兴趣,可以仅收藏本页。
RPIO.PWM
提供了利用 DMA 为 Raspberry Pi 实现 PWM 功能,使用板载的半硬件脉宽调制(PWM )模块可精确到 1µs(微秒)。
在 RPIO.PWM
中,您可以随意使用所有 15 个 DMA 通道,并且每个通道中可以使用任意个数 GPIO。当通过 DMA 实现 PWM 时,RPIO.PWM
几乎不消耗 CPU 资源,并且可以产生稳定的脉冲且分辨率非常高。RPIO.PWM
是使用 C 语言(源代码)编写的;可通过提供的封装包在 Python 中使用,甚至可以直接在您的 C 语言代码中使用。
RPIO.PWM
提供了手动控制任何东西的底层方案,甚至还为特殊用途准备的简化 PWM 辅助类库(比如:RPIO.PWM.Servo
)。该模块目前还处于 beta 阶段,请将反馈发送至 chris@linuxuser.at。而且目前仅支持 BCM GPIO 编号方式。
示例
PWM.Servo
使用示例(使用默认的 20ms 子循环时长和默认的 10µs 脉宽增量粒度):
from RPIO import PWM
servo = PWM.Servo()
# 设置 GPIO 17 上的 servo 为 1200µs(1.2ms)
servo.set_servo(17, 1200)
# 设置 GPIO 17 上的 servo 为 2000µs(2.0ms)
servo.set_servo(17, 2000)
# 清除 GPIO 17 上的 servo
servo.stop_servo(17)
使用底层 PWM 方案的示例:
from RPIO import PWM
# 设置 PWM 和 DMA 使用通道 0
PWM.setup()
PWM.init_channel(0)
# 为子循环添加脉冲值
PWM.add_channel_pulse(0, 17, 0, 50)
PWM.add_channel_pulse(0, 17, 100, 50)
# 停止通道 0 中指定 GPIO 上的 PWM
PWM.clear_channel_gpio(0, 17)
# 关闭所有 PWM 和 DMA 操作
PWM.cleanup()
RPIO.PWM.Servo
RPIO.PWM.Servo
类库的详细描述(来源自 $ pydoc RPIO.PWM.Servo
):
Servo 类库
# 方案定义:
__init__(self, dma_channel=0, subcycle_time_us=20000, pulse_incr_us=10)
# 请确认 PWM 设置了正确的增量粒度和子循环时间。
set_servo(self, gpio, pulse_width_us)
# 为 GPIO 设置每个子循环重复一次的脉宽(默认为 20ms)。
stop_servo(self, gpio)
# 停止该 GPIO 的 servo 操作。
RPIO.PWM
底层 PWM 方案文档(来源自 $ pydoc RPIO.PWM
):
函数
add_channel_pulse(dma_channel, gpio, start, width)
# 为某个 DMA 通道中指定的 GPIO 设置脉冲(添加到子循环中)
cleanup()
# 停止所有 PWM 和 DMA 操作
clear_channel(channel)
# 清空某个通道中所有脉冲值
clear_channel_gpio(channel, gpio)
# 清空该 DMA 通道中指定 GPIO 上的值
get_channel_subcycle_time_us(channel)
# 以微秒为单位返回该通道子循环时间
get_pulse_incr_us()
# 以微秒为单位返回当前设置的宽脉增量粒度
init_channel(channel, subcycle_time_us=20000)
# 以微秒为单位设置某通道为特定的子循环时间
is_channel_initialized(channel)
# 如果该通道被初始化则返回 1,否则返回 0
is_setup()
# 如果调用了 setup(..) 则返回 1,否则返回 0
print_channel(channel)
# 打印特定通道的信息到标准输出设备
set_loglevel(level)
# 为该 PWM 模块设置 loglevel。
# PWM.LOG_LEVEL_DEBUG 将记录所有信息,PWM.LOG_LEVEL_ERRORS 将只记录错误信息。
setup(pulse_incr_us=10, delay_hw=0)
# 任何通道工作之前,都需要调用一次 Setup。
# 可选参数:
# pulse_incr_us:宽脉增量粒度(默认为 10us)
# delay_hw:PWM.DELAY_VIA_PWM(默认)或 PWM.DELAY_VIA_PCM
常量
DELAY_VIA_PCM = 1
DELAY_VIA_PWM = 0
LOG_LEVEL_DEBUG = 0
LOG_LEVEL_ERRORS = 1
PULSE_WIDTH_INCREMENT_GRANULARITY_US_DEFAULT = 10
SUBCYCLE_TIME_US_DEFAULT = 20000
VERSION = '0.9.1'
扩展讲解
可以查看 Github 上的 C 语言源程序获得更多细节。
子循环
每个 DMA 通道都设置了一个特定的子循环,包括添加了脉冲设置,并且会反复执行。伺服系统,通常使用 20ms 的子循环时间,并且每秒重复 50 次。您可以为多个 GPIO 添加脉冲设置,也可以为某 GPIO 设置多个脉冲值。子循环时间不能低于 2ms。
如需获得更多关于子循环的信息,可以看下面的示例。左边的示波器图像放大显示了一个子循环,右边的图像整体显示了它们的重复情况。
脉宽增量粒度
脉宽增量粒度(默认为 10µs)应用于所有 DMA 通道(当使用 PWM 计时硬件时)。通过制定一个 start
和 width
参数,为子循环添加脉冲设置,两者都可以拥有多种粒度。例如,设置 500µs 的脉冲值以及粒度设置为 10µs,那么您将需要设置脉宽为 50(50 * 10µs = 500µs)。
由于使用的是 PWM 硬件,脉宽增量粒度是系统的全局设置,因此您不能在同一时间内使用不同的粒度设置,尽管在不同的进程中也是如此。
示波器示例
在示波器图像中,GPIO 15 为蓝色的通道,GPIO 17 为黄色的通道。左边的示波器图像显示单个子循环,右边的图像整体显示了它们的重复情况。首先我们将 PWM.Servo 的子循环设置为默认的 20ms,以及脉宽增量粒度为 10µs:
from RPIO import PWM
servo = PWM.Servo()
现在设置 GPIO 15 上每 20ms 脉冲为 4000us(4ms):
servo.set_servo(15, 4000)
现在设置 GPIO 17 上的脉冲为 1000µs(1ms)
servo.set_servo(17, 1000)
我们可以使用底层 PWM 模块为子循环进一步设置脉冲。该设置完成了脉宽增量粒度的设置(start=200*10µs=2000µs, width=100*10µs=1000µs
):
PWM.add_channel_pulse(0, 17, start=200, width=100)
原文地址:RPIO.PWM, PWM via DMA for the Raspberry Pi 项目地址:RPIO’s documentation!