PWM,Pulse Width Modulation,以數位方式控制高低電位週期比例來達到模擬類比電壓的效果,比方說控制馬達速度、LED燈亮度...
值得一提的是,因為是模擬的方式所以PWM訊號頻率其實也會出現在輸出訊號的頻譜裏,當然也要輸出裝置頻寬夠高才能夠被察覺.
樹莓派身為一塊萬用開發版當然有辦法輸出PWM,目前查到有下面幾個方法:
- RPi.GPIO
- 指令下達方式:Python
- PWM生成方式:軟體模擬
- 安裝:
- #sudo apt-get install python-dev python-rpi.gpio
- 用法:
- #sudo python #進入Python
- >>import RPi.GPIO as GPIO
- >>GPIO.setmode(GPIO.BCM)
- >>GPIO.setup(18, GPIO.OUT) #設定GPIO18為輸出腳
- >>pwm = GPIO.PWM(18, 500) #建立PWM實例,在GPIO18輸出,頻率為500Hz
- >>pwm.start(100) #開始輸出DUTY=100%的脈波
- 心得:
- 用在伺服馬達(Servo)上會感覺到顫振,確實是用軟體方式來輸出,持續輸出脈寬的重複性不佳,大概只適合做LED燈控制等人機應用.
- 軟體輸出方式大概是以系統內建計時器,去計時控制輸出腳位為高位/低位,由於Linux並非即時系統,各行程(process)無法保證被定時呼喚,因此即便系統計時器是可靠的,在上位做控制的行程也沒辦法總是在計時到達的當下去處理.
- RPIO
- 指令下達方式:Python
- PWM生成方式:半軟體模擬?(文件上寫著透過DMA通道,不太清楚背後機制)
- 安裝:
- #sudo apt-get install python-setuptools
- #sudo easy_install -U RPIO
- 用法:
- #sudo python #進Python
- >> from RPIO import PWM
- >> servo = PWM.Servo() #建立一個Servo實例,預設週期為50Hz
- >> servo.set_servo(18,1500) #在GPIO18上持續輸出脈寬為1500us的脈波
- >> servo.set_servo(19,10000) #在GPIO19上持續輸出脈寬為10000us的脈波
- 心得:
- 發現如果將其中一隻Pin輸出關閉,所有輸出都會被關閉,不知道是不是BUG?
- 可以多通道輸出(但不曉得通道代表什麼意思),比方說
- >> servo0 = PWM.Servo(0)
- >> servo1 = PWM.Servo(1)
- 如此就建立了兩個Servo物件對應到不同的DMA通道,但操作起來仍發現會相互干擾
- 顫陣比GPIO小,但仍能感受到.
- pigpio
- 指令下達方式:pipe 、c-interface、python
- PWM生成方式:軟體模擬(p指令)、硬體輸出(hp指令)
- #git clone https://github.com/joan2937/pigpio #跟上最新版
- 用法(pipe方式):
- #sudo pigpiod #喚起掌管輸出入的專用daemon
- #pigs p 19 255 #在GPIO19上輸出DUTY 100%的PWM信號(軟體模擬輸出)
- #pigs hp 18 100 500000#在GPIO18上輸出頻率為100Hz DUTY為50%的PWM信號(硬體直接輸出)
- 心得:
- "硬"PWM,直接用樹莓派BCM2835晶片內建兩個底層PWM輸出單元生成PWM信號,直接以IC輸出信號重複性一定是最穩定的,也就是脈寬不會有忽大忽小的問題
- pigpio只是作為寫入晶片上特定registor的API罷了
- BCM2835只有兩個PWM通道(Channel),甚至在Pi2上只有一隻引腳被接到介面IO上,而Raspberry PI B+則有GPIO18,GPIO19可用.
- 操作起來真的是顫陣最低的(滿意)!
- 另外要說pigpio的shell指令很豐富,初期拿來測試硬體相當順手,文件也建立的很完整(滿意)!
- 各型Raspberry PI GPIO表:http://elinux.org/RPi_BCM2835_GPIOs
從BCM2835文件可以發現這塊晶片頂多只能輸出兩個PWM信號,真要再多的話就要以通訊方式(I2C UART)送出命令透過PWM IC代為輸出穩定的PWM信號了,
類似透過這樣的晶片
後記:
即便是用了Hardware PWM,功率電路之間的相互干擾也是另一令人頭痛的因素....尚待努力
其他參考:
BCM2835硬體Sheet