树莓派的硬件pwm
好久没写博客了,来水一篇
最近有个项目需要用树莓派来产生pwm信号来控制一个舵机。
原本使用的是Rpi.GPIO中提供的软件pwm的方式来产生信号,但是遇到两个问题
问题一是
import PRi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setup(7,GPIO.OUT)
p = GPIO.PWM(7,330)
p.start(50)
执行到以上还一切正常,虽然由于是软件pwm,所以频率和占空比在示波器上可以看到并不是特别精准,不过问题不大。但是,如果想停止发送pwm信号,再重新发送
p.stop()
p.start(50)
此时,就会发现信号完全乱掉了,虽然还是pwm波,但是频率变成了800k-900k的样子,非常奇怪。
我又试验了下,发现在start以后,需要
del p
p = GPIO.PWM(7,330)
p.start(50)
这样才能正常的发送信号。我记得以前用的时候是可以直接stop然后再start的。不知道是现在GPIO的版本改了还是因为哪里的问题?
遇到的第二个问题就是软件pwm不够精准的问题。因为控制的是360度舵机,而且没有编码盘,对占空比非常敏感。理论上给49.5%的占空比就应该静止不转动,但实际上发现给47.5%占空比的时候才会比较静止,但不是很稳定,还是会很缓慢的正传或者反转。考虑到项目需要舵机长时间(7天)保持固定位置,因此软件pwm是必然无法使用的了。
我以前控制树莓怕3B+的时候有用wiringPi来用树莓派产生pwm波,主要是控制gpio pwmc xxx, gpio pwmr xxx, gpio pwm 1 xxx这三条指令。但是我在树莓派4B上测试发现似乎走不通,不知道是不是因为wiringPi已经不再维护了的原因。
经过寻找,终于找到了个比较方便的用树莓派4B产生硬件pwm的方法。
https://github.com/jdimpson/syspwm/blob/master/syspwm.py
虽然是python2写的,但是把print语句改一下就和python3没区别。
用这个代码,设置下频率和占空比就好了,还省去了之前其对时钟频率的奇奇怪怪的计算。要注意的是这个代码里面的占空比不是百分比,而是指正脉宽的毫秒数。
可以看到这个代码基本就是对"/sys/class/pwm/pwmchip0"下文件的一些读写操作,和/proc的逻辑差不多,通过文件类型的接口来控制外设(硬件)
更多的参考资料见:
https://jumpnowtek.com/rpi/Using-the-Raspberry-Pi-Hardware-PWM-timers.html
https://github.com/raspberrypi/linux/blob/rpi-4.4.y/arch/arm/boot/dts/overlays/README