今天遇到有人想要同時控制蜂鳴器發聲與伺服馬達轉動, 但是卻發現只要使用蜂鳴器發聲後, 伺服馬達就失控, 可以參考以下的程式:
from machine import Pin,PWM
import time
# 伺服馬達接 D1, 頻率 50Hz
servo = PWM(Pin(5), freq=50)
servo.duty(100) # 轉到角度 A
time.sleep(1) # 等待 1 秒
# 無緣蜂鳴器接 D8
buzzer = PWM(Pin(15))
buzzer.duty(0)
servo.duty(30) # 轉到角度 B
print('開門')
time.sleep(1) # 等待 1 秒
buzzer.freq(261) # 設定聲音頻率
buzzer.duty(512) # 設定音量
time.sleep(0.5) # 持續播放半秒
buzzer.duty(0) # 停止播放
time.sleep(1) # 等待 1 秒
servo.duty(100) # 轉回角度 A
print('關門')
播完聲音後, 伺服馬達就轉不回來了, 這主要是因為 PWM 的頻率是所有腳位共用, 播完聲音後頻率已經被改為 261Hz, 不再是控制伺服馬達所需要的 50Hz, 因此無法將馬達轉回來。要解決這問題, 最陽春的做法就是在控制伺服馬達前, 重新設定 PWM 的頻率:
from machine import Pin,PWM
import time
# 伺服馬達接 D1, 頻率 50Hz
servo = PWM(Pin(5), freq=50)
servo.duty(100) # 轉到角度 A
time.sleep(1) # 等待 1 秒
# 無緣蜂鳴器接 D8
buzzer = PWM(Pin(15))
buzzer.duty(0)
servo.duty(30) # 轉到角度 B
print('開門')
time.sleep(1) # 等待 1 秒
buzzer.freq(261) # 設定聲音頻率
buzzer.duty(512) # 設定音量
time.sleep(0.5) # 持續播放半秒
buzzer.duty(0) # 停止播放
time.sleep(1) # 等待 1 秒
servo.freq(50) # 重新設定頻率
servo.duty(100) # 轉回角度 A
print('關門')
這樣就轉得回來了。不過這樣的作法在播放聲音的時候, 伺服馬達可能還是會受到頻率變換的影響, 導致偶有抖動的狀況, 最根本的做法就是在控制完 PWM 訊號的裝置後, 卸除 PWM 功能:
from machine import Pin,PWM
import time
def set_PWM(
p, # 腳位編號
d, # 工作週期
f, # 頻率
t, # 持續時間
):
pwm = PWM(Pin(p), freq=f) # 建立 PWM 物件
pwm.duty(d) # 設定工作週期
time.sleep(t) # 等待持續時間
pwm.deinit() # 卸除 PWM
# 伺服馬達接 D1, 轉到角度 A, 1 秒
set_PWM(5, 100, 50, 1)
# 伺服馬達接 D1, 轉到角度 B, 1 秒
print('開門')
set_PWM(5, 30, 50, 1)
# 無緣蜂鳴器接 D8, 播聲音 0.5 秒
set_PWM(15, 512, 261, 0.5)
time.sleep(1) # 等待 1 秒
print('關門')
# 伺服馬達接 D1, 轉到角度 A, 1 秒
set_PWM(5, 100, 50, 1)
如果是使用 ESP32, 那也可以參考使用 esp32.RMT 設計不同頻率的 PWM讓不同腳位以不同的頻率進行 PWM。
Top comments (0)