【问题标题】:Google EdgeTPU can't get PWM to work with PythonGoogle EdgeTPU 无法让 PWM 与 Python 一起使用
【发布时间】:2019-03-27 20:31:00
【问题描述】:

这是我的测试代码:

from periphery import PWM
import time

# Open PWM channel 0, pin 0
pwm = PWM(0,0)

# Set frequency to 1 kHz
pwm.frequency = 50
# Set duty cycle to 75%
pwm.duty_cycle = 0.02

pwm.enable()

print(pwm.period)
print(pwm.frequency)
print(pwm.enabled)

# Change duty cycle to 50%

pwm.duty_cycle = 0.05

pwm.close()

问题是这部分:

# Open PWM channel 0, pin 0
pwm = PWM(0,0)

运行时可以看到输出PWM(0,0)PWM(0,1)PWM(0,2)

但我在尝试运行以下命令时收到错误消息:

PWM(1,1)

PWM(2,2)

mendel@elusive-jet:/sys/class/pwm$ sudo python3 /usr/lib/python3/dist-packages/edgetpuvision/testPWM.py
OSError: [Errno 19] No such device

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/periphery/pwm.py", line 69, in _open
    f_export.write("%d\n" % pin)
OSError: [Errno 19] No such device

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/edgetpuvision/testPWM.py", line 5, in <module>
    pwm = PWM(1,1)
  File "/usr/local/lib/python3.5/dist-packages/periphery/pwm.py", line 44, in __init__
    self._open(channel, pin)
  File "/usr/local/lib/python3.5/dist-packages/periphery/pwm.py", line 71, in _open
    raise PWMError(e.errno, "Exporting PWM pin: " + e.strerror)
periphery.pwm.PWMError: [Errno 19] Exporting PWM pin: No such device

根据 Coral 和图书馆网站的文档: https://coral.withgoogle.com/tutorials/devboard-gpio/

https://github.com/vsergeev/python-periphery

PWM(1,1)

PWM(2,2)

应该没有问题,我可以看到以下目录存在:

"\sys\class\pwm\pwmchip0"
"\sys\class\pwm\pwmchip1"
"\sys\class\pwm\pwmchip2"

在 python-periphery 源代码中 https://github.com/vsergeev/python-periphery/blob/master/periphery/pwm.py

它应该得到如下路径:

PWM(1,1) ===&gt; /sys/class/pwm/pwmchip1/pwm1 如果pwm1 不存在,那么它应该调用export 来生成它。

所以,我的主要问题是:

  • 什么是channelpin 以及它是如何使用的?
  • 为什么我无法让 PWM(1,1) PWM(2,2) 工作?

提前谢谢你。

----------------2019.4.2更新--------

我自己想出了上一个答案(感谢任何提供帮助的人)。

但是从我自己的回答中可以看出,我仍然无法让 PWM 工作,因为它不能输出稳定的电压。 (您可以在下面查看更多详细信息)。

我目前遇到了另一个问题,即输出电压根本不稳定。所以,这就是我所做的测试:

我使用50hz PWM 和5% 占空比设置了Raspberry Pi 3+ Model BEdgeTPU Coral Board。由于两个设备都有 GPIO 输出 3.3V,我的理论是,它们的输出应该是相同的,但它们不是。

以下是使用 Arduino UNO 板测量的电压:PiEdgeTPU。 (注:所有电压均需除以 10)。您可以看到 Pi 输出中有一个清晰的模式 (PWM),在 1.8v 左右交替。但是如果你看一下 EdgeTPU 的输出,你会发现电压到处都是,而且电压要低得多(1.1v 对 1.8v)。

EdgeTPU PWM 输出显然有问题,所以我做了进一步的研究。从(有限的)document 发现,它说

所有 GPIO 引脚在 iMX8M SOC 内部都有一个 90k 下拉电阻 在启动期间默认使用,除了 I2C 引脚,它 而是在 SOM 上上拉至 3.3V。但是,这些都可以 使用启动后加载的设备树覆盖更改

这让我怀疑90k pull-down resistor 可能由于这个公式V=IR 而降低了输出电压。因此,我正在考虑按照指示在启动时更改device tree overlay。但是,猜猜看,除了overlays.txt 文件中的以下行之外,没有关于如何更改它的文档:

# List of device tree overlays to load. Format: overlay=<dtbo name, no extenstion> <dtbo2> ...
overlay=

我到处搜索,没有关于如何配置 Mendel Linux 设备树覆盖的文档。所以,我目前卡住了,如果你知道答案,请分享它,我将不胜感激。

我也会将此问题分享给 Coral 支持团队,看看他们是否会给我任何回复。(仅供参考,我在发布原始问题时确实向他们发送了一些东西,但还没有收到他们的任何消息,即使他们的网站上写着We try to respond to inquiries within one business day — but often you'll get a response even quicker, usually a few hours.) 所以,祝我好运。如果收到任何回复,将保持更新此答案。

以下是我想传达给 Google/Google Cloud/Google EdgeTPU/Google Coral Board 团队的段落/问题:

  • 为什么选择python-periphery作为默认库来实现GPIO 和脉宽调制?
  • 为什么在没有站点/文档或任何类型可找到的情况下选择 Mendel Linux 作为默认操作系统?

【问题讨论】:

  • 很难从提供的样本中确定波形的任何内容,因为采样率太低且读取间隔不一致。 50Hz 信号每 20 毫秒循环一次,这意味着您需要每 10 毫秒或更长时间采样一次才能获得准确的读数。这些样本在 75-115 毫秒之间变化,这太慢了,无法准确测量信号。
  • @Devunwired 好的,你说的对我有意义。我将尝试增加采样率以再次测试它。但是只要比较 Pi 和 Coral 板的结果,你就可以看出有明显的不同,对吧? (具有相同的频率和占空比)
  • 您无法说出任何有价值的信息,因为不清楚您在波形中的哪个点收集样本(并且 ADC 在切换期间携带残余电压)。你真的需要在示波器上验证一下,看看输出时序是否正确
  • 附带说明一下,我只是将示波器连接到所有三个 PWM 输出,并且它们的信号参数与外围代码无关。
  • @Devunwired 我今天再次对其进行了测试,看来 PWM 确实适用于小型 LED 灯(我可以通过调暗灯光来确认它是否正常工作)。但我仍然无法让它与 SG90 伺服(ee.ic.ac.uk/pcheung/teaching/DE1_EE/stores/sg90_datasheet.pdf)一起工作,我可以使用 Raspberry Pi 轻松控制伺服。我仍然怀疑下拉电阻可能会过度消耗电压。您能分享一下如何在 Mendel Linux 上设置设备树覆盖吗?谢谢。

标签: python linux pwm tpu google-coral


【解决方案1】:

3.3V PWM 操作似乎仍然存在一个悬而未决的问题(与 2.5 不同,它被正确地记为启用上拉的引脚和具有弱下拉的每个引脚之间的分压器)。

设备树覆盖的管脚配置可以在这里找到:https://coral.googlesource.com/linux-imx/+/refs/heads/master/arch/arm64/boot/dts/freescale/fsl-imx8mq-phanbell.dts#171

那里的数字(0x7f)可以用这个位掩码解码:https://coral.googlesource.com/linux-imx/+/refs/heads/master/Documentation/devicetree/bindings/pinctrl/fsl%2Cimx8mq-pinctrl.txt

2.5V 来自设置 PUE(上拉使能),而所有 GPIO 都具有弱下拉。如果这被移除(并且您应该移除 LVTTL 和 ODE 以获得最大驱动强度),IO 将驱动 3.3V。这是一个覆盖层。要启用,请将 pwm.dtbo 复制到 /boot,然后编辑 overlays.txt 以将 pwm 添加到列表中(即 overlays=pwm)

PWM Overlay

【讨论】:

  • 感谢@Micheal Brooks 的解释!我试图为谷歌珊瑚实现覆盖以将 gpio 模式更改为开漏。为此,我复制了您的示例并修改了子节点以及相应的引脚。您可以找到 .dts 文件 here。引导控制台说覆盖已成功加载,但检查它没有工作的引脚。你知道为什么会这样吗?
【解决方案2】:

什么是通道和引脚以及它是如何使用的?

channel 映射到 Linux sysfs 中的驱动芯片(例如 pwmchip0),pin 映射到每个通道上的单独输出。每个通道都有npwm 引脚。

您可以在您的设备上运行pinout 命令以获取有关 40 针连接器上的外围端口及其连接到的 PWM 通道的更多详细信息:

$ pinout
            3.3.V -> 1    2 <- 5V
 I2C2_SDA (i2c-1) -> 3    4 <- 5V
 I2C2_SCL (i2c-1) -> 5    6 <- GND
        UART3_TXD -> 7    8 <- UART1_TX
              GND -> 9   10 <- UART1_RX
        UART3_RXD -> 11  12 <- SAI1_TXC
 GPIO_P13 (gpio6) -> 13  14 <- GND
  PWM3 (pwmchip2) -> 15  16 <- GPIO_P16 (gpio73)
             3.3V -> 17  18 <- GPIO_P18 (gpio138)
        SPI1_MOSI -> 19  20 <- GND
        SPI1_MISO -> 21  22 <- GPIO_P22 (gpio140)
        SPI1_SCLK -> 23  24 <- SPI1_SS0
              GND -> 25  26 <- SPI1_SS1
 I2C3_SDA (i2c-2) -> 27  28 <- I2C3_SCL (i2c-2)
 GPIO_P29 (gpio7) -> 29  30 <- GND
 GPIO_P31 (gpio8) -> 31  32 <- PWM1 (pwmchip0)
  PWM2 (pwmchip1) -> 33  34 <- GND
        SAI1_TXFS -> 35  36 <- GPIO_P36 (gpio141)
GPIO_P37 (gpio77) -> 37  38 <- SAI1_RXD0
              GND -> 39  40 <- SAI1_TXD0

在此板上,每个通道只有一个引脚(cat npwm 返回 1),因此外围的引脚编号始终为零。

为什么我无法让 PWM(1,1) PWM(2,2) 工作?

根据上面的解释,以下是初始化开发板上每个 PWM 的有效外围命令:

  • PWM1 (Pin 32) --> pwm = PWM(0,0)
  • PWM2 (Pin 33) --> pwm = PWM(1,0)
  • PWM3 (引脚 15) --> pwm = PWM(2,0)

【讨论】:

  • 感谢您的补充,但实际上我已经弄清楚了所有这些(您也可以参考我自己的答案)。我想我应该用另一个问题更新问题,我我的答案后面也有说明。
【解决方案3】:

好吧,经过几天的研究,最终再次回答了我自己的问题。这是我发现的:

什么是通道和引脚以及它是如何使用的?

答案: Channel 就像lane 好像PIN 是一个high-way,有的芯片/pin 支持多个channel 有的不支持,你可以算出这个使用以下命令输出(以 EdgeTPU 为例,其他 Linux SOC 应该类似): cd /sys/class/pwm 然后做一个ls 应该显示多个芯片/引脚,如 pwmchip0 pwmchip1 pwmchip2,假设你想知道有多少channel/lanepwmchip0 支持,然后你cd pwmchip0 然后cat npwm 它应该给你是一个数字,对于 EdgeTPU,它显示 1,这意味着 pin PWM1 支持 1 个通道/通道。您可以对pwmchip1 pwmchip2 ... pwmchip# 执行相同的操作 (仅供参考,EdgeTPU 的所有引脚仅支持 1 个通道)

为什么我无法让 PWM(1,1) PWM(2,2) 工作?

这是有趣的部分,我对此有太多话要说。

简短回答: THEIR DOCUMENT IS WRONG. it should be PWM(Pin,Channel)

Long Anser:在 here 中,它说您应该将 PWM 初始化为 PWM(Channel, Pin),但通过查看它的实现,它应该是 PWM(Pin, Channel) 根据code。和另一个 PWM 独立模块 here 的很好的例子(强烈建议任何 EdgeTPU 用户使用这个而不是 python-periphery)。 我有PR 来更新他们的文档,但我想说,他们的 PWM 绝对没有经过任何测试。否则,误导性信息现在应该已经注意到了。 (TBH,这个项目好像死了,一年多没有更新,甚至不确定我的 PR 是否会被合并。未来的工作:如果我的文档更正 PR 获得批准,我将努力将独立的 PWM 模块 PR 到python 外围库)

那么,在让 PWM 工作之后,一切都按预期工作了吗? 代码?

回答:很遗憾不是请查看我更新后的问题。

【讨论】:

  • 请避免在答案中提出其他问题,因为无法回答这些问题。如果此处的问题与原始问题相关,您可以编辑问题本身。否则,请考虑提出第二个问题以解决新问题。
猜你喜欢
  • 1970-01-01
  • 2018-05-03
  • 2017-02-01
  • 1970-01-01
  • 2021-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多