RPIO 文档翻译 - RPIO.PWM(利用 DMA 为 Raspberry Pi 实现 PWM)

更新日志:
2013 年 6 月 4 日更新:根据官方文档完成了初步翻译。
本文会在适当的时间里进行增删改等操作,如果您对该文感兴趣,可以仅收藏本页。
本文链接:RPIO 文档翻译 - RPIO.PWM(利用 DMA 为 Raspberry Pi 实现 PWM)

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 计时硬件时)。通过制定一个起始点和宽度参数,为子循环添加脉冲设置,两者都可以拥有多种粒度。例如,设置 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()

pwm_0

现在设置 GPIO 15 上每 20ms 脉冲为 4000us(4ms):

servo.set_servo(15, 4000)

pwm_1

现在设置 GPIO 17 上的脉冲为 1000µs(1ms)

servo.set_servo(17, 1000)

pwm_2

我们可以使用底层 PWM 模块为子循环进一步设置脉冲。该设置完成了脉宽增量粒度的设置(start=200*10µs=2000µs, width=100*10µs=1000µs):

PWM.add_channel_pulse(0, 17, start=200, width=100)

pwm_3

原文地址:RPIO.PWM, PWM via DMA for the Raspberry Pi
项目地址:RPIO’s documentation!

2 thoughts on “RPIO 文档翻译 - RPIO.PWM(利用 DMA 为 Raspberry Pi 实现 PWM)”

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>