以 Arduino 實做多接腳軟體 PWM === ![](https://i.imgur.com/F9gnJsY.png) 網路上不乏軟體 PWM 的教學, 不過當中大部分都是使用 Delay 函數實現, 即便使用 [TimerOne](https://github.com/PaulStoffregen/TimerOne) 中的 `setPwmDuty` 函數也僅支援單一腳位。 「多接腳軟體PWM」這個 feature 原本是用於處理某個專案產生的, 不過似乎很少人這樣處理,那就把這個功能從原專案中切出來分享。 其實過程中也有詢問過前輩,得到的建議是直接使用硬體 PWM 的晶片或模組處理, 不過懶得再去買一顆模組回來,再加上土砲魂作祟:想要嘗試用軟體技術處理硬體極限。 Business Logic --- 算法的思路其實很簡單,每一個腳位都有不同的工作週期, 在週期開始的把所有腳位打開,接著依照各自的工作週期, 在特定的時間依序將腳位關閉,如此重複就能實現 PWM 了。 比如說現在六個接腳都有各自的工作週期: ![](https://i.imgur.com/Tn0GCgh.png) 把這些並行的工作想成一連串的單一執行緒工作: ![](https://i.imgur.com/Nqu5NiM.png) Timer 中斷 --- 既然 $t(0)$, $t(1)$, $t(2)$, $t(3)$ ... 的工作確定了, 接下來就是讓單晶片在該工作的時間工作就好了, 我是使用一個 TimerOne 的函式庫 ,並且在每次中斷時設定下一次中斷時間。 ```c++ void doPwm(){ uint32_t delay = pwmManager.doDate(); Timer1.initialize(delay); Timer1.attachInterrupt(doPwm); } ``` 問題 --- 即便單元測試覆蓋了 17 個測試項目,但是實際上機時卻工作不太順暢, 還會發生當機的情況,後來發現兩次中斷點太近就會發生問題, 於是有兩個改進方向: - 增加週期 - 降低解析度 程式碼 --- [https://github.com/FlySkyPie/arduino-software-pwm](https://github.com/FlySkyPie/arduino-software-pwm) Reference --- 某位實現 16 channel 軟體 PWM 的大神,不過程式碼太韌體我看不懂: https://forum.43oh.com/topic/1723-16-channel-software-pwm-using-a-single-timer/ ###### tags: `development note` `2019-10-25` ###### tags: `arduino` `pwm`