Arduino UNO R4 WiFi 是 Arduino 經典微控制器系列的最新成員。除了強大的 Renesas RA4M1 微控制器外,這款新開發板還配備了 12 x 8 的 LED 顯示矩陣。或許您已經看過 LED 矩陣上顯示的標誌性心形符號。這是每個 Arduino UNO R4 WiFi 的預設程序,如圖 1 所示。
Arduino UNO R4 WiFi 的操作文件詳盡,並提供使用者友善的 API。然而,我們有機會從硬體層面探索 LED 顯示矩陣背後的工作原理。這是一個深入了解微控制器 I/O 和多路復用技術的絕佳機會。
如何用 11 條控制線控制 96 個 LED?
答案很簡單,可以使用一種名為 Charlieplexing 的技術,據說以其發明者 Charles Allen 的名字命名。此技術依賴於微控制器輸出引腳的三態特性。每個引腳可以配置為:
- 輸出:邏輯低
- 輸出:邏輯高
- 輸入:高阻抗
圖 2 中透過一系列開關演示了此操作。例如,微控制器的三態開關(例如 TRI_0)決定相應引腳是輸入還是輸出。當開關斷開時,每個微控制器的 I/O 引腳懸空(高阻抗),允許外部電路確定電壓。當開關閉合時,ROW_0 驅動器決定引腳的輸出電壓。點擊此超鏈結,查看基於圖 2 的交互式 MultisimLive 仿真。作為挑戰,請嘗試按順序啟動 LED1 至 LED6。
關於圖 2,我們看到 LED1 被啟動。當 ROW_0 拉電流,ROW_1 灌電流時,就會發生這種情況。我們可以透過同時切換 ROW_0 和 ROW_1 的邏輯來啟動 LED2。完成後,ROW_1 將拉動電流,ROW_0 將吸電流。
請注意,ROW_2 配置為高阻抗輸入。這一點很重要,因為它可以防止多個 LED 同時啟動。例如,如圖 2 所示,如果 TRI_2 被啟動:
- ROW_2 高電平:LED1 和 LED6 同時激活
- ROW_2 低電平:LED1 和 LED3 同時激活
技術提示:對於電子學新手來說,「 拉電流 (Source Current)」和「 灌電流 (Sink Current)」這兩個術語可能會令人困惑。這是一個參考系問題,部分原因在於物理學史。它始於18世紀50年代本傑明·富蘭克林 (Benjamin Franklin) 的實驗,他提出了電流從電源正極流向負極的理論。近150年後,J.J. 湯姆森 (J.J. Thomson) 於1897年發現了電子。從那時起,我們一直用富蘭克林的傳統流動(正極流向負極)和電子流動(負極流向正極)來思考電學。
您可能會認為這是一個已經解決的問題。然而,即使在今天,您也可以選擇採用其中一種約定俗成的教科書。仔細觀察就會發現,所有電流向量都被反轉了,所有右手定則都被左手定則取代,反之亦然。
再次強調,「拉電流」和「灌電流」這兩個術語取決於您的參考系。為了清晰起見,我們將遵循傳統流動,即正極電源端「拉」電流,負極電源端「灌」電流。在圖 2 中,5 VDC 是電源,地是接收器。
Arduino 程式碼範例
我們可以使用 Arduino 程式碼來更好地理解圖 2 的操作。為方便起見,假設 LED 矩陣連接到分別對應 ROW_0、ROW_1 和 ROW_2 的 D0、D1 和 D2 接腳。如程式碼所示,LED1 在以下情況下啟動:
pinMode(D0, OUTPUT); // Tri state configuration
pinMode(D1, OUTPUT);
pinMode(D2, INPUT);
digitalWrite(D0, HIGH); // Logic assertion when the Tri state buffer is active
digitalWrite(D1, LOW);
再舉一個例子,假設我們希望啟動 LED5:
pinMode(D0, INPUT);
pinMode(D1, OUTPUT);
pinMode(D2, OUTPUT);
digitalWrite(D1, HIGH);
digitalWrite(D2, LOW);
多工技術 Multiplexing
到目前為止,我們關注的是單一 LED 的控制。實際上,我們期望同時點亮多個 LED。例如,假設我們希望同時啟動 LED1 和 LED5。根據圖 2 的原理圖,這無法直接實現。如果 LED1 亮起,仔細檢查圖 2 會發現,其他可能的 LED 僅有 LED3 或 LED6。事實上,如果我們仔細研究所有 8 種可能性,就會發現在任何給定的開關狀態下,只有 2 個 LED 可以同時點亮。
解決方案是多工 LED。
使用這種多工技術,在任何給定時間只有一個 LED 處於活動狀態。我們快速切換 LED,每個 LED 都會短暫亮起。例如,要啟動 LED1 和 LED5,我們可以交替使用上一節中的程式碼片段。如果循環序列以高於約 30Hz 的頻率完成,人眼就能觀察到兩個 LED 同時亮起。這種視覺暫留(閃爍融合)會讓人產生LED同時亮起的錯覺。
這種技術的一個顯著問題是 LED 亮度。回想一下,多工是一個時分過程,每個 LED 都被分配一個時隙。在我們的雙 LED 問題中,每個 LED 的亮時間為 50%。而圖2 所示的六 LED 問題,每個 LED 的亮時間為 16%。因此,亮時間為 50% 的 LED 會比亮時間為 16% 的 LED 更亮。請參閱本文,深入了解 LED 多工技術,並分析其亮度、時間和脈衝電流。
Arduino UNO R4 上的 Charlieplexing
粗略查看 Arduino UNO R4 WiFi 數據手冊,我們發現 LED 顯示矩陣由 11 個微控制器 I/O 引腳驅動。數據手冊還展示了一個互補 LED 矩陣,其中每對 LED 都配置為陽極對陰極和陰極對陽極。圖 3 中包含了一小部分原理圖。請注意,這與圖 2 的範例幾乎完全相同。 Charlieplexing 的運作方式與上一節中所描述的相同。
如何提高 Arduino UNO R4 WiFi 顯示器的亮度?
簡單來說,LED 亮度受 Charlieplex 方法的限制,而 Charlieplex 方法又受微控制器電流有限的 I/O 接腳的限制。我們還必須考慮修改易於使用的 LED 矩陣庫所帶來的開銷。
顯示幕已經達到了預期亮度。
但是,您可以添加紅色透鏡來增加表觀亮度。例如,紅色半透明的 Hammond 1591STRD 既可以用作外殼,也可以用作透鏡。您可以在影片 1 中查看效果。
影片 1:Hammond 1591STRD 外殼用作 Arduino UNO R4 紅色鏡頭的視頻
Charlieplex 方法有哪些限制?
為了更好地理解 Arduino UNO R4 的局限性,我們需要考慮 Charlieplex 方法的限制。
-
回想一下,Charlieplexing 是一種用於控制多個 LED 的經濟高效的方法。驅動電源直接來自微控制器,無需借助行和列驅動器。因此,亮度(LED 電流)與微控制器驅動引腳的「強度」直接相關。這是一個硬性的物理限制,如果不從根本上改變顯示硬件,就無法改變。
-
單一 LED 的亮度由開啟時間(佔空比)決定。 12 x 8 的顯示器上有 96 個 LED,每個 LED 的開啟時間約為 1%。每個 LED 必須輪流發光,但只能持續片刻。這是另一個無法改變的物理限制。如果我們希望整個顯示器的亮度保持一致,這一點尤其重要。例如,如果只有兩個像素處於活動狀態,我們可以將時間分配給它們。但是,隨著更多 LED 被激活,顯示器的亮度會降低。
總結來說,提高亮度的唯一方法是重新設計硬髒,添加行和列驅動器,或降低預期並減少陣列中的 LED 數量。雖然這不是一個線性過程,但一般來說,將 LED 總數減半會使感知亮度翻倍,因為現在每個 LED 的活化時間可能會加倍。
技術提示:對於像 Renesas R7FA4M1AB3CFM#AA0 這樣的複雜微控制器,單一接腳電流並非單一規格。不過,一般來說,RA4M1 可以處理每個引腳 8mA 的電流,所有引腳合計電流限制為 60mA。請查閱資料手冊,因為其中還有許多其他注意事項和規定。
如何直接從 Arduino UNO R4 LED 矩陣存取 LED?
通常情況下,您會使用 Arduino 庫來控制 LED 顯示器。但是,由於我們已經深入研究了相關知識,因此我們可以使用 Renesas Flexible Software Package (FSP) 存取單一 RA4M1 特殊功能暫存器 (SFR)。這項技術在未來的實驗中可能非常有用,尤其是當我們需要直接連接埠存取所需的速度時。
技術提示:Renesas Flexible Software Package (FSP) 是硬體抽象層 (HAL)。它在許多方面與 Arduino 語言類似,因為它們都旨在隱藏/簡化底層硬體,從而提高程式碼的可移植性。
您可能有興趣知道,Arduino UNO R4 Minima 和 WiFi 的實作是基於 Renesas FSP 基礎構建的。
仔細查看 Arduino UNO R4 WiFi 原理圖,可以發現:
- ROW_0 對應 P205(連接埠 2 腳位 5)
- ROW_1 對應 P012(連接埠 0 腳位 12)
- ROW_2 對應 P013(連接埠 0 腳位 13)
例如,要點亮 LED 1,我們可以使用以下這段程式碼:
R_IOPORT_PinCfg(NULL, ROW_0, IOPORT_CFG_PORT_DIRECTION_OUTPUT);
R_IOPORT_PinCfg(NULL, ROW_1, IOPORT_CFG_PORT_DIRECTION_OUTPUT);
R_IOPORT_PinCfg(NULL, ROW_2, IOPORT_CFG_PORT_DIRECTION_INPUT);
// Assume all other row drivers are inputs (high impedance)
R_IOPORT_PinWrite(&g_ioport_ctrl, ROW_0, BSP_IO_LEVEL_HIGH);
R_IOPORT_PinWrite(&g_ioport_ctrl, ROW_1, BSP_IO_LEVEL_LOW);
要開啟 LED5,我們可以使用以下這段程式碼:
R_IOPORT_PinCfg(NULL, ROW_0, IOPORT_CFG_PORT_DIRECTION_INPUT);
R_IOPORT_PinCfg(NULL, ROW_1, IOPORT_CFG_PORT_DIRECTION_OUTPUT);
R_IOPORT_PinCfg(NULL, ROW_2, IOPORT_CFG_PORT_DIRECTION_OUTPUT);
R_IOPORT_PinWrite(&g_ioport_ctrl, ROW_1, BSP_IO_LEVEL_HIGH);
R_IOPORT_PinWrite(&g_ioport_ctrl, ROW_2, BSP_IO_LEVEL_LOW);
然後我們可以使用以下程式碼在 LED0 和 LED5 之間進行多工:
#define ROW_0 BSP_IO_PORT_02_PIN_05
#define ROW_1 BSP_IO_PORT_00_PIN_12
#define ROW_2 BSP_IO_PORT_00_PIN_13
void setup() {
;
}
void loop() {
R_IOPORT_PinCfg(NULL, ROW_0, IOPORT_CFG_PORT_DIRECTION_OUTPUT);
R_IOPORT_PinCfg(NULL, ROW_1, IOPORT_CFG_PORT_DIRECTION_OUTPUT);
R_IOPORT_PinCfg(NULL, ROW_2, IOPORT_CFG_PORT_DIRECTION_INPUT);
R_IOPORT_PinWrite(&g_ioport_ctrl, ROW_0, BSP_IO_LEVEL_HIGH);
R_IOPORT_PinWrite(&g_ioport_ctrl, ROW_1, BSP_IO_LEVEL_LOW);
delay(20);
R_IOPORT_PinCfg(NULL, ROW_0, IOPORT_CFG_PORT_DIRECTION_INPUT);
R_IOPORT_PinCfg(NULL, ROW_1, IOPORT_CFG_PORT_DIRECTION_OUTPUT);
R_IOPORT_PinCfg(NULL, ROW_2, IOPORT_CFG_PORT_DIRECTION_OUTPUT);
R_IOPORT_PinWrite(&g_ioport_ctrl, ROW_1, BSP_IO_LEVEL_HIGH);
R_IOPORT_PinWrite(&g_ioport_ctrl, ROW_2, BSP_IO_LEVEL_LOW);
delay(20);
}
程式碼運作時,LED 會閃爍。當延遲減少到 10ms 左右時,閃爍現象就會消失。
結論
Arduino UNO R4 WiFi 包含一個 12 x 8 的 LED 顯示矩陣,用「趣味」來形容再適合不過了! Arduino 一如既往地提供了一個易於使用的庫,讓您可以在幾分鐘內配置和使用顯示器。
就個人而言,非常欣賞 UNO R4 WiFi 的硬體設計,因為它提供了一個學習 Charlieplexing 技術的機會。這款硬體應用程式提供了一個了解微控制器三態輸出、多工技術以及 Renesas FSP 等工具的視窗。這些功能共同作用,有助於加深對 LED 電流和脈衝操作的理解。
歡迎您在下方留言提問和評論。
最後,如果您學到了什麼,請按讚。
實用超鏈結
請點擊以下超鏈結以取得相關實用資訊: