哪些 Arduino Nano Every I/O 接腳可用於 PWM 輸出?
Arduino Nano Every 設計用於五個 PWM 輸出,使用接腳 D3、D5、D6、D9 和 D10。 PWM 訊號使用 analogWrite() 函數產生。例如,指令 analogWrite(3, 64); 將 Arduino 數位輸出接腳 D3 設定為產生佔空比為 25% 的 PWM 訊號。
下表列出了 ATmega4809 的實體連接埠。 Arduino 引腳名稱和相關的硬體定時器在我們繼續進行逆向工程時至關重要:
- PB0 (D9) - TCA
- PB1 (D10) - TCA
- PB2 (D5) - TCA
- PF4 (D6) - TCB
- PF5 (D3) - TCB
本工程概述假設您對 Arduino PWM 有所了解,並且正在尋找更改預設 PWM 頻率的方法。有關 Arduino 和占空比的更多信息,請參閱此 Arduino 教程。
圖 1:Digilent Analog Discovery 作為邏輯分析儀運行,用於同時測量 Arduino Nano Every 的所有 PWM 接腳。
Arduino Nano Every 的預設 PWM 頻率是多少?
Arduino Nano Every 的預設 PWM 頻率為 976.5625Hz。這個頻率可能看起來有點奇怪,但它直接來自 16 MHz 振盪器:
16 MHz ÷ 64 ÷ 256 = 976.5625 Hz
其中,除以 64 是 TCA0_CTRLA 暫存器的配置設置,除以 256 是 8-bit PWM 的自然除法。在這種情況下,PWM 將 62,500Hz 時脈(16 MHz ÷ 64)細分為 256 個 time slot 時槽。
為什麼要更改 PWM 頻率?
Arduino 預設的 976.5625Hz 頻率適用於許多簡單的項目,例如 LED 調光和小型馬達的轉速控制。然而,當用於控制高功率馬達等設備時,此頻率可能會產生令人不安的嘯叫聲。在高於人類聽覺極限(約 20 kHz)的頻率下工作可以消除噪音污染。
此頻率可能與其他系統不相容。例如,在以後的文章中,我將示範如何使用 Arduino 控制設計為 25 kHz PWM 控制的變速風扇。 976.5625Hz 的 PWM 與 25kHz 相差甚遠。正如本文將要演示的那樣,我們可以產生 32kHz 的 PWM。這更接近所需的 25kHz,但仍有一段距離。
另一個潛在Arduino PWM 探索領域是開關電源。雖然 976.5625Hz 訊號可能有效,但它會產生令人不適的噪聲,而且成本高昂且效率低。這些開關電源通常以高頻率工作,以減小濾波器件的尺寸。
如何對 Arduino 軟體進行逆向工程?
首先,讓我們來認識一下 Arduino 及其相關社群的傑出貢獻。他們共同為整整一代學習者建構了一個起點。事實上,我敢說你很難找到一個沒有寫過 Arduino 程式的電氣工程師、技術專家或技技術人員。
Arduino 的成功很大程度上歸功於其硬體抽象。團隊將諸如 PWM 之類的複雜任務簡化為一個簡單的 analogWrite() 函數。這對學習者很有幫助,但當我們試圖對 Arduino Nano 的 PWM 函數進行逆向工程時,情況就不那麼好了。
假設我們希望繼續使用 Arduino 的抽象,我們可以深入研究 Arduino 程式碼庫,或配置微控制器並從相關暫存器中提取值。雖然探索程式碼是一項很好的學術練習,但由於 Arduino 程式碼包含多層抽象,允許相同的命令(例如 analogWrite())在 Arduino 產品線的所有成員上運行,因此這令人難以承受。另一方面,探究 ATmega4809 資料手冊並非易事。
在所有情況下,我們都需要謹慎行事,因為這可能會損壞相關的 Arduino 功能。例如,我們可以透過更改 TCA(16 位元定時器/計數器 A 型)週邊裝置中的 CTRLA 暫存器來輕鬆更改 PWM 頻率。這解決了一個問題,但卻引發了另一個問題,因為它會破壞其他 Arduino 功能。例如,我們可以將 PWM 頻率提高 32 倍,但不幸的是,millis() 追蹤的時間也會改變 32 倍。這充其量只是帶來了不便。由於命名函數無法執行其預期功能,這也可能引發 bug。
我們是如何確定除以 64 的?
完整的解釋需要深入研究 ATmega4809 資料手冊,並詳細研究底層定時器週邊。為了簡潔起見,我們將識別一些訊號並描述它們如何影響 PWM。
我們從 16 MHz 振盪器開始,它是微控制器中的主時脈。週邊時鐘 (CLK_PER) 是連結中的下一個環節。它源自於 16MHz 振盪器,並用作所有周邊的參考。
ATmega4809 遵循預分頻器的傳統,如圖 2 所示。這允許數位時脈訊號進行 2 到 64 倍的數位分頻。如前所述,我們可以深入研究 Arduino 程式碼來確定設置,或者我們可以執行以下 Arduino 程式碼行來確定運行微控制器中的實際設置。
Serial.print("MCLKCTRLA = "); Serial.println(CLKCTRL.MCLKCTRLB, BIN);
圖 2:16MHz 時脈可以透過預分頻器分頻來產生週邊時鐘。
結果回傳為 0。然後,我們在規格書中尋找暫存器以確定相應的設定。最重要的 bit 是 bit 0,它告訴我們預分頻器已停用,因此 CLK_PER = CLK_MAIN。
我們的下一站是 TCA 定時器外設,特別是 CTRLA 暫存器,它標識了 TCA 模組本身的預分頻器設定。
Serial.print("TCA0_CTRLA = "); Serial.println(TCA0.SINGLE.CTRLA, BIN);
結果是二進制 1011。查看規格書後,我們發現前導 101 表示除以 64。 LSB 表示週邊已啟用。這就解決了 TCA 的問題,TCA 是起始表中標識的前三個 PWM 輸出。
最後一步是將 TCB 輸出與 TCA 關聯起來。跳過幾個步驟,我們來看看 CTRLA 暫存器。
Serial.print("TCB0_CTRLA = "); Serial.println(TCB0_CTRLA, BIN);
結果為二進位 101。規格書顯示 TCB 週邊裝置使用來自 TCA0 的 CLK_TCA。因此,更改 A 中的預分頻器將更改 B 的操作,但反之則不會。
修改定時器/計數器 A 時會發生哪些問題?
再次強調,Arduino 對硬體進行了抽象,使其更易於使用。如前所述,修改/配置底層硬體可能會破壞 Arduino 的功能。
無需解釋,我們只需指出修改定時器 A 會破壞 millis() 函數。它很可能會破壞其他基於時間的函數。然而,修改定時器 B 似乎不會破壞 millis()。
如何每次都提高 Arduino Nano 的 PWM 頻率?
可透過設定 ATmega4809 定時器 A 和 B 中的時脈預分頻器,或變更主振盪器的頻率/預分頻器來修改 PWM 頻率。然而,許多此類變更會破壞 Arduino 的功能。
本文的其餘部分將介紹一種更改與 TCB 關聯的兩個 PWM 輸出的方法。三個 TCA PWM 輸出保持原來的 976.5625Hz,millis() 函數保持不變。請注意,我們尚未進行完整的功能測試。 Arduino 的其他功能完全有可能受到影響。如果您發現任何功能損壞,請在下方留言。
鑑於這些限制,我們只能對 TCB PWM 頻率進行小幅調整。我們可以將 CTRLA 暫存器變更為使用 CLK_PER 或 CLK_PER/2,分別獲得 31.25kHz 和 62.5kHz 的 PWM 頻率。我們只需進行適當的設定即可。
對於 32.25 kHz 的 8-bit PWM,請使用:
TCB0_CTRLA = 0b00000011; // pin D6
TCB1_CTRLA = 0b00000011; // pin D3
對於 62.5 kHz 8-bit PWM 使用:
TCB0_CTRLA = 0b00000001; // pin D6
TCB1_CTRLA = 0b00000001; // pin D3
結果如圖 3 所示,其中使用 Digilent Analog Discovery 作為邏輯分析儀。從上到下,PWM 訊號與 Arduino 接腳 D3、D5、D6、D10 和 D11 相關聯。請注意,所有 PWM 訊號的佔空比均設定為 25%。
圖 3:Digilent Analog Discovery 螢幕截圖,顯示兩個 TCB PWM 訊號的頻率分別為 31.25 和 62.5kHz,而三個 TCA PWM 訊號的頻率為 976.5625Hz。所有訊號的佔空比均為 25%。
後續步驟
ATmega4809 能夠透過 TCA 提供高解析度 16-bit PWM 訊號。您可能已經從本文的主線猜到了,配置週邊通常會導致 Arduino 抽象概念的遺失和功能中斷。
或許是時候放下 Arduino 抽象概念,學習使用 MPLAB 等工具進行裸機程式設計了。這是一項值得投入的時間,因為您將學習如何釋放微控制器的全部潛力,包括最新高效能產品令人眼花撩亂的複雜性。
結語
本文為學習微控制器提供了絕佳的機會。我們從最底層開始,使用 Arduino 抽象技術深入研究了 ATmega4809 的定時器週邊。我們了解了 PWM 產生器,並對 Arduino 抽象技術有了更深入的理解。
關於 PWM 和頻率提升,我們了解到,與 TCB 相關的 PWM 訊號可以提升到 31kHz 和 64kHz,而不會破壞 millis() 等函數。同時,我們也承認其他尚未測試的函數可能會效能下降。如果您發現任何損壞的函數,請在下方留言。此外,如果可以,請留下完整的程式碼清單以幫助他人。