2021年1月底的時(shí)候,樹莓派基金會發(fā)布了一個(gè)重磅消息,推出了進(jìn)軍微控制器領(lǐng)域的樹莓派Pico。
功能強(qiáng)勁,價(jià)格便宜的特性讓Pico受到了全世界創(chuàng)客們的關(guān)注,這篇文章就來給大家介紹一下Pico這個(gè)小玩意兒。
文章原文來自DroneBot Workshop,負(fù)責(zé)人是一個(gè)非常和藹的老爺爺。有條件的小伙伴可以去油管關(guān)注一下他。
這篇文章使用MicroPython在樹莓派 Pico上編程,一起來看看三十塊的微控制器究竟能做些什么。
介紹
樹莓派基金會發(fā)布微控制器本身就是一個(gè)大消息,畢竟在這之前,這個(gè)世界上最流行的單板電腦的制造商從來沒有表示過對微控制器的興趣。
不僅僅是樹莓派Pico的公布讓人感到意外,這次樹莓派還自己打造了一款新的芯片。他們沒有在現(xiàn)有代碼的基礎(chǔ)上,支持基于ESP32或SAMD21的設(shè)計(jì),而是選擇創(chuàng)建自己的微控制器。
所以談到Pico時(shí),我們都是新手。
樹莓派也在官網(wǎng)發(fā)布了一大堆技術(shù)文檔,還有一本名為《Get Started with MicroPython on Raspberry Pi Pico》的說明書。它有紙質(zhì)版,也有PDF版下載。
除此之外,目前還沒有關(guān)于Pico更深入的資料。不過隨著時(shí)間的推移,這種情況很快就會改變,樹莓派已經(jīng)授權(quán)包括Adafruit在內(nèi)的其他廠商在自己的設(shè)計(jì)中使用RP2040芯片。假以時(shí)日,就會給我們帶來更多的代碼和開發(fā)工具。
我們先來嘗試一下,給Pico連接上一堆東西,會發(fā)生什么有趣的事情吧!
樹莓派 Pico
Pico是一塊小小的板子,大小和Arduino Nano差不多。和所有樹莓派一樣,包裝非常簡陋,只是一個(gè)塑料包裝內(nèi)的Pico,而塑料包裝本身就是從一條條的包裝上剪下來的,非常像小時(shí)候吃的咪咪蝦條或者是糖果的包裝。
看看Pico的板子
四刀買到的就僅僅是這么一款裸板,沒有多的,就是這么環(huán)保。
裸板不帶針腳,需要自己焊。這是一塊做工精良的電路板,也可以作為SMD元件,直接焊接到印刷電路板上。
俯視圖
從頂部看,Pico是這樣的。
板上最主要的功能是一端的microUSB連接器。它既用于通信,也用于給Pico供電。
在microUSB連接器旁邊安裝了一個(gè)板載LED,它內(nèi)部連接到GPIO針腳25。
值得注意的是,這是整個(gè)Pico板上唯一的LED。
開機(jī)按鈕安裝在離LED稍低一點(diǎn)的地方,它可以讓你改變Pico的啟動模式,這樣你就可以在上面加載MicroPython,進(jìn)行拖拽式編程。
在板子的底部,你會看到三個(gè)連接點(diǎn),這些連接點(diǎn)是用于串行Debug選項(xiàng)的,我們今天是入門,暫時(shí)不探討這個(gè)問題,高級開發(fā)者會比較感興趣。
在板子的中央是整個(gè)板子的“大腦”——RP2040 MCU,我們一會兒就會研究它的功能。
接地引腳
板子上有好幾個(gè)地線,8個(gè)地線加上3針Debug連接器上的一個(gè)附加地線。
這些引腳很容易發(fā)現(xiàn),它們是均勻的,而且是方形的,而不是像其他連接的圓形。
其中一個(gè)位于33號針腳的地線也被指定為模擬地線。
電源引腳
Pico是一個(gè)3.3V的邏輯器件,但由于內(nèi)置了電壓轉(zhuǎn)換器和穩(wěn)壓器,它可以用一系列電源供電。
所有與電源相關(guān)的引腳都被安排在了一起,靠近microUSB連接器。
VBUS - 這是來自 microUSB 總線的電源,5 V。如果Pico不是由microUSB連接器供電,那么這里將沒有輸出。
VSYS - 這是輸入電壓,范圍為 2 至 5 V。板載電壓轉(zhuǎn)換器將為 Pico 將其改為 3.3 V。
3V3 - 這是 Pico 內(nèi)部調(diào)節(jié)器的 3.3 伏輸出。只要將負(fù)載保持在 300ma 以下,它就可用于為其他組件供電。
還有幾個(gè)輸入可以讓你控制 Pico 的電源。
3V3_EN - 你可以使用此輸入禁用 Pico 的內(nèi)部電壓調(diào)節(jié)器,從而關(guān)閉 Pico 和由其供電的任何組件。
RUN - 可以啟用或禁用 RP2040 微控制器,也可以將其復(fù)位。
GPIO引腳
樹莓派 Pico板上有26個(gè)裸露的GPIO連接。
它們的排列順序很好,在GPIO 22和GPIO 26之間有一個(gè) "空隙"(這些 "缺失 "的引腳在內(nèi)部使用)。
這些引腳都有多種功能,你可以為PWM配置多達(dá)16個(gè)引腳。
有兩個(gè)I2C總線,兩個(gè)UART和兩個(gè)SPI總線,這些可以配置使用多種GPIO引腳。
模擬引腳
Pico有三個(gè)模數(shù)轉(zhuǎn)換器,還有一個(gè)內(nèi)部用于板載溫度傳感器的轉(zhuǎn)換器。
ADC的分辨率為12位。
你也可以在ADC_VREF引腳上提供一個(gè)外部精密電壓參考。其中一個(gè)接地點(diǎn),即33腳上的ADC_GND被用作該參考點(diǎn)的接地點(diǎn)。
RP2040微控制器
樹莓派 Pico是圍繞基金會的新芯片RP2040微控制器而設(shè)計(jì)的。下面是它的參數(shù):
運(yùn)行在48MHz,但可以超頻到133MHz。
30個(gè)GPIO引腳(26個(gè)暴露)
可支持USB主機(jī)或設(shè)備模式
8 可編程I/O(PIO)狀態(tài)機(jī)
RP2040能夠支持高達(dá)16MB的片外閃存,不過在Pico中只有4MB。
樹莓派基金會對這款芯片有很多計(jì)劃,也已經(jīng)授權(quán)給了很多其他廠商。
對Pico進(jìn)行編程
你可以使用兩種編程語言之一開始使用 Pico。
MicroPython - 一種專門為微控制器制作的解釋語言。
C++ - 許多微控制器用戶都熟悉C++,因?yàn)樗挥糜贏rduino和ESP32板上。
雖然我急于將C++與Pico一起使用,以榨取它的每一克性能,但還是決定與大多數(shù)人一樣,使用MicroPython。在這個(gè)早期的開發(fā)階段,C++的工具還在進(jìn)行最后的開發(fā),期待著Pico成為PlatformIO和Arduino IDE板系列的一部分。
開始使用Pico
當(dāng)我們拿到Pico板時(shí),它被包裝在一個(gè)塑料載體中,沒有額外的零件。
除非你有計(jì)劃將 Pico 表面貼裝,或者你的唯一目的是只是點(diǎn)個(gè)燈,否則我們都需要一些引腳。
Pico 有 40 個(gè)引腳,每側(cè) 20 個(gè)。另外三個(gè)針腳用于調(diào)試端口。
標(biāo)準(zhǔn)的公頭針腳有 40 個(gè)針腳帶,因此可以將其中一個(gè)針腳帶減半,作為 Pico 的針腳使用。如果你想在 Debug 連接器上安裝針腳,你需要另一個(gè) 3 針的公頭,可以是直的或 90 度的。
焊接一個(gè)Pico
在開始對 Pico 進(jìn)行編程之前,我們需要進(jìn)行一些焊接工作!除了杜邦公頭引腳之外,我們還需要合適的烙鐵和一些焊料。
電烙鐵的頭需要精細(xì)一點(diǎn),我們還需要一塊清潔海綿和一個(gè)支架。
此外,我們還需要想辦法在焊接Pico引腳時(shí)把它固定住,因?yàn)樗鼈冃枰跃_的90度角安裝到電路板上,這樣才能裝入無焊料面包板。
許多實(shí)驗(yàn)都使用無焊面包板來固定引腳,雖然這種方法可行,但有可能因熱力或焊料飛濺而損壞面包板。
所以最好的解決方法是,你有一塊老舊的面包板,用它作為針座。
我個(gè)人喜歡用幾塊便宜的灌注板、打孔實(shí)驗(yàn)板。我說的 "便宜 "是指單面的東西,沒有排孔,只有一面是裸銅的。
兩片這種東西很適合固定引腳,每當(dāng)要焊接一個(gè)小模塊或者單片機(jī)的時(shí)候,我就經(jīng)常用這個(gè)。
把電烙鐵加熱到一定溫度,然后加熱引腳與焊盤的連接處,在另一面涂上焊料,千萬不要直接涂到電烙鐵上。加熱零件,而不是焊料。
如果你想焊接Debug的3個(gè)引腳連接器(這是可選的),你可能應(yīng)該先做。這些引腳的方向與GPIO引腳的方向相反。我用了一個(gè)小的便簽墊來固定電路板,因?yàn)镈ebug連接器與GPIO引腳在網(wǎng)格上并不一致。
之后就是焊接40個(gè)引腳了,一次20個(gè)! 真的不需要太長的時(shí)間,只需要用盡可能多的焊料,避免出現(xiàn)焊橋,完成后再檢查一下。
焊接后清理Pico
我喜歡在焊接完我的PCB后清洗它們,以去除焊料核心中的助焊劑和樹脂。它表現(xiàn)為焊接連接處周圍的褐色污漬。
這一步完全是可有可無的,因?yàn)橹竸┖蜆渲瑢υ倪\(yùn)行或壽命沒有任何不利影響。它只是看起來更好看!
如果你想克隆你的板子,你需要一些PCB板清洗劑或Flus Remover。由于它也往往會留下一點(diǎn)殘留物,我用異丙醇來清理。
PCB板清洗劑可以到網(wǎng)上購買。異丙醇可以在當(dāng)?shù)厮幍暾业剑欢ㄒI純酒精和水的混合物(70%),不要買有香味的。
我用一把舊牙刷和一些塑料容器,在一個(gè)盆子里進(jìn)行工作。記得最好要準(zhǔn)備好口罩、手套和護(hù)目鏡。
我用牙刷蘸PCB清潔劑擦洗引腳,然后用牙刷蘸異丙醇沖洗。
讓板子自然風(fēng)干,也可以使用空氣軟管,這樣之后,我們將擁有一個(gè)閃閃發(fā)光的新Pico!
Pico 和Thonny IDE
現(xiàn)在Pico的引腳已經(jīng)連接好了,我們可以開始對它進(jìn)行實(shí)驗(yàn)了。
建議你把它放在一個(gè)無焊的面包板上,以迎接我們即將到來的實(shí)驗(yàn)。
雖然有許多IDE可以讓我們選擇與我們的新Pico一起工作,但我的建議是使用樹莓派推薦的Thonny IDE。
Thonny IDE
Thonny自稱是 "Python IDE for Beginners",它適用于Windows、Mac OSX和Linux。
它也是樹莓派操作系統(tǒng)(以前的Raspbian)的一部分。
我將在樹莓派操作系統(tǒng)上使用Thonny IDE,運(yùn)行在8GB的樹莓派 4上,作為我今天實(shí)驗(yàn)的開發(fā)平臺。當(dāng)然,你可以使用任何你能運(yùn)行Thonny的平臺,但我想讓它在樹莓派家族中運(yùn)行--另外,由于Thonny已經(jīng)安裝在新構(gòu)建的樹莓派操作系統(tǒng)上,所以上手非常簡單。
啟動和安裝MicroPython
我們需要做的第一件事是將MicroPython安裝到Pico上。
將microUSB連接到Pico上,并準(zhǔn)備將另一端插入電腦。在插入之前,先按下Pico上的Boot Select(開關(guān))按鈕。
按住BOOTSEL鍵,將Pico插入電腦的USB端口。按住BOOTSEL鍵幾秒鐘,然后松開。
你應(yīng)該會看到一個(gè)新的驅(qū)動器在你的電腦上可用,信息看起來會有所不同,這取決于你所使用的操作系統(tǒng),但它類似于你將U盤插入電腦時(shí)得到的信息。
打開新的 "驅(qū)動器",你會看到一個(gè)名為RPI-RP2的文件夾。在這個(gè)驅(qū)動器里,你會看到幾個(gè)文件,其中一個(gè)是網(wǎng)頁文檔index.htm。
點(diǎn)擊該網(wǎng)頁文件,瀏覽器就會打開,你會被重定向到樹莓派 Pico入門頁面。
點(diǎn)擊MicroPython入門的標(biāo)簽。你會看到一個(gè)鏈接來下載一個(gè)UF2文件,這就是可下載的MicroPython文件。把這個(gè)文件下載到你的電腦上。
現(xiàn)在將下載的文件拖到Pico的RPI-RP2文件夾中。一旦這樣做了,文件夾就會消失,Pico將以MicroPython模式啟動。
配置 Thonny IDE
在Pico仍然被連接的情況下,打開Thonny IDE,如果你和我一樣使用樹莓派操作系統(tǒng),你會在編程工具菜單下找到Thonny。
一旦Thonny打開,請看右下角的狀態(tài)欄,它可能會顯示一個(gè)Python的版本。這是當(dāng)前在你的計(jì)算機(jī)上運(yùn)行的Python版本,對于我們的實(shí)驗(yàn)來說,這一點(diǎn)并不重要。
點(diǎn)擊該消息,應(yīng)該會出現(xiàn)一個(gè)下拉菜單,還有其他環(huán)境可以選擇。其中一個(gè)應(yīng)該是MicroPython (樹莓派 Pico)。選擇那一個(gè)。
你會注意到底部打開了一個(gè)新的Shell,在這個(gè)Shell中,你應(yīng)該會看到一些文字,表明你已經(jīng)連接到Pico。
是時(shí)候開始編程了!
Shell測試
Shell是Pico的 "命令行",你可以直接在這里執(zhí)行代碼。
一個(gè)簡單的測試是輸入以下內(nèi)容(這也是查看你是否正確連接到 Pico 的好方法),然后按 Enter 鍵。
print(“HelloWorld”)
你應(yīng)該在shell中看到 "Hello World "被打印出來了,當(dāng)然這是你告訴Pico要做的。
腳本測試
當(dāng)然,你不會直接在shell中輸入你的程序,一來,一旦你執(zhí)行了程序,它們就會消失,二來,對于任何相當(dāng)大的程序來說,也是不方便的。
你要用編輯器來輸入你的程序,也就是shell上面的大文本區(qū)域,在Thonny IDE的屏幕上占主導(dǎo)地位。
進(jìn)入這個(gè)編輯器,輸入和剛才一樣的文字,用一個(gè)漂亮的 "你好 "來迎接編程世界。
點(diǎn)擊 "運(yùn)行 "按鈕(綠色帶箭頭的那個(gè)),系統(tǒng)會提示你先保存程序。你可以選擇將其保存在本地電腦或Pico上,嘗試保存在Pico上。給你的程序起個(gè)帶".py "后綴的名字,比如 "hello.py"。
程序?qū)⒈槐4娌⑦\(yùn)行,你將在shell中看到 "Hello World "的問候語。你可以按 "運(yùn)行 "按鈕再次看到它,再按一次。
所以,現(xiàn)在你知道了如何編寫和保存MicroPython程序,我們就可以開始我們的實(shí)驗(yàn)了!
使用LED和開關(guān)
基本的數(shù)字I/O功能可以很容易地用LED和開關(guān)來說明,這正是我們開始Pico冒險(xiǎn)的方式。
但請注意我們?nèi)绾谓o開關(guān)布線,我們將以不同的方式進(jìn)行操作。
RGB LED
最簡單的輸出設(shè)備可能是LED。當(dāng)在正確的方向上施加足夠的電流時(shí),這種輸出設(shè)備就會工作。雖然簡單,但它可以用來說明I/O技術(shù),這些技術(shù)可以應(yīng)用于其他設(shè)備,如繼電器或晶體管。
我將使用一個(gè)Common-Cathode RGB LED,但你也可以使用三個(gè)分立的LED來代替。無論哪種方式,你都還需要三個(gè)降壓電阻,我在實(shí)驗(yàn)中使用了330歐姆的電阻。
如果你選擇像我這樣使用RGB LED,一定要買一個(gè)標(biāo)準(zhǔn)的RGB LED,而不是一個(gè)可編程的。
按鈕開關(guān)
這是最簡單的輸入設(shè)備。我用的是一對瞬時(shí)常開按鈕開關(guān)
一個(gè)紅色和一個(gè)黑色,但在其他方面是相同的。
我們再次使用一個(gè)簡單的輸入設(shè)備來測試我們的小Pico的I/O能力。我們將以不同的方式為兩個(gè)開關(guān)布線,使其更加有趣,而且我們也不會使用任何上拉或下拉電阻。
LED和開關(guān)的連接
這里是我們的LED和開關(guān)的連接圖,請記住,如果你沒有共陰極RGB LED,你可以使用三個(gè)獨(dú)立的LED。
請注意,這兩個(gè)開關(guān)的接線方式不同。
黑色按鈕開關(guān)的一側(cè)連接到Pico的GPIO引腳,另一側(cè)連接到地。
紅色開關(guān)則相反,它的一側(cè)連接到GPIO引腳,另一側(cè)連接到3.3伏,這是Pico的工作電壓和邏輯電壓。
經(jīng)典項(xiàng)目——點(diǎn)燈
我們要做的第一個(gè)實(shí)驗(yàn)是我們自己的Arduino "Blink "草圖的變體。是的,從技術(shù)上講,我們已經(jīng)看到了如何閃爍板載LED,但由于我們現(xiàn)在有一個(gè)RGB LED在我們的支配下,我們當(dāng)然可以找到另一種方法來點(diǎn)燈!
在Thonny中打開以下代碼。
#樹莓派PicoRGBBlink #rgb-blink.py #REDLED-PicoGPIO10-Pin14 #GREENLED-PicoGPIO11-Pin15 #BLUELED-PicoGPIO14-Pin19 #DroneBotWorkshop2021 #https://dronebotworkshop.com importmachine importutime led_red=machine.Pin(10,machine.Pin.OUT) led_green=machine.Pin(11,machine.Pin.OUT) led_blue=machine.Pin(14,machine.Pin.OUT) whileTrue: led_red.value(1) led_green.value(0) led_blue.value(0) utime.sleep(2) led_red.value(0) led_green.value(1) led_blue.value(0) utime.sleep(2) led_red.value(0) led_green.value(0) led_blue.value(1) utime.sleep(2) led_red.value(1) led_green.value(1) led_blue.value(0) utime.sleep(2) led_red.value(1) led_green.value(0) led_blue.value(1) utime.sleep(2) led_red.value(0) led_green.value(1) led_blue.value(1) utime.sleep(3) led_red.value(1) led_green.value(1) led_blue.value(1) utime.sleep(2) print("EndofLoop") led_red.value(0) led_green.value(0) led_blue.value(0) utime.sleep(2)
這是一個(gè)簡單的腳本,肯定可以改進(jìn),但它可以很好地說明我們的觀點(diǎn)。
我們先導(dǎo)入 machine 和 utime 庫。你會發(fā)現(xiàn),任何涉及I/O端口的活動都需要用到machine,而只要我們想使用時(shí)間函數(shù),就需要用到utime。
然后,我們定義三個(gè) LED 元件的連接,請注意,它們是以 GPIO 編號而非 Pico 上的物理引腳編號來表示的。我們將所有這些引腳定義為 machinePin.OUT,這意味著這些引腳現(xiàn)在被設(shè)置為輸出引腳。
while True條件類似于Arduino草圖中的Loop,這里的代碼是連續(xù)執(zhí)行的。
在本節(jié)中,我們對LED進(jìn)行尋址,并將它們設(shè)置為開(值為1)或關(guān)(值為0)。我們通過一個(gè)序列,在最后一個(gè)序列,我們打印到控制臺。
然后我們再做一遍。
將腳本加載到Pico上,然后觀察LED,你應(yīng)該會看到一個(gè)彩色的閃爍。
開關(guān)測試
我們接下來的腳本是對兩個(gè)開關(guān)進(jìn)行一個(gè)非常基本的測試,我們用這樣一個(gè)奇怪的方式來接線。
你會觀察到的第一件奇怪的事情是它們的接線不同,黑色的開關(guān)將輸入端連接到地,而紅色的開關(guān)將輸入端連接到3.3伏,用于邏輯HIGH。
另一個(gè)有趣的事情是,這兩個(gè)開關(guān)都沒有采用上拉或下拉電阻,它們顯然需要這些電阻,黑色開關(guān)需要上拉,紅色開關(guān)需要下拉才能正常工作。
我們將在代碼中加入所需的電阻!
#樹莓派PicoSwitchTest #switchtest.py #REDBUTTON-PicoGPIO15-Pin20 #BLACKBUTTON-PicoGPIO2-Pin4 #DroneBotWorkshop2021 #https://dronebotworkshop.com importmachine importutime button_red=machine.Pin(15,machine.Pin.IN,machine.Pin.PULL_DOWN) button_black=machine.Pin(2,machine.Pin.IN,machine.Pin.PULL_UP) whileTrue: ifbutton_red.value()==1: print("Red") ifbutton_black.value()==0: print("Black") utime.sleep(0.25)
請注意定義按鈕的行的語法,你會看到它們是如何被定義為Inputs的,以及如何添加了下拉和上拉電阻。
在while True: 循環(huán)中,你還會注意到我們是在監(jiān)測不同的條件,紅色的開關(guān)觸發(fā)了一個(gè)HIGH輸入,而黑色的開關(guān)觸發(fā)了一個(gè)LOW。
最后的微小時(shí)間延遲是一種簡單的debouncing形式,如果你喜歡,你可以實(shí)驗(yàn)一下這個(gè)值。
這個(gè)腳本會在控制臺中打印所有的結(jié)果,所以在你按下按鈕的時(shí)候要注意。
中斷和切換
接下來的實(shí)驗(yàn)引入了幾個(gè)有用的概念。第一個(gè),也可以說是這兩個(gè)概念中最重要的,就是 "中斷"。
中斷
中斷就像它的聲音一樣,是一個(gè) "中斷 "程序正常流程的事件。在我們的情況下,我們處理的是外部硬件中斷,這意味著在程序繼續(xù)運(yùn)行之前,需要處理一個(gè)信號或狀態(tài)變化。
在Pico上,我們按照以下方式創(chuàng)建一個(gè)中斷。
我們將一個(gè)引腳定義為 "中斷輸入", 我們定義該點(diǎn)上的狀態(tài)變化被認(rèn)為是一個(gè)中斷。在 Pico 上,我們可以使用任何 GPIO 引腳來實(shí)現(xiàn)這一點(diǎn),而且我們可以定義多個(gè)引腳。
我們創(chuàng)建了一個(gè) "中斷處理程序 "函數(shù),我們希望在檢測到中斷時(shí)運(yùn)行該函數(shù)。
我們將 "中斷處理程序 "與 "中斷輸入 "配對。
現(xiàn)在,每當(dāng)中斷輸入條件發(fā)生時(shí),Pico 將停止它正在做的任何事情,并執(zhí)行 "中斷處理程序"。然后它將恢復(fù)到原來的位置。
切換
雖然不像中斷那樣基本,但仍然非常有用。“切換”只是將 Pico 上的輸出狀態(tài)反轉(zhuǎn)。
因此,如果輸出為高電平,而我們應(yīng)用 "切換",它就會變?yōu)榈碗娖健?/p>
我們不需要知道輸出的當(dāng)前狀態(tài),我們只需要知道當(dāng)我們應(yīng)用一個(gè)切換器時(shí),它將變?yōu)橄喾吹臓顟B(tài)。
自然,這是寫另一個(gè)Blink程序的理想函數(shù),所以我們會這么做。只有我們的Blink程序才會有被中斷的風(fēng)險(xiǎn)!
#樹莓派PicoInterrupt&ToggleDemo #interrrupt-toggle-demo.py #REDLED-PicoGPIO10-Pin14 #GREENLED-PicoGPIO11-Pin15 #REDBUTTON-PicoGPIO15-Pin20 #DroneBotWorkshop2021 #https://dronebotworkshop.com importmachine importutime led_red=machine.Pin(10,machine.Pin.OUT) led_green=machine.Pin(11,machine.Pin.OUT) led_red.value(0) led_green.value(0) button_red=machine.Pin(15,machine.Pin.IN,machine.Pin.PULL_DOWN) defint_handler(pin): button_red.irq(handler=None) print("InterruptDetected!") led_red.value(1) led_green.value(0) utime.sleep(4) led_red.value(0) button_red.irq(handler=int_handler) button_red.irq(trigger=machine.Pin.IRQ_RISING,handler=int_handler) whileTrue: led_green.toggle() utime.sleep(2)
在這個(gè)MicroPython腳本中,我們將閃爍我們的RGB LED的綠色部分,使用一個(gè)切換器來改變它的狀態(tài)。在正常的操作下,LED狀態(tài)將每兩秒鐘切換一次。
然而,我們可以通過按下紅色按鈕來中斷閃爍。這將導(dǎo)致一個(gè)中斷,這將關(guān)閉綠色的LED,然后打開紅色的。它將保持四秒,之后程序控制權(quán)將被恢復(fù),因此我們可以繼續(xù)進(jìn)行綠色閃爍。
我們通過導(dǎo)入machine和utime庫來開始我們的腳本,就像我們之前一樣。
LED段和紅色按鈕的定義和之前的腳本一樣。LED在程序啟動時(shí)被關(guān)閉。
然后我們定義一個(gè)函數(shù),這是我們的中斷處理程序,叫做 "int_handler"。在這個(gè)函數(shù)中,我們做了以下工作。
關(guān)閉中斷,這樣我們就不會有多個(gè)中斷了。
將 "中斷檢測 "打印到Shell上
打開紅色LED段。
關(guān)閉綠色LED段。
睡眠四秒。
關(guān)閉紅色段。
重新建立中斷
退出
處理函數(shù)后的那一行將中斷 "粘 "到我們定義為紅色按鈕輸入的引腳上。需要注意的是,它指定了 "IRQ_RISING",這意味著如果輸入從0(地)上升到1(3.3伏),它將觸發(fā)一個(gè)中斷。這與我們紅色按鈕的接線方式一致。
在True循環(huán)中,我們只需使用定義為輸出的任何GPIO引腳可用的 "toggle "功能來閃爍LED。
將它發(fā)送到Pico上,觀察RGB LED,它應(yīng)該開始閃爍綠色。觀察一段時(shí)間,然后按下紅色按鈕。LED應(yīng)該變成紅色,Shell應(yīng)該顯示 "Interrupt Detected"。四秒鐘后,綠色閃爍將重新開始。
開關(guān)和LED演示
既然我們一直在研究開關(guān)和LED,我們不妨把它們結(jié)合起來,再編寫一個(gè)簡單的腳本。
#樹莓派PicoSwitch&RGBLEDDemo #switch-led-demo.py #REDLED-PicoGPIO10-Pin14 #GREENLED-PicoGPIO11-Pin15 #BLUELED-PicoGPIO14-Pin19 #BLACKBUTTON-PicoGPIO2-Pin4 #DroneBotWorkshop2021 #https://dronebotworkshop.com importmachine importutime led_red=machine.Pin(10,machine.Pin.OUT) led_green=machine.Pin(11,machine.Pin.OUT) led_blue=machine.Pin(14,machine.Pin.OUT) led_red.value(0) led_green.value(0) led_blue.value(0) button_black=machine.Pin(2,machine.Pin.IN,machine.Pin.PULL_UP) whileTrue: ifbutton_black.value()==0: led_red.value(1) led_green.value(0) led_blue.value(0) utime.sleep(1) led_red.value(0) led_green.value(1) led_blue.value(0) utime.sleep(1) led_red.value(0) led_green.value(0) led_blue.value(1) utime.sleep(1) led_red.value(0) led_green.value(0) led_blue.value(0)
這個(gè)很簡單,現(xiàn)在大家應(yīng)該對它的操作很熟悉了。我們用machine庫函數(shù)定義RGB LED和黑色按鈕。
記住,黑色按鈕是由我們定義的上拉保持HIGH的,當(dāng)按鈕被按下時(shí),它就會變LOW,因?yàn)榱硪贿吺墙拥鼐€的。
所以在True循環(huán)中,我們尋找一個(gè) "0 "的值,以表示按鈕被按下。一旦我們檢測到這個(gè)條件,我們就會通過它們的顏色循環(huán)LED段。
正如我所說,很簡單的東西。
模擬輸入測試
現(xiàn)在我們來談?wù)勀M輸入。
樹莓派 Pico有三個(gè)模擬輸入,它們都有12位的分辨率。
這三個(gè)輸入端如下。
GPIO 26 - ADC0 (31針)
GPIO 27 - ADC1 (針腳 32)
GPIO 28 - ADC2 (針腳34)
還有第四個(gè)ADC用于內(nèi)部溫度傳感器。
電位計(jì)的連接
在我們的測試中,我們將使用一個(gè)電位器在模擬輸入端呈現(xiàn)一個(gè)可變電壓,然后我們將讀取該電壓。我們將使用ADC0作為我們的電位計(jì)輸入,但你也可以使用其他兩個(gè)中的一個(gè)。
請注意,雖然我將23號針腳顯示為地線,這只是為了方便,但你可以使用任何Pico地線針腳。在33號針腳處還有一個(gè)特殊的模擬地,你可以使用。在我的面包板上,我將33號針腳與其他一些地線相連。
電位計(jì)讀數(shù)
我們要做的第一個(gè)實(shí)驗(yàn)是簡單地讀取我們在模擬輸入端得到的值,這個(gè)值應(yīng)該根據(jù)我們電位器的位置而波動。
#樹莓派PicoAnalogInputTest #analog-input.py #POT-PicoGPIO26ADC0-Pin32 #DroneBotWorkshop2021 #https://dronebotworkshop.com importmachine importutime potentiometer=machine.ADC(26) whileTrue: print(potentiometer.read_u16()) utime.sleep(2)
這是一個(gè)簡單的腳本,像往常一樣,首先導(dǎo)入用于GPIO操作的machine庫和用于時(shí)間函數(shù)的utime庫。
然后我們定義我們的電位器連接。請注意我們?nèi)绾问褂?"ADC "來表示我們要將GPIO 26針作為模擬輸入。當(dāng)然這只適用于具有模擬輸入能力的三個(gè)GPIO引腳。
在True循環(huán)中,我們只需打印從電位器上得到的值,然后延遲幾秒鐘再做一次。
需要注意的是,我們用 "read_u16 "函數(shù)得到的值的類型是一個(gè)無符號的16位整數(shù)。這意味著它將在0和65,535之間變化,而不是你可能期望從12位ADC中得到的4095。
這可能看起來很奇怪,但正如我們將在下一個(gè)腳本中看到的那樣,能夠傳遞具有相同數(shù)值數(shù)據(jù)類型的值實(shí)際上是有用的。
運(yùn)行腳本并觀察Shell,你應(yīng)該會看到那里的數(shù)值隨著你移動電位器軸而改變。
LED PWM控制
讓我們在之前的腳本基礎(chǔ)上進(jìn)行擴(kuò)展,使用電位器的輸出來控制LED的亮度。
當(dāng)然,我們將使用PWM進(jìn)行控制,這個(gè)任務(wù)在MicroPython中非常簡單。
#樹莓派PicoLEDPWMTest #led-pwm.py #POT-PicoGPIO26ADC0-Pin32 #REDLED-PicoGPIO10-Pin14 #DroneBotWorkshop2021 #https://dronebotworkshop.com importmachine importutime led_red=machine.PWM(machine.Pin(10)) potentiometer=machine.ADC(26) led_red.freq(1000) whileTrue: led_red.duty_u16(potentiometer.read_u16())
在這個(gè)腳本中需要注意的一個(gè)關(guān)鍵項(xiàng)目是我們定義 "led_red "的方式。我們將其定義為 "PWM",而不是輸出。
電位器的定義與上一個(gè)腳本中的方式完全相同。
現(xiàn)在我們已經(jīng)給輸出賦予了 "PWM "的屬性,它繼承了許多其他參數(shù)。其中之一是PWM頻率,我們將其設(shè)置為1000 Hz。
在true循環(huán)中,我們不斷地從電位器中獲取無符號的16位值,并將其傳遞給LEDs占空比,也方便地指定為無符號的16位整數(shù)。
這就說明了兩者保持相同的編號方案的價(jià)值,不需要將模擬值,真的是0到4095,映射到占空比,真的是0到100。
運(yùn)行程序,你應(yīng)該可以順利地控制紅色LED段的亮度。
添加顯示屏
我們將進(jìn)行的下一個(gè)實(shí)驗(yàn)是將一個(gè)OLED顯示器連接到我們的Pico上,當(dāng)然,也可以在上面打印一些東西。
我們將使用 I2C 顯示屏,因此我們也將看到 Pico 如何使用 I2C 連接工作。記住,Pico有兩條I2C總線。
我們的OLED是標(biāo)準(zhǔn)的1602型OLED顯示器,到處都有。如果你愿意,也可以使用與我的顯示屏尺寸不同的顯示屏,只需在代碼中更改尺寸即可。
這是我們?nèi)绾伟堰@些東西都掛起來的,只有四根線。
我們的顯示器需要一個(gè)庫,我們可以使用Thonny ID安裝。你可能會發(fā)現(xiàn)在全菜單模式下比在基本模式下更容易,但這兩種方式都可以。
點(diǎn)擊 "工具 "菜單
點(diǎn)擊 "管理包"
搜索 "ssd1306"
找到 "ssd1306.py "并安裝它。
現(xiàn)在我們已經(jīng)安裝了庫,我們可以看一下演示OLED顯示屏的腳本。
#樹莓派PicoOLEDDisplayTest #Usesssd1306module #display-ssd1306-test.py #DroneBotWorkshop2021 #https://dronebotworkshop.com importmachine importutime sda=machine.Pin(20) scl=machine.Pin(21) i2c=machine.I2C(0,sda=sda,scl=scl,freq=400000) fromssd1306importSSD1306_I2C oled=SSD1306_I2C(128,32,i2c) print(i2c.scan()) oled.text('Welcometothe',0,0) oled.text('PiPico',0,10) oled.text('DisplayDemo',0,20) oled.show() utime.sleep(4) oled.fill(1) oled.show() utime.sleep(2) oled.fill(0) oled.show() whileTrue: oled.text("HelloWorld",0,0) foriinrange(0,164): oled.scroll(1,0) oled.show() utime.sleep(0.01)
我們的 OLED 顯示屏是一個(gè) I2C 設(shè)備,所以你會注意到,在腳本的開頭,我們將兩個(gè) GPIO 引腳定義為 SDA (GPIO 20) 和 SCL (GPIO 21)。
Pico有兩條I2C總線,你可以使用幾種不同的GPIO引腳來連接它們。但它們并不是隨便的引腳,例如某些引腳被指定為總線0的SDA,只有它們才能用于SDA總線0。
然后我們使用機(jī)器庫的I2C函數(shù)定義一個(gè)I2C連接。我們需要給它提供以下參數(shù)。
I2C總線號,在我們的例子中是0。
SDA引腳
SCL引腳
I2C總線頻率--在我們的例子中是400KHz。
然后我們添加OLED庫,并創(chuàng)建一個(gè)I2C OLED對象。我們將大小參數(shù)和I2C連接信息傳遞給它。
注意,我們沒有傳遞I2C地址。SD1306 OLED顯示器有一個(gè)固定的I2C地址,所以我們不需要指定它。
不過,我在這里添加了一行與顯示器無關(guān)的內(nèi)容,但可以讓你掃描I2C總線,并打印出它發(fā)現(xiàn)占用的地址。請注意,在Shell中打印出來的是十進(jìn)制,而不是你更可能習(xí)慣看到的十六進(jìn)制。
回到OLED腳本!
我們開始在顯示屏上打印,幾行文字。注意我們?nèi)绾沃付啃虚_始的像素位置。
實(shí)際上,我們并沒有直接打印到顯示屏上,而是將數(shù)據(jù)發(fā)送到一個(gè)緩沖區(qū)。oled.show()這一行將把該緩沖區(qū)的數(shù)據(jù)傳輸?shù)斤@示器上。
在打印完歡迎信息并按住它四秒鐘后,我們再執(zhí)行oled.fill(1)。這將打開顯示器中的每一個(gè)像素,或者更準(zhǔn)確地說,是緩沖區(qū)中的每一個(gè)像素。然后我們做一個(gè)oled.show()來顯示填充。
我們將填充物保持在顯示屏上兩秒鐘,然后執(zhí)行oled.fill(0),當(dāng)我們顯示它時(shí),它將關(guān)閉顯示屏中的每個(gè)像素。
現(xiàn)在進(jìn)入True循環(huán)。
我們再次輸入一些文本,經(jīng)典的 "Hello World"。但我們沒有進(jìn)行 "顯示 "來顯示它,而是開始一個(gè)for-loop。在這個(gè)循環(huán)中,我們使用led.scroll(1,0)將顯示水平移動1像素(垂直移動0像素,這就是另一個(gè)參數(shù))。
然后我們在屏幕上顯示,然后休眠一段很短的時(shí)間。然后我們再做一次。
結(jié)果將是顯示屏在屏幕上滾動。你可以在for-loop中使用參數(shù)來改變它。
將腳本加載到你的Pico上,然后觀看顯示。你應(yīng)該看到歡迎文字,然后是顯示填充,然后是空。之后,只要你讓實(shí)驗(yàn)運(yùn)行,滾動的 "Hello World "就會繼續(xù)。
驅(qū)動電機(jī)
微控制器比較流行的應(yīng)用之一是驅(qū)動一個(gè)或幾個(gè)直流電動機(jī)。
這是通過使用H-Bridge來實(shí)現(xiàn)的,H-Bridge是一種功率晶體管或MOSFET的排列方式,可以處理電機(jī)電流,同時(shí)允許你控制電機(jī)的方向和速度。
我們將只用一個(gè)電機(jī)來實(shí)現(xiàn)這一點(diǎn)。我們將使用TB6612FNG H-Bridge和樹莓派 Pico來控制一個(gè)小型直流電機(jī)。
TB6612FNG H-Bridge
TB6612FNG H-Bridge是我們之前使用過的,一款基于MOSFET的H-Bridge,相比老款備用的L-298N有很多性能上的優(yōu)勢。
該設(shè)備其實(shí)有兩個(gè)通道,我們只用通道A來演示。
通道A有三個(gè)輸入。
AI1 - 方向和模式
AI2 - 方向和模式
PWMA - 一個(gè)PWM輸入,用于控制電機(jī)速度。
在它們之間,AI1和AI2引腳控制電機(jī)方向和模式。模式包括短制動和停止模式。在我們的簡單演示中,我們將只處理方向模式。
TB6612FNG H-Bridge在板子的另一側(cè)還有電源和電機(jī)的連接。
下面是我們將使用TB6612FNG H-Bridge和樹莓Pico的連接方式。
請注意,由于我使用的是6V電機(jī),我已經(jīng)為它提供了一個(gè)6V電源。不要試圖使用Pico的輸出電壓來為你的電機(jī)供電,單獨(dú)的電源是必要的。我使用了四節(jié)AA型電池,這是一種簡單而安全的安排。
電機(jī)的極性其實(shí)并不重要,它只是決定了哪條路是向前的,哪條路是向后的。
一旦它被全部連接起來,我們就需要一些代碼來運(yùn)行它。我建議這樣做。
#樹莓派PicoMotorTest #motor-test.py #POT-PicoGPIO26ADC0-Pin32 #REDBUTTON-PicoGPIO15-Pin20 #BLACKBUTTON-PicoGPIO2-Pin4 #REDLED-PicoGPIO10-Pin14 #GREENLED-PicoGPIO11-Pin15 #BLUELED-PicoGPIO14-Pin19 #DroneBotWorkshop2021 #https://dronebotworkshop.com importmachine importutime potentiometer=machine.ADC(26) mtr_AI1=machine.Pin(8,machine.Pin.OUT) mtr_AI2=machine.Pin(7,machine.Pin.OUT) mtr_PWMa=machine.PWM(machine.Pin(6)) button_red=machine.Pin(15,machine.Pin.IN,machine.Pin.PULL_DOWN) button_black=machine.Pin(2,machine.Pin.IN,machine.Pin.PULL_UP) led_red=machine.Pin(10,machine.Pin.OUT) led_green=machine.Pin(11,machine.Pin.OUT) led_blue=machine.Pin(14,machine.Pin.OUT) led_red.value(0) led_green.value(0) led_blue.value(1) mtr_PWMa.freq(50) mtr_AI1.value(1) mtr_AI2.value(0) whileTrue: mtr_PWMa.duty_u16(potentiometer.read_u16()) ifbutton_red.value()==1: mtr_AI1.value(0) mtr_AI2.value(1) led_red.value(1) led_green.value(0) led_blue.value(0) ifbutton_black.value()==0: mtr_AI1.value(1) mtr_AI2.value(0) led_red.value(0) led_green.value(1) led_blue.value(0) utime.sleep(0.25)
我們要利用電位器、兩個(gè)開關(guān)和RGB LED,以及電機(jī)控制器。電位器將控制電機(jī)的速度,開關(guān)將控制電機(jī)的方向,而LED將用彩色指示燈顯示當(dāng)前的方向。
我們使用我們的之前的兩個(gè)庫,并像以前一樣設(shè)置電位器。
接下來,我們將Pico與TB6612FNG H-Bridge的連接定義為輸出。GPIO 6上的PWMA輸出被定義為PWM,它將控制電機(jī)速度。
LED和按鈕的設(shè)置與之前相同。
PWM頻率設(shè)置為50Hz,這是一個(gè)任意的選擇。隨意實(shí)驗(yàn)一下,看看是否能提高電機(jī)性能。
電機(jī)AI1和AI2輸入被設(shè)置為正向旋轉(zhuǎn),所以電機(jī)將以正向啟動。請注意,當(dāng)我們啟動時(shí),RGB LED的藍(lán)段也會被打開。
在True循環(huán)中,我們讀取電位器的值,并將其傳遞給電機(jī)PWM信號,以控制電機(jī)的速度。我們還要看按鈕的狀態(tài)。
如果紅色按鈕被按下,我們設(shè)置AI1和AI2信號,使電機(jī)反轉(zhuǎn)。我們也會點(diǎn)亮紅色LED段。
如果黑色按鈕被按下,我們設(shè)置電機(jī)方向正向,并打開綠色LED段。
加載、檢查代碼。它應(yīng)該用一個(gè)藍(lán)色的LED啟動,你應(yīng)該能夠控制電機(jī)的速度。按下按鈕可以控制方向,還可以改變 LED 的顏色。
Pico Everything 演示
剩下的就是把所有的東西放在一起做一個(gè)大的最終演示。這一點(diǎn)我們已經(jīng)做得不遠(yuǎn)了,因?yàn)樵谏弦粋€(gè)腳本中,我們使用了所有的東西,除了OLED顯示屏。
所以讓我們把OLED顯示屏添加到這個(gè)組合中。下面是我們需要做的代碼。
#樹莓派EverythingTest #everything.py #POT-PicoGPIO26ADC0-Pin32 #REDBUTTON-PicoGPIO15-Pin20 #BLACKBUTTON-PicoGPIO2-Pin4 #REDLED-PicoGPIO10-Pin14 #GREENLED-PicoGPIO11-Pin15 #BLUELED-PicoGPIO14-Pin19 #DroneBotWorkshop2021 #https://dronebotworkshop.com importmachine importutime potentiometer=machine.ADC(26) mtr_AI1=machine.Pin(8,machine.Pin.OUT) mtr_AI2=machine.Pin(7,machine.Pin.OUT) mtr_PWMa=machine.PWM(machine.Pin(6)) button_red=machine.Pin(15,machine.Pin.IN,machine.Pin.PULL_DOWN) button_black=machine.Pin(2,machine.Pin.IN,machine.Pin.PULL_UP) led_red=machine.Pin(10,machine.Pin.OUT) led_green=machine.Pin(11,machine.Pin.OUT) led_blue=machine.Pin(14,machine.Pin.OUT) sda=machine.Pin(20) scl=machine.Pin(21) i2c=machine.I2C(0,sda=sda,scl=scl,freq=400000) fromssd1306importSSD1306_I2C oled=SSD1306_I2C(128,32,i2c) oled.text('PicoMotorTest',0,0) oled.show() utime.sleep(2) led_red.value(1) led_green.value(0) led_blue.value(0) utime.sleep(2) led_red.value(0) led_green.value(1) led_blue.value(0) utime.sleep(2) led_red.value(0) led_green.value(0) led_blue.value(1) mtr_PWMa.freq(50) mtr_AI1.value(1) mtr_AI2.value(0) whileTrue: speedvalue=int((potentiometer.read_u16())/500) mtr_PWMa.duty_u16(potentiometer.read_u16()) ifbutton_red.value()==1: mtr_AI1.value(0) mtr_AI2.value(1) led_red.value(1) led_green.value(0) led_blue.value(0) ifbutton_black.value()==0: mtr_AI1.value(1) mtr_AI2.value(0) led_red.value(0) led_green.value(1) led_blue.value(0) oled.fill_rect(1,15,speedvalue,25,1) oled.show() oled.fill_rect(1,15,speedvalue,25,0) utime.sleep(0.25)
現(xiàn)在你應(yīng)該能認(rèn)出這段代碼的大部分內(nèi)容了,基本上就是之前的腳本,加上了I2C OLED顯示屏的庫和設(shè)置。除此之外,前幾行都是一樣的,都是LED顏色的序列,一切設(shè)置好后,會有一個(gè)Display print。
在True循環(huán)中,我們看到正在計(jì)算一個(gè)名為 "speedvalue "的整數(shù)。這個(gè)變量將用于設(shè)置OLED上條形圖顯示的大小。
紅色和黑色的按鈕和之前的操作完全一樣。
然后,OLED在其標(biāo)題線下畫一個(gè)矩形,并填入矩形。矩形的長度由 "speedvalue "決定,所以隨著速度的增加,矩形會變長。
從某種意義上說,我們是把OLED當(dāng)做一個(gè)粗略的速度指示器,或者說是一個(gè)速度表!
裝上所有的東西,看演示效果。它的操作應(yīng)該和之前的實(shí)驗(yàn)一樣,只是這次我們除了有一個(gè)顯示電機(jī)速度的顯示器外,還有一個(gè)指示其方向的RGB LED。
在沒有主機(jī)的情況下運(yùn)行
到目前為止,我們所做的一切都是從 Thonny IDE 將程序加載到 Pico 上運(yùn)行的。
但是,一旦你開發(fā)了程序,你就會希望它能夠獨(dú)立運(yùn)行,由 microUSB 端口或通過 Pico VSYS 電源輸入供電。
你的程序或程序已經(jīng)存儲在 Pico 上。那么我們?nèi)绾巫屗陂_機(jī)時(shí)運(yùn)行程序呢?
答案是,我們更改程序名稱!
主程序main.py
當(dāng) Pico 啟動時(shí),它會查找名為 main.py 的程序。如果它找到了它,就會加載它并在啟動時(shí)運(yùn)行它。
因此,如果你想讓你的程序在無人看管的情況下運(yùn)行,你需要將其保存為main.py。稍后,如果你愿意,你可以將main.py改成其他程序,或者完全刪除它。
首先將你希望在啟動時(shí)運(yùn)行的程序加載到Thonny IDE中。現(xiàn)在點(diǎn)擊 "文件",然后選擇 "另存為"。
你會被問到是否要保存在本地計(jì)算機(jī)上或Pico上,你肯定要保存在Pico上。
現(xiàn)在把你的程序保存為 "main.py"。就像這樣,全部用小寫。
現(xiàn)在從電腦上拔下 Pico 的插頭,并將其插入合適的電源,如 USB 適配器。你會看到Pico重新開機(jī),并運(yùn)行你保存為 "main.py "的程序。
結(jié)束語
這顯然只是樹莓派Pico的開始。
我很希望看到PlatformIO和Arduino IDE能夠?yàn)闃漭?Pico提供支持,因?yàn)槟壳盀镻ico創(chuàng)建C++程序的方法有些繁瑣,特別是對于初學(xué)者來說。
但它是進(jìn)入MicroPython的一個(gè)很好且廉價(jià)的入口,你會在這里看到更多的東西。
所以盡快拿起Pico開始實(shí)驗(yàn)吧!
責(zé)任編輯:lq
-
微控制器
+關(guān)注
關(guān)注
48文章
7900瀏覽量
153646 -
芯片
+關(guān)注
關(guān)注
459文章
52119瀏覽量
435643 -
樹莓派
+關(guān)注
關(guān)注
121文章
1933瀏覽量
106929
原文標(biāo)題:目前全網(wǎng)最詳細(xì)的樹莓派 Pico入門指南!
文章出處:【微信號:gh_c472c2199c88,微信公眾號:嵌入式微處理器】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
知名廠商微控制器(MCU)芯片手冊分享

家用電器開發(fā)中微控制器的選型要點(diǎn)

FPGA 與微控制器優(yōu)缺點(diǎn)比較
超高頻讀寫器究竟是什么,能做什么?一文讀懂!

嵌入式系統(tǒng)中微控制器與微處理器的區(qū)別

ESP32 微控制器系列指南


評論