星期四, 6月 29, 2017

解決 PCM 播放與 Servo 程式庫衝突的問題

由於同事在製作使用伺服馬達的六腳機器人專案, 想要讓機器人遇到障礙物時可以用喇叭播放驚恐的聲音, 因此就利用了善心人士寫好的 PCM 播放程式庫, 不過一用才知道, 原來 Servo 程式庫和 PCM 程式庫都用到了 Arduino UNO 上的 Timer, 因此無法共存。研究了一下發現, Servo 會用到 Timer1 產生中斷送出給伺服馬達的方波訊號, 而 PCM 程式庫為了播放 8KHz 的聲音, 同時用了 Timer1 和 Timer2, Timer1 負責每秒產生 8000 次中斷, 每次中斷切換下一個 PCM 採樣值, 而 Timer2 則負責將 Sample 資料以 PWM 方式送出給喇叭發聲。兩個程式庫都用到了 Timer1, 如果混在一起用, 連編譯都不會過。即使編譯會過, 程式也無法正常運作, 因為兩個程式所需要的 Timer1 頻率根本不一樣。

為了解決問題, 必須有一方讓出 Timer1 給對方使用。討論之後發現, 機器人遇到障礙時可發出聲音後再繼續動作, 並不一定要邊發出聲音邊動作, 所以決定修改 PCM 程式庫, 把 Timer1 讓出來, 改成用很單純的迴圈搭配 delayMicroseconds(), 每 125μs 切換 PCM 採樣值發聲, 問題就解決了。修改過的程式庫可在這裡下載, 如果您也有一樣的困擾, 也許可以試用看看。

有關 Timer, 可參考這一篇文章, 有簡明易懂的說明, 並且整理了常用的程式庫所佔用的 Timer, 如果你的程式遇到怪現象, 例如使用了 tone() 函式後, 3 和 11 腳的 PWM 就失效, 很可能就是 Timer 的問題。

沒有留言: