# **RaspberryPi** ###### tags: `智慧聯網` `RaspberryPi` <style> .flex-container { display: flex; justify-content: center; } </style> ## 簡介 <div class="flex-container"> <img src="https://i.imgur.com/Muqt3H2.png" width="50%"></div> >樹莓派(英語:Raspberry Pi)是基於Linux的單晶片電腦,由英國樹莓派基金會開發,目的是以低價硬體及自由軟體促進學校的基本電腦科學教育。 >樹莓派是源自一個開放源程式碼的硬體專案平台,該平台包括一塊具備簡單I/O功能的電路板以及一大堆的Linux 軟體。 ### 命名由來 >樹梅派 Raspberry Pi 的 Pi 就是指 ![](https://i.imgur.com/K9UQZc6.png =15x15) python,一開始只打算使用 python 當 Raspberry Pi 的專屬語言,但之後各種的語言都可以在 Raspberry Pi 上面運行了。 >而以樹莓為命名 Raspberry 則是為了致敬 Apple、Tangerine Computer Systems、Apricot Computers、Acorn等以水果為命字的公司。 ><div class="flex-container"><img src="https://i.imgur.com/0UN4LvW.png" width="100%"></div> ### 應用 >樹莓派可以用來開發交互產 品,比如它可以讀取大量的開關和感測器信號,並且可以控制電燈、電機和其他各 式各樣的物理設備;也可以開發出與PC一樣的周邊裝置,也可以運行在Linux PC 上的軟體進行通信。 > > ![](https://i.imgur.com/Muqt3H2.png =25x20)**機器人、自走車** &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;![](https://i.imgur.com/Muqt3H2.png =25x20)**做成掌機** > ![](https://i.imgur.com/jeWNguB.png =50%x)![](https://i.imgur.com/ipqlQ9X.png =50%x) > <br/> > ![](https://i.imgur.com/Muqt3H2.png =25x20)**物聯網通訊的閘道器**&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;![](https://i.imgur.com/Muqt3H2.png =25x20)**四軸飛行器、無人機** > ![](https://i.imgur.com/BnHsTwO.png =50%x)![](https://i.imgur.com/s5sxjw8.png =50%x) > <br/> > ![](https://i.imgur.com/Muqt3H2.png =25x20)**做成平板**&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;![](https://i.imgur.com/Muqt3H2.png =25x20)**影音播放器** > ![](https://i.imgur.com/YLhzLPF.png =50%x)![](https://i.imgur.com/kcxePA9.png =50%x) > ### Arduino uno 與 Raspberry Pi B 比較 | | Arduino uno | Raspberry Pi Model B | | --------------------------------- | ----------------- | ------------------------------------------ | | Price | $30 | $35 | | Size | 7.6x1.9x16.4 cm | 8.6x5.4x1.7 cm | | Memory | 0.002MB | 512MB | | Clock Speed | 16MHz | 700MHz | | On Board Network | None | 10/100 wired Ethernet RJ45 | | Multitasking | No | Yes | | Iput voltage | 7~12V | 5V | | USB | One,input only | Two,peripherals OK | | Flash | 32KB | SD Card(2~16G) | | Operating System | None | Linux distributions | | Integrate Development Environment | Arduino | Scratch、IDLE、anything with Linux support | 官網 : https://www.raspberrypi.org 各式硬體種類 : https://www.raspberrypi.org/products/ ## Raspberry Pi 3 Model B+ 與 Pi 3 最大的改變是網路效能增加了! ### 特色 > * 新增四根 PoE 的 Pin 腳支援,並有對應的擴充板(HAT)。 ><div class="flex-container"><img src="https://i.imgur.com/KMKztkX.jpg" width="70%"></div> ></br> > > * 網路效能提升! > ><div class="flex-container"><img src="https://i.imgur.com/E1sj9Oo.png" width="90%"></div> ></br> ><div class="flex-container"><img src="https://i.imgur.com/7TgOldf.png" width="90%"></div> ></br> > ### 規格 <div class="flex-container"><img src="https://i.imgur.com/yiahr6f.png" width="100%"></div> </br> | 型號 | 樹莓派 3B+ | |:--------:| ------------------------------------------------------------------------------ | | 晶片 | 博通 BCM2837B0, Cortex-A53 | | 處理器 | 64-bit SoC@1.4GHz 四核 | | 記憶體 | 1GB LPDDR2 記憶體 | | Wifi | Zero W天線 2.4GHz and 5GHz雙頻Wi-Fi, 支持IEEE 802.11 b/g/n/ac Wireless LAN | | 藍芽 | Bluetooth 4.2, BLE | | 乙太網路 | 300Mbps | | USB | USB 2.0 接口 x 4 | | IO | 40pin GPIO 針腳 | | 影像音頻 | HDMI 接口 x 1 、 DSI 顯示連接器 x 1 、 CSI 攝像頭接口 x 1 、 RCA av端口 音頻輸出 x1 | | 電源IC | Microchip LAN7515 | | 電源 | 5V / 2.5A DC Via Micro USB 接口、5V DC Via GPIO Header、獨立乙太網路供電(PoE) | </br> * **Fusion 360 Raspberry Pi 3 Model B+** 若看不到,請點擊此[連結](https://bit.ly/2QsnYmW) <div class="flex-container"><iframe src="https://mail61250.autodesk360.com/shares/public/SH56a43QTfd62c1cd9689c02d7782677d1ee?mode=embed" width="750" height="600" allowfullscreen="true" webkitallowfullscreen="true" mozallowfullscreen="true" frameborder="0"></iframe></div> ## Raspberry Pi 4 Model B 和之前的版本最大的改變是多了 2GB/4GB/8GB 的記憶體版本可供選擇 <div class="flex-container"><img src="https://i.imgur.com/Qx72dtN.png" width="80%"></div> </br> <div class="flex-container"><img src="https://i.imgur.com/zSDmikV.png" width="60%"></div> </br> 紅色圈起來的地方是MicroSD卡插槽 (樹莓派背面) <div class="flex-container"><img src="https://i.imgur.com/BfyJrGz.jpg" width="80%"></div> </br> ### 特色 1. 使用 Broadcom 2711 四核心晶片(原本為 BCM2837B0)Quad-core Cortex-A72 64-bit SoC,單核心時脈可達 1.5GHz,有三倍速快。 2. 三種記憶體(LPDDR4 SDRAM)大小可選擇,分別是 1GB, 2GB, 4GB 和 8GB。 3. 乙太網路(Ethernet)達 True Gigabit Ethernet。 4. 支援藍牙5.0(Bluetooth 5.0)。 5. 兩個 USB 3.0 和 兩個 USB 2.0。 6. 支援雙螢幕輸出,解析度可達 4K。 7. 使用 VideoCore VI,可支援 OpenGL ES 3.x。 8. 可硬體解 4Kp60 HEVC 影片。 ### 規格 | 型號 | 樹莓派 4B | |:--------:| -------------------------------------------------------------------------------------------------------------------------------- | | 晶片 | Broadcom 2711,Quad-core Cortex-A72 | | 處理器 | 四核ARM Cortex-A72(v8) 64位元 1.5GHz處理器 | | 記憶體 | 1GB, 2GB or 4GB LPDDR4 SDRAM | | Wifi | 2.4GHz / 5.0GHz IEEE 802.11.b/g/n/ac wireless LAN | | 藍芽 | **Bluetooth 5.0**, BLE | | 乙太網路 | **ports delivering true Gigabit Ethernet** | | USB | **2 x USB 2.0 / 2 x USB 3.0** | | IO | Extended 40-pin GPIO header | | 影像音頻 | **2 x micro HDMI、4k video(支援雙螢幕輸出)**、1 X MIPI DSI display port、1 X MIPI CSI camera port、4 pole stereo output and composite video port | | 電源IC | Microchip LAN7515 | | 電源 | DC 5V3A, 從**USB Type-C**接頭,或GPIO排針,或PoE輸入皆可| * **Fusion 360 Raspberry Pi 4 Model B+** 若看不到,請點擊此[連結](https://bit.ly/379pgxW) <div class="flex-container"><iframe src="https://mail61250.autodesk360.com/shares/public/SH56a43QTfd62c1cd968946788175dc3610a?mode=embed" width="750" height="600" allowfullscreen="true" webkitallowfullscreen="true" mozallowfullscreen="true" frameborder="0"></iframe></div> # 環境設置 ## 安裝作業系統 將官方作業系統透過Raspberry Pi Imager 燒錄到MicroSD卡中,完成後將MicroSD插入樹莓派然後開機啟動,就完成安裝啦 > 安裝系統前須注意 : > > 1.確認您的電腦是否有Micro SD讀卡機,若沒有須自行準備並接至電腦 > 2.周邊設備是否備齊,如圖所示 : ><div class="flex-container"><img src="https://i.imgur.com/RGYoLjE.png" width="80%"></div> > 3.將作業系統燒錄至Micro SD的動作只會用到電腦,固可先將設備先接至電腦(ex.鍵盤、滑鼠....),待燒錄完畢後再轉移到樹莓派即可。 ### 安裝流程 * 步驟一 : 將Micro SD 接至電腦 ><div class="flex-container"><img src="https://i.imgur.com/aNKAvIX.jpg" width="80%"></div></br> > * 步驟二 : 至[官網](https://www.raspberrypi.org/software/)下載Raspberry Pi Imager 在這裡選擇windows版本 >不須下載傳統燒錄軟體、映像檔,更簡便快速 ><div class="flex-container"><img src="https://i.imgur.com/s1hamA9.png" width="80%"></div> ></br> * 步驟三 : 開啟執行檔後 繼續在Windows中開啟Raspberry Pi Imager ></br> ><div class="flex-container"><img src="https://i.imgur.com/B8kbC6g.png" width="80%"></div> ></br> > - 選擇作業系統 >Operating System>Raspberry Pi OS(other)>Raspberry Pi OS Full(32-bit) > </br> ><div class="flex-container"><img src="https://i.imgur.com/9agbYrk.gif" width="80%"></div> ></br> > - 選擇你的SD卡 > <div class="flex-container"><img src="https://i.imgur.com/q1Eqi6W.gif" width="80%"></div> ></br> > - 開始燒錄 燒錄完成後會驗證(Verifying...⏳) > <div class="flex-container"><img src="https://i.imgur.com/k3Pxlkg.gif" width="80%"></div> * 步驟四 : 取出Micro SD卡 插入樹莓派的SD卡插槽 ><div class="flex-container"><img src="https://i.imgur.com/BfyJrGz.jpg" width="80%"></div> </br> * 步驟五 : 將樹梅派接上螢幕、鍵盤、滑鼠、網路後開機進行設定區域、語言、密碼、網路等等的設定,就完成啦::tada:: ><div class="flex-container"><img src="https://i.imgur.com/cRRq15g.gif" width="90%"></div> </br> ## 網路設定 ### wifi連線 #### 方法一 : raspi-config 尚未連接WiFi(Wlan0)時觀察網路介面的相關參數 ```bash $ifconfig ``` ><div class="flex-container"><img src="https://i.imgur.com/A95ApzH.png" width="90%"></div> > ```bash $sudo raspi-config ``` * 步驟一 : 選擇Network Options ><div class="flex-container"><img src="https://i.imgur.com/SJ3Kea5.png" width="90%"></div> > * 步驟二 : 選擇N2 Wi-fi ><div class="flex-container"><img src="https://i.imgur.com/uYx8vSt.png" width="90%"></div> > * 步驟三 : 選擇你所在的國家Taiwan(TW) ><div class="flex-container"><img src="https://i.imgur.com/cdBYzQg.png" width="90%"></div> > * 步驟四 : 輸入你的WiFi名稱(必須大小寫一致) ><div class="flex-container"><img src="https://i.imgur.com/yLLIQcU.png" width="90%"></div> > * 步驟五 : 輸入你的WiFi密碼,若沒設密碼直接按確定 ><div class="flex-container"><img src="https://i.imgur.com/ydYtWPa.png" width="90%"></div> > * 步驟六 : 重新開機 ><div class="flex-container"><img src="https://i.imgur.com/j40IiHq.png" width="90%"></div> > 再觀察一次網路參數,連線成功::tada:: ```bash $ifconfig ``` ><div class="flex-container"><img src="https://i.imgur.com/z1cKHld.png" width="90%"></div> #### 方法二 : 修改 /network/interfaces * 步驟一 : 所在的區域必須擁有網路(無線分享器WIFI或是有線分享器)。 * 步驟二 : 設定你的WIFI名稱與密碼(名稱必須完全一致) > ```bash > $sudo nano /etc/network/interfaces > ``` > <div class="flex-container"><img src="https://i.imgur.com/TVB7EEy.png" width="80%"></div> > <br/> > > ::: info > 輸入完成後按下Ctrl+O(英文O) → Enter → Ctrl+X重新開機等候數分鐘約5~10分鐘,樹莓派就會自行連上WIFI > ::: * 步驟三 : **重新開機**後檢查連線是否成功,也可以隨便開個網頁來看看 > ```bash > $ifconfig > ``` ><div class="flex-container"><img src="https://i.imgur.com/PJYqzlR.jpg" width="80%"></div> > <br/> ## 遠端連線 ### ssh 就是secure shell,透過網路連線到其他台主機上。 * 步驟一 : 我們首先要獲得Raspberry pi的ip address >網路的話可以連wifi,也可以把網路線連接在電腦上或路由器上,在terminal輸入ifconfig可以得到目前的ip address。 > > ```bash > $ifconfig > ``` > 此範例用的是wlan0(wifi)的網路 ><div class="flex-container"><img src="https://i.imgur.com/PJYqzlR.jpg" width="80%"></div> > <br/> * 步驟二 : 接下來要啟用ssh >從2016年底開始,Raspberry pi預設ssh都是關閉的,所以我們要先前往設定啟用它。 > > -偏好設定>Raspberry Pi 設定 > > <div class="flex-container"><img src="https://i.imgur.com/RR5yb3v.png" width="80%"></div> > <br/> > -啟用SSH > <div class="flex-container"><img src="https://i.imgur.com/klZum6H.png" width="80%"></div> > <br/> > > :::info > 也可以透過樹梅派的terminal打開它,輸入: > ```bash > $sudo raspi-config > ``` > -選擇Interface Options > <div class="flex-container"><img src="https://i.imgur.com/4wOfRFH.png" width="80%"></div><br/> > -選擇ssh > <div class="flex-container"><img src="https://i.imgur.com/SKaZxy3.png" width="80%"></div><br/> > -選擇enable後它就會告訴你SSH server已經啟用了 > <div class="flex-container"><img src="https://i.imgur.com/E4oMaag.png" width="80%"></div><br/> > ::: * 步驟三 : 下載[putty](https://the.earth.li/~sgtatham/putty/latest/w64/putty.exe) ><div class="flex-container"><img src="https://i.imgur.com/V0S08Gb.png" width="80%"></div><br/> > - 回到我們的電腦,我們已經獲得ip address,也啟用ssh,開啟putty,輸入相對應的IP位置後便完成後就可以遠端控制Raspberry pi了。 > <div class="flex-container"><img src="https://i.imgur.com/osj781Y.png" width="80%"></div><br/> > > :::warning > 預設帳號是 **pi** > 預設密碼是 **raspberry** (密碼是盲打喔 不是鍵盤壞掉) > ::: > 完成 ::tada:: > <div class="flex-container"><img src="https://i.imgur.com/CQkebu2.png" width="80%"></div><br/> ### VNC VNC是一個遠端桌面的軟體,分成我們的VNC Server(Raspberry pi),與VNC Viewer(筆電端)。 直接從樹莓派設定可以看到系統預設的VNC伺服器也不見了,也不是消失無蹤,而是預設不啟動了。此時想以VNC操控,就會失敗。 <div class="flex-container"><img src="https://i.imgur.com/D1Po6DF.png" width="50%"></div><br/> 不過只要自己在命令列下打指令,啟動TightVNC伺服器: * 步驟一 : 透過putty連線下開啟vnc的指令(也可以直接在樹莓派的terminal下指令) > ```bash > $tightvncserver > ``` > <div class="flex-container"><img src="https://i.imgur.com/fb5qSkh.png" width="80%"></div><br/> > * 步驟二 : 在筆電上下載[VNC Viewer](https://www.realvnc.com/en/connect/download/viewer/windows/)進行連線 > -在此下載的是windows版本 > <div class="flex-container"><img src="https://i.imgur.com/PqXFgG4.png" width="80%"></div></br> > -完成後開啟執行檔 > <div class="flex-container"><img src="https://i.imgur.com/JLxsfeo.png" width="80%"></div></br> > -建立連線設定 >File>New connection... > <div class="flex-container"><img src="https://i.imgur.com/DGxahJy.png" width="80%"></div></br> > > :::info > VNC Server : 樹莓派IP加上 **:1** > (簡單的說:0代表實體連接的螢幕,而剛剛的指令會開出另一個螢幕:1。) > Name : 隨意取名,方便辨識 > ::: > > -建立完成,點擊右鍵兩下、輸入密碼就能看到連線畫面 :tada: > <div class="flex-container"><img src="https://i.imgur.com/yDCKzAx.gif" width="80%"></div></br> > ## 中文化 ### 介面中文化 * 步驟一 : 在左上角按「Raspberry 圖案」 > Preferences > Raspberry Pi Configuration > <div class="flex-container"><img src="https://i.imgur.com/9CRRDpU.png" width="100%"></div></br> * 步驟二 : Set Locale... **Language :** zh(Chinese) **Country :** TW(Taiwan) **Character Set :** UTF 8 > <div class="flex-container"><img src="https://i.imgur.com/KW8Toa8.jpg" width="100%"></div></br> > * 步驟三 : 重新開機 > <div class="flex-container"><img src="https://i.imgur.com/6Mcxs80.png" width="80%"></div></br> 完成啦 :tada: > <div class="flex-container"><img src="https://i.imgur.com/O2isX8W.jpg" width="100%"></div> ### 中文輸入法 #### 下載輸入法 * 步驟一 : 點選開始功能表的 偏好設定/Add/Remove Software > <div class="flex-container"><img src="https://i.imgur.com/bNvzgrb.png" width="80%"></div> * 步驟二 : 在搜尋欄中輸入<font color="red">scim-chewing</font> > <div class="flex-container"><img src="https://i.imgur.com/aem0RTY.png" width="80%"></div> * 步驟三 : 勾選最下面兩個選項,按下Apply,系統會要求輸入設定時預設的管理者密碼 【Chewing IM engine module for SCIM】 【Chinese input method data tables for SCIM platform】 > <div class="flex-container"><img src="https://i.imgur.com/X0AzrG3.png" width="80%"></div> * 步驟四 : 系統會將相關的應用程式工具一併勾選,按下OK鍵 > <div class="flex-container"><img src="https://i.imgur.com/T3qyJtZ.png" width="80%"></div> #### 設定輸入法介面的切換鍵 * 步驟一 : 點選 開始功能表/偏好設定/SCIM Input Method(SCIM輸入法框架) > <div class="flex-container"><img src="https://i.imgur.com/aFeBVN9.png" width="80%"></div> * 步驟二 : 點選**介面(前端)設定**,設定輸入法的切換鍵與快速鍵,設定切換下一種輸入法的快速鍵(...) > <div class="flex-container"><img src="https://i.imgur.com/xef7bxX.png" width="80%"></div> * 步驟三 : 點選【...】符號 > <div class="flex-container"><img src="https://i.imgur.com/6UP2w5u.png" width="80%"></div> * 步驟四 : 再按一下鍵盤上的左側【Shift】按鍵 > <div class="flex-container"><img src="https://i.imgur.com/uvWwVVF.png" width="50%"></div> * 步驟五 : 在空白欄裡會出現「Shift_L」,點選<b><font color="blue">+</font></b>新增至選定的按鍵欄位中 > <div class="flex-container"><img src="https://i.imgur.com/LFlyyLO.png" width="80%"></div> ><br> > <div class="flex-container"><img src="https://i.imgur.com/R2Uxo4p.png" width="80%"></div> * 步驟六 : 這樣就完成切換至下一種輸入法快速鍵的設定,記得要點選 ✔ > <div class="flex-container"><img src="https://i.imgur.com/ooxobqn.png" width="80%"></div> #### 輸入法引擎設定 * 步驟一 : 點選 輸入法引擎/全域設定 > <div class="flex-container"><img src="https://i.imgur.com/3gPv6wb.png" width="80%"></div> * 步驟二 : 取消簡體中文項目的勾選(需要則保留),勾選自己常用繁體中文的輸入法、其他語文項目,點選✔ > <div class="flex-container"><img src="https://i.imgur.com/SKFsUof.png" width="80%"></div> * 步驟三 : 新增完成關閉設定時會要求重新啟動電腦 > <div class="flex-container"><img src="https://i.imgur.com/lDMG44O.png" width="80%"></div> * 步驟四 : 右上角會出現小鍵盤,完成啦 ::tada:: > <div class="flex-container"><img src="https://i.imgur.com/bgGjVoL.png" width="80%"></div> > <br> > <div class="flex-container"><img src="https://i.imgur.com/I0sFikD.gif" width="80%"></div> # 程式範例 ## GPIO <div class="flex-container"><img src="https://i.imgur.com/24cEkJS.png" width="50%"></div> > GPIO(General Purpose I/O Ports)意思是通用型輸入/輸出介面,也就是一些針腳可以通過它們輸出高電位或者低電位,可以供使用者由程式控制自由使用,與裝置進行通訊,達到控制裝置的目的。 > > 既然一個針腳可以用於輸入、輸出或其他特殊功能,那麼一定有暫存器用來選擇這些功能。 > > 對於輸入,一定可以透過讀取某個暫存器來確定針腳電位的高低;對於輸出,一定可以透過寫入某個暫存器來讓這個針腳輸出高電位或者低電位;對於其他特殊功能,則有另外的暫存器來控制它們,所以掌握了 GPIO 就相當於掌握了硬體的控制。 <div class="flex-container"><img src="https://i.imgur.com/wUfYzs3.png" width="100%"></div> </br> > 這裡可以看到有二種編號規則,分別是紅框內的 BOARD 編號規則,與紅框外的 BCM 編號規則。 ## LED發光二極體的控制實作 ### 控制單科LED閃爍練習 程式範例 : [led_single.py](https://drive.google.com/drive/folders/1glqcCGJ8rV3s-mAqVNVvJSNdwEKJ0erf?usp=sharing) > 開始撰寫程式碼: > ```bash > $nano /home/pi/led_single.py > ``` > ```python= > #匯入模組 > import time > import RPi.GPIO as GPIO > > #宣告設定 > GPIO.setwarnings(False) > GPIO.setmode(GPIO.BCM) > GPIO.setup(4, GPIO.OUT) > > #主程式區 > while True: > GPIO.output(4,1) > time.sleep(1) > GPIO.output(4,0) > time.sleep(1) > ``` > > * 匯入模組 > <font color="orange">import time </font>: 匯入時間模組,要完成閃爍效果,需要用到時間暫停的技巧。 > <font color="orange">import RPi.GPIO as GPIO </font>: 匯入RPi.GPIO模組物件,用於控制Raspberry Pi GPIO引腳。 > <div class="flex-container"><img src="https://i.imgur.com/VfiaNCw.png" width="80%"></div> > > * 宣告設定 > <font color="orange">setwarnings(False) </font>: 在執行過程中將所有警告提示關閉(False)。 > <font color="orange">setmode(GPIO.BCM) </font>: 設定模式 > &nbsp;&nbsp; -- GPIO.BCM : 使用GPIO編號 > &nbsp;&nbsp; -- GPIO.BOARD : 使用電路板腳位(pin的)編號 > <font color="orange">setup(4, GPIO.OUT) </font>: 設定GPIO.4(BOARD模式7)作為輸出(Output)腳位 > * 主程式區 > 透過無窮迴圈讓LED燈反覆閃爍,若要停用則按<font color="red">Ctrl+C</font>強制停止。 > <font color="orange">GPIO.output(4,1) </font>: (對應腳位,電位),1代表輸出高電位(High)的3.3V信號使LED點亮,0代表輸出低電位(Low)的0V信號使LED熄滅。 > <font color="orange">time.sleep(1) </font>: 利用第2行的時間模組,將時間暫停1秒,sleep()方法暫停執行給定秒數。 電路圖 : > <div class="flex-container"><img src="https://i.imgur.com/ukuAVhF.png" width="100%"></div> </br> ### LED按鍵控制練習: 按著才會亮 程式範例 : [led_switch.py](https://drive.google.com/drive/folders/1glqcCGJ8rV3s-mAqVNVvJSNdwEKJ0erf?usp=sharing) > ```python= > import RPi.GPIO as GPIO > import time > GPIO.setwarnings(False) > GPIO.setmode(GPIO.BCM) > GPIO.setup(4, GPIO.OUT) > GPIO.setup(17, GPIO.IN) > > while True: > value01 = GPIO.input(17) > GPIO.output(4, value01) > time.sleep(0.1) > ``` ### LED按鍵控制練習: 按一下亮,按一下滅 程式範例 : [led_switch_on_off.py](https://drive.google.com/drive/folders/1glqcCGJ8rV3s-mAqVNVvJSNdwEKJ0erf?usp=sharing) > ```python= > import RPi.GPIO as GPIO > import time > > GPIO.setwarnings(False) > GPIO.setmode(GPIO.BCM) > GPIO.setup(4, GPIO.OUT) > GPIO.setup(17, GPIO.IN) > > led = 0 > > '''def my_callback(channel): > if led == 0: > led = 1 > GPIO.output(4, led) > else: > led = 0 > GPIO.output(4, led)''' > > GPIO.add_event_detect(17, GPIO.RISING) > #GPIO.add_event_callback(17, my_callback) > > while(True): > if GPIO.event_detected(17): > print('Button pressed') > if led == 0: > led = 1 > GPIO.output(4, led) #(pin,電位高低) > else: > led = 0 > GPIO.output(4, led) > ``` 電路圖 : > <div class="flex-container"><img src="https://i.imgur.com/XrMDyNH.png" width="100%"></div> </br> ### PWM範例 : LED亮度變化 暗到亮 使用硬體 PWM 可以達到更精準的控制效果,對系統的負擔也小了許多。 而樹莓派支援硬體PWM的腳位,分別是 BCM 編號 12, 13, 18, 19 的四隻腳位。 儘管有四隻腳位支援硬體 PWM 功能,但是卻只有兩個頻道 (Channel)。 其中 12/18 屬於同一個頻道 (Channel 0)、而 13/19 則同屬於另外一個頻道 (Channel 1)。 ### PWM範例 : LED漸亮 程式範例 : [led_pwm1.py](https://drive.google.com/drive/folders/1glqcCGJ8rV3s-mAqVNVvJSNdwEKJ0erf?usp=sharing) **Duty Cycle**(工作週期,高電位佔用整個波形周期的比例),下圖分別呈現工作週期為 50% 與 25% 時的電位波形。 <div class="flex-container"><img src="https://i.imgur.com/piQ0lr4.png" width="80%"></div> 在控制 LED 燈泡方面,只要記得工作週期越大燈泡就越亮,而工作週期越小時燈泡就越暗。 > ```python= > import time > import RPi.GPIO as GPIO > > GPIO.setwarnings(False) > GPIO.setmode(GPIO.BCM) > GPIO.setup(4, GPIO.OUT) > > #GPIO.PWM(GPIO接脚,頻率設定(Hz)) > p1 = GPIO.PWM(4, 1000) > #開始PWM, Duty Cycle(工作週期,表示在一個週期之中,高電位持續時間的比例)為0% > p1.start(0) > > while True: > #dc範圍 : 1~100,步長為5 > for dc in range(1,101,5): > #設定工作週期進而改變LED燈泡的亮度,dc單位為赫茲(Hz) > #工作週期寬度:5% →10% → 15%...→ 100%,即可完成漸亮的效果 > p1.ChangeDutyCycle(dc) > time.sleep(0.2) > ``` 電路圖 : > <div class="flex-container"><img src="https://i.imgur.com/ukuAVhF.png" width="100%"></div> </br> ### PWM範例 : LED閃爍頻率慢到快 程式範例 : [led_pwm2.py](https://drive.google.com/drive/folders/1glqcCGJ8rV3s-mAqVNVvJSNdwEKJ0erf?usp=sharing) > ```python= > import time > import RPi.GPIO as GPIO > > GPIO.setwarnings(False) > GPIO.setmode(GPIO.BCM) > GPIO.setup(4, GPIO.OUT) > > p2 = GPIO.PWM(4, 50) #(GPIO接脚,頻率設定(Hz)) > p2.start(50)#開始PWM, Duty Cycle(工作週期,高電位佔用整個波形周期的比例)為50% > > while True: > for dc in range(5,101,5): #dc範圍 : 5~100,步長為5 > p2.ChangeFrequency(dc)#設置新的頻率 > time.sleep(1) > ``` 電路圖 : > <div class="flex-container"><img src="https://i.imgur.com/ukuAVhF.png" width="100%"></div> </br> ## 超音波感測器 <div class="flex-container"><img src="https://i.imgur.com/4ew1u51.png" width="30%"></div> </br> 超音波模組HC-SR04,算是常見的模組,特別是用在智慧車等專案中,用來測量前方障礙物的距離。 它的運作原理很簡單,模組會送出8個40khz的聲波,如果前方有障礙物,信號就會返回,模組收到信號後,再利用返回的時間,去計算該障礙的距離。 常見的HC-SR04都有4個腳,除了VCC和GND以外,Trig就是發送訊號,Echo就是接收返回的訊號。然後我們就能利用一發一收,去算出中間的距離了。 ### 範例程式 : 測距儀 程式範例 : [distance.py](https://drive.google.com/drive/folders/1glqcCGJ8rV3s-mAqVNVvJSNdwEKJ0erf?usp=sharing) > ```python= > import time, RPi.GPIO as GPIO > > GPIO_TRIGGER = 24 #設定觸發腳位編號名稱,方便未來變更腳位 > GPIO_ECHO = 25 #設定迴聲腳位編號名稱 > GPIO.setwarnings(False) #關閉警告提示 > GPIO.setmode(GPIO.BCM) #設定trigger為輸出腳位 > GPIO.setup(GPIO_TRIGGER, GPIO.OUT) #設定echo為輸入腳位 > GPIO.setup(GPIO_ECHO, GPIO.IN) > > def measure(): > GPIO.output(GPIO_TRIGGER, False) #設定觸發腳位為低電位,準備開始觸發 > time.sleep(0.5) > GPIO.output(GPIO_TRIGGER, True) #設定觸發腳位為高電位,開始觸發 > time.sleep(0.00001) > GPIO.output(GPIO_TRIGGER, False) #設定觸發腳位為低電位,停止觸 > start = time.time() > while GPIO.input(GPIO_ECHO) == 0: #當echo=0再開始計算時間 > start = time.time() > while GPIO.input(GPIO_ECHO) == 1: #當echo=1紀錄收到停止的時間 > stop = time.time() > elapsed = stop - start #計算echo脈波寬度 > distance = elapsed * 34300 #換算echo實際來回的總距離(cm/s) > distance = distance / 2 #來回除以2,即為與待測物的距離 > return distance > > print("Ultrasonic Measurement") > while 1: > cm = measure() > print("Distance : %.1f cm" % cm) > ``` > 實作結果 : > <div class="flex-container"><img src="https://i.imgur.com/cR220Eh.gif" width="100%"></div></br> > > 電路圖 : > 使用杜邦線將工作電壓(Vcc)接5V、接地(GND)接GND、觸發(Tig)接GPIO.24、迴聲(Echo)接GPIO.25 > <div class="flex-container"><img src="https://i.imgur.com/sfqQ1Y4.png" width="100%"></div> </br> ### 範例程式 : 測量平均值距離 程式範例 : [ultrasonic_distance_average.py](https://drive.google.com/drive/folders/1glqcCGJ8rV3s-mAqVNVvJSNdwEKJ0erf?usp=sharing) > ```python= > import time, RPi.GPIO as GPIO > > GPIO_TRIGGER = 24 > GPIO_ECHO = 25 > GPIO.setwarnings(False) > GPIO.setmode(GPIO.BCM) > GPIO.setup(GPIO_TRIGGER, GPIO.OUT) > GPIO.setup(GPIO_ECHO, GPIO.IN) > > def measure(): > GPIO.output(GPIO_TRIGGER, False) > time.sleep(0.5) > GPIO.output(GPIO_TRIGGER, True) > time.sleep(0.00001) > GPIO.output(GPIO_TRIGGER, False) > start = time.time() > while GPIO.input(GPIO_ECHO) == 0: > start = time.time() > while GPIO.input(GPIO_ECHO) == 1: > stop = time.time() > elapsed = stop - start > distance = elapsed * 34300 > distance = distance / 2 > return distance > > #求平均三次的測量結果 > def measure_average(): > distance1=measure() > time.sleep(0.1) > distance2=measure() > time.sleep(0.1) > distance3=measure() > distance = (distance1 + distance2 + distance3) / 3 > return distance > > print("Ultrasonic Measurement") > try: #例外處理 > while True: > cm = measure_average() > print("Distance : %.1f cm" % cm) > time.sleep(1) #每隔一秒測試一次平均值 > except KeyboardInterrupt: #按Ctrl+C中斷 > GPIO.cleanup() #重置釋放GPIO,然後離開程式,防止下次執行其他程式可能發生仍然在使用中的錯誤 > ``` ## 人體紅外線感測器 <div class="flex-container"><img src="https://i.imgur.com/9KNrj5F.png" width="30%"><img src="https://i.imgur.com/TPBbHR7.png" width="30%"></div> <br> ### 範例程式 : 入侵偵測 程式範例 : [pir.py](https://drive.google.com/drive/folders/1glqcCGJ8rV3s-mAqVNVvJSNdwEKJ0erf?usp=sharing) > ```python= > import RPi.GPIO as GPIO > import time > > GPIO.setwarnings(False) > GPIO.setmode(GPIO.BCM) > GPIO.setup(13, GPIO.IN)#Read output from PIR motion sensor > GPIO.setup(4, GPIO.OUT)#LED output pin > try: > while True: > i=GPIO.input(13) > if i==0: #When output from motion sensor is LOW > print ("No intruders", i) > GPIO.output(4, 0)#Turn OFF LED > time.sleep(1) > elif i==1: #When output from motion sensor is HIGH > print ("Intruder detected",i) > GPIO.output(4, 1) #Turn ON LED > time.sleep(10) > except KeyboardInterrupt: > print("Bye Bye!") > finally: > GPIO.cleanup() > ``` > > 電路圖 : > <div class="flex-container"><img src="https://i.imgur.com/E8i3Ns2.png" width="100%"></div> </br> ## 伺服馬達(SERVO) <div class="flex-container"><img src="https://i.imgur.com/tvvmzSi.gif" width="50%"></div></br> > 伺服馬達(Servomotor)是對用於使用伺服機構的馬達(電動機)總稱。 > 伺服(Servo)一詞來自拉丁文"Servus",本為奴隸(Slave)之意,此指依照命令動作的意義。 > 所謂伺服系統,就是依照指示命令動作所構成的控制裝置,應用於馬達的伺服控制,將感測器裝在馬達與控制對象機器上,偵測結果會返回伺服放大器與指令值做比較。 ### 硬體方式 程式範例 : [servo_hardware.py](https://drive.google.com/drive/folders/1glqcCGJ8rV3s-mAqVNVvJSNdwEKJ0erf?usp=sharing) 之前透過RPIGPIO的PWM指令,以便讓LED漸亮,PWM是屬於**軟體模擬**控制,所以不限制特殊腳位編號,缺點是無法精準控制。而本範例特別匯入使用**pigpio**函式庫模組,PWM是屬於**硬體模擬**控制,有支援硬體PWM的腳位,分別是BCM編號12、13、18、19的四隻腳位而已,如果PWM使用其他腳位,執行時會出現<font color="red">pigpio.error:GPIO has no hardware PWM </font>錯誤。 > 在執行程式碼前,請在樹莓派上下載**pigpio**套件: > ```bash > $sudo apt-get install pigpio > ``` > 並且執行: > ```bash > $sudo pigpiod > ``` > 若未下載套件、執行套件.執行程式碼時會有以下的錯誤訊息產生: > :::danger > %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% > Can't connect to pigpio at localhost(8888) > > Did you start the pigpio daemon? E.g. sudo pigpiod > > Did you specify the correct Pi host/port in the environment > variables PIGPIO_ADDR/PIGPIO_PORT? > E.g. export PIGPIO_ADDR=soft, export PIGPIO_PORT=8888 > > Did you specify the correct Pi host/port in the > pigpio.pi() function? E.g. pigpio.pi('soft', 8888) > %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% > Traceback (most recent call last): > File "/home/pi/servo_hardware.py", line 14, in <module> > pi.hardware_PWM(PWMPIN, PWM_FREQ, update(90)) > File "/usr/lib/python2.7/dist-packages/pigpio.py", line 1964, in hardware_PWM > self.sl, _PI_CMD_HP, gpio, PWMfreq, 4, extents)) > File "/usr/lib/python2.7/dist-packages/pigpio.py", line 1006, in _pigpio_command_ext > sl.s.sendall(ext) > AttributeError: 'NoneType' object has no attribute 'sendall' > > ::: > 開始撰寫程式: > ```python= > import time > import sys #匯入系統模組 > import pigpio > > PWMPIN = 18 #使用GPIO.18腳位 > PWM_FREQ = 50 #PWM頻率設為50 > version = sys.version #讀取Python版本 > pi = pigpio.pi() #將pigpio命名為pi > > #將角度換算成PWM的工作週期 > def update(angle): > duty_cycle = int(500 * PWM_FREQ + (1900 * PWM_FREQ * angle / 180)) > return (duty_cycle) > > #主程式開始 > pi.hardware_PWM(PWMPIN, PWM_FREQ, update(90)) #初始值轉到90度的位置 > try: > while True: > if version[0] == '3': #判斷是否為python3 > text = input('Angle:') #輸入控制的角度 > else: > text = raw_input('Angle:') > angle = int(text) #轉換成數值 > if(angle >= 0 and angle <= 180): #如果介於0~180才轉動馬達 > dc = update(angle) > pi.hardware_PWM(PWMPIN, PWM_FREQ, dc) > except KeyboardInterrupt: #按下Ctrl+C中斷 > pass #不做任何動作 > finally: #最後 > pi.set_mode(PWMPIN, pigpio.INPUT) #恢復輸入模式離開 > ``` 電路圖 : > <div class="flex-container"><img src="https://i.imgur.com/EEInBJ5.png" width="100%"></div> </br> 實際操作 : > <div class="flex-container"><img src="https://i.imgur.com/cQYHlha.gif" width="100%"></div> </br> ### 軟體方式 程式範例 : [servo_software.py](https://drive.google.com/drive/folders/1glqcCGJ8rV3s-mAqVNVvJSNdwEKJ0erf?usp=sharing) >使用軟體來模擬PWM功能有一些缺點,因為執行PWM軟體模擬功能時,需要CPU不斷地計算時間訂控制波形,造成CPU資源部只要提供PWM軟體使用,還必須同時提供各式各樣的程式使用,所以很容易造成無法**即時**處理PWM功能,進而影響PWM輸出的波形。 一旦波形不正確,PWM也失去了精確性,造成伺服馬達可能無法定位到正確的角度。使用硬體PWM才可以達到更精準地控制效果,對系統的負擔比較小。 > > 在執行程式碼前,請在樹莓派上下載**pigpio**套件(載過的可以忽略): > ```bash > $sudo apt-get install pigpio > ``` > 並且執行(執行過的可以忽略): > ```bash > $sudo pigpiod > ``` > ```python= > import pigpio > import time > import sys > > PWMPIN = 27 #改接GPIO.27 > version = sys.version > pi = pigpio.pi() > > def update(angle): > duty_cycle = int(angle * 11.1 + 500.0) > return (duty_cycle) > > pi.set_servo_pulsewidth(PWMPIN, update(90)) > try: > while True: > if version[0] == '3': > text = input('Angle:') > else: > text = raw_input('Angle:') > angle = int(text) > if(angle >= 0 and angle <= 180): > dc=update(angle) > pi.set_servo_pulsewidth(PWMPIN, dc) > except KeyboardInterrupt: > pass > finally: > pi.set_mode(PWMPIN, pigpio.INPUT) > ``` 電路圖 : > <div class="flex-container"><img src="https://i.imgur.com/NGzSJRL.png" width="100%"></div> </br> ## DHT11 數位溫溼度感測模組的控制 <div class="flex-container"><img src="https://i.imgur.com/IOG9cIB.png" width="50%"></div></br> DHT11數位溫溼度感測模組屬於**數位輸入**,而非類比輸入。 溫度測量範圍為0-50度,測量誤差±2度,溼度測量範圍為20-95%,測量誤差±5,工作電壓5V。 DHT11可同時監測周圍環境的溫度與濕度的變化,價格低廉,經常使用於物聯網環境溫溼度監測。 ### 顯示溫溼度 程式範例 : [dht11.py、dht11_example.py](https://drive.google.com/drive/folders/1hK4MSnCZwmaflIqCppBL7PpFwAJSTcuK?usp=sharing) > dht11.py (做為副程式,用來模擬1線通信介面程式) > ```python= > import time > import RPi > > > class DHT11Result: > 'DHT11 sensor result returned by DHT11.read() method' > > ERR_NO_ERROR = 0 > ERR_MISSING_DATA = 1 > ERR_CRC = 2 > > error_code = ERR_NO_ERROR > temperature = -1 > humidity = -1 > > def __init__(self, error_code, temperature, humidity): > self.error_code = error_code > self.temperature = temperature > self.humidity = humidity > > def is_valid(self): > return self.error_code == DHT11Result.ERR_NO_ERROR > > > class DHT11: > 'DHT11 sensor reader class for Raspberry' > > __pin = 0 > > def __init__(self, pin): > self.__pin = pin > > def read(self): > RPi.GPIO.setup(self.__pin, RPi.GPIO.OUT) > > # send initial high > self.__send_and_sleep(RPi.GPIO.HIGH, 0.05) > > # pull down to low > self.__send_and_sleep(RPi.GPIO.LOW, 0.02) > > # change to input using pull up > RPi.GPIO.setup(self.__pin, RPi.GPIO.IN, RPi.GPIO.PUD_UP) > > # collect data into an array > data = self.__collect_input() > > # parse lengths of all data pull up periods > pull_up_lengths = self.__parse_data_pull_up_lengths(data) > > # if bit count mismatch, return error (4 byte data + 1 byte checksum) > if len(pull_up_lengths) != 40: > return DHT11Result(DHT11Result.ERR_MISSING_DATA, 0, 0) > > # calculate bits from lengths of the pull up periods > bits = self.__calculate_bits(pull_up_lengths) > > # we have the bits, calculate bytes > the_bytes = self.__bits_to_bytes(bits) > > # calculate checksum and check > checksum = self.__calculate_checksum(the_bytes) > if the_bytes[4] != checksum: > return DHT11Result(DHT11Result.ERR_CRC, 0, 0) > > # ok, we have valid data, return it > return DHT11Result(DHT11Result.ERR_NO_ERROR, the_bytes[2], the_bytes[0]) > > def __send_and_sleep(self, output, sleep): > RPi.GPIO.output(self.__pin, output) > time.sleep(sleep) > > def __collect_input(self): > # collect the data while unchanged found > unchanged_count = 0 > > # this is used to determine where is the end of the data > max_unchanged_count = 100 > > last = -1 > data = [] > while True: > current = RPi.GPIO.input(self.__pin) > data.append(current) > if last != current: > unchanged_count = 0 > last = current > else: > unchanged_count += 1 > if unchanged_count > max_unchanged_count: > break > > return data > > def __parse_data_pull_up_lengths(self, data): > STATE_INIT_PULL_DOWN = 1 > STATE_INIT_PULL_UP = 2 > STATE_DATA_FIRST_PULL_DOWN = 3 > STATE_DATA_PULL_UP = 4 > STATE_DATA_PULL_DOWN = 5 > > state = STATE_INIT_PULL_DOWN > > lengths = [] # will contain the lengths of data pull up periods > current_length = 0 # will contain the length of the previous period > > for i in range(len(data)): > > current = data[i] > current_length += 1 > > if state == STATE_INIT_PULL_DOWN: > if current == RPi.GPIO.LOW: > # ok, we got the initial pull down > state = STATE_INIT_PULL_UP > continue > else: > continue > if state == STATE_INIT_PULL_UP: > if current == RPi.GPIO.HIGH: > # ok, we got the initial pull up > state = STATE_DATA_FIRST_PULL_DOWN > continue > else: > continue > if state == STATE_DATA_FIRST_PULL_DOWN: > if current == RPi.GPIO.LOW: > # we have the initial pull down, the next will be the data pull up > state = STATE_DATA_PULL_UP > continue > else: > continue > if state == STATE_DATA_PULL_UP: > if current == RPi.GPIO.HIGH: > # data pulled up, the length of this pull up will determine whether it is 0 or 1 > current_length = 0 > state = STATE_DATA_PULL_DOWN > continue > else: > continue > if state == STATE_DATA_PULL_DOWN: > if current == RPi.GPIO.LOW: > # pulled down, we store the length of the previous pull up period > lengths.append(current_length) > state = STATE_DATA_PULL_UP > continue > else: > continue > > return lengths > > def __calculate_bits(self, pull_up_lengths): > # find shortest and longest period > shortest_pull_up = 1000 > longest_pull_up = 0 > > for i in range(0, len(pull_up_lengths)): > length = pull_up_lengths[i] > if length < shortest_pull_up: > shortest_pull_up = length > if length > longest_pull_up: > longest_pull_up = length > > # use the halfway to determine whether the period it is long or short > halfway = shortest_pull_up + (longest_pull_up - shortest_pull_up) / 2 > bits = [] > > for i in range(0, len(pull_up_lengths)): > bit = False > if pull_up_lengths[i] > halfway: > bit = True > bits.append(bit) > > return bits > > def __bits_to_bytes(self, bits): > the_bytes = [] > byte = 0 > > for i in range(0, len(bits)): > byte = byte << 1 > if (bits[i]): > byte = byte | 1 > else: > byte = byte | 0 > if ((i + 1) % 8 == 0): > the_bytes.append(byte) > byte = 0 > > return the_bytes > > def __calculate_checksum(self, the_bytes): > return the_bytes[0] + the_bytes[1] + the_bytes[2] + the_bytes[3] & 255 > ``` > dht11_example.py (主程式) > ```python= > #!/usr/bin/python3 > # -*- coding: utf-8 -*- > import RPi.GPIO as GPIO > import dht11 #匯入dht11.py副程式 > import time > import datetime #匯入日期時間模組套件 > > GPIO.setwarnings(False) > GPIO.setmode(GPIO.BCM) > GPIO.cleanup() > instance = dht11.DHT11(pin=18) #使用GPIO.18腳位 > > #主程式開始 > try: > while True: > result = instance.read() #讀取溫溼度結果 > if result.is_valid(): #如果讀值是有效才顯示 > print("目前監測的時間" + str(datetime.datetime.now())) #顯示目前系統時間 > print("目前溫度: %d 度C" % result.temperature) #顯示溫度 > print("目前濕度: %d %%" % result.humidity) #顯示濕度 > time.sleep(3) #間隔3秒取樣 > except KeyboardInterrupt: > print("Bye Bye!") > finally: > GPIO.cleanup() > ``` 電路圖: > <div class="flex-container"><img src="https://i.imgur.com/fOCO5ic.png" width="80%"></div></br> 執行主程式: > <div class="flex-container"><img src="https://i.imgur.com/r7HQbv7.gif" width="80%"></div> ## 火焰感測器模組 <div class="flex-container"><img src="https://i.imgur.com/AgY7YWS.png" width="30%"><img src="https://i.imgur.com/0mriIdm.png" width="50%"></div> 火焰感測器模組工作電壓 3V 或 5V 均可,利用紅外線對火焰非常敏感的特點,使用特製的紅外線接收管來檢測火焰,然後把火焰的亮度轉化為高低變化的電壓信號,使用打火機測試火焰距離為 80cm 以內,但火焰越大,測試距離越遠,探測角度約 60 度左右,越靠近火焰,AO 讀值越小,DO 則為高電位。一般常用做智慧居家的火焰警報等用途。 程式範例 : [fire_sensor.py、AnaloginOutSerial.ino](https://drive.google.com/drive/folders/1hrlduOXHv_QpuIWWndV349xnSpXMe0dK?usp=sharing) ### UART UART(Universal Asynchronous Receiver/Transmitter)是指通用非同步收發傳輸器,只允許兩個裝置直接對接,無法接更多裝置,除非使用 RS-422、RS-485 則可接多個裝置,基本傳送僅需利用 Tx 傳輸與 Rx 接收兩個接腳,跟 SPI 均屬於全雙工通訊,連接方式如下圖,由於速度不是很快,一般而言最高為 115.2Kbps,雖有更高速版本但不太普及,所以**不適合用在高速、大量傳輸上**。 <div class="flex-container"><img src="https://i.imgur.com/uCoXP13.png" width="50%"></div> </br> 接著程式範例是利用樹莓派的 UART 傳輸方式,讀取 Arduino 開發板的類比腳位數值。 > fire_sensor.py > ```python= > #!/usr/bin/python3 > # -*- coding: utf-8 -*- > import tkinter as tk > import serial # 匯入串列傳輸模組 > > def update_data(): # 建立資料更新副程式 > response = ser.readline() # 讀取串列傳輸的值 > now = response[:len(response) - 1] # 去掉最後面的換行字元 > label2.configure(text = now) # 顯示類比讀值(0~1023) > root.after(1, update_data) # 每隔1mS 呼叫update_data副程式 > > ser = serial.Serial("/dev/ttyACM0", 9600) # 設定串列傳輸裝置與傳輸速率 > root = tk.Tk() > root.wm_title("Arduino DEMO") > root.geometry("300x80+10+10") > label1 = tk.Label(text="UART", font = ("Times", 18)) > label1.pack() > label2 = tk.Label(text="", font = ("Times", 18)) > label2.pack() > update_data() > root.mainloop() > ser.close() # 關閉串列傳輸 > > ``` > AnaloginOutSerial.ino > ```arduino= > const int analogInPin = A0; > int sensorValue = 0; > void setup() { > Serial.begin(9600); > } > > void loop() { > sensorValue = analogRead(analogInPin); > Serial.println(sensorValue); > delay(2); > } > > ``` > * 找到A0腳位,根據感測器的腳位用杜邦線與arduino做連接 > <div class="flex-container"><img src="https://i.imgur.com/DqOue18.png" width="80%"></div></br> > > * 依序點選「軟體開發→ Arduino IDE」進入編輯環境 > <div class="flex-container"><img src="https://i.imgur.com/NhRl5Yt.png" width="80%"></div></br> > > * 撰寫完成,編譯並上傳資料 > <div class="flex-container"><img src="https://i.imgur.com/IBqadef.png" width="80%"></div></br> > > * 打開 Terminal,執行py檔 > > ```bash > $python3 /home/pi/fire_sensor.py > ``` > * 便會看到GUI畫面,顯示類比讀值 (測試時請小心喔!) > <div class="flex-container"><img src="https://i.imgur.com/MWh3eSy.gif" width="80%"></div></br> ## 從樹莓派控制 Arduino 輸出信號 利用樹莓派控制 Arduino 的 Pin13 腳位狀態,讓內建 LED 每隔 1 秒閃爍。 程式範例 : [led_control.py、ledOnOff.ino](https://drive.google.com/drive/folders/1hsrziYVtVaeiwk9dm6CWICJ4gxYR9voL?usp=sharing) led_control.py > ```python= > import serial > import time > > ser = serial.Serial('/dev/ttyACM0', 9600) > prevtime = time.time() # 設定目前時間到pretime變數 > tt = '0' > while 1: > if time.time() - prevtime > 1: # 當間隔超過1秒 > if tt == '0': > tt = '1' # 若之前輪出0,就改為輸出1 > else: > tt = '0' # 若之前輪出1,就改為輸出0 > ser.write(tt.encode()) > #由於使用 time.sleep 會讓 serial 當機,所以需利用 time time技巧做1秒間隔的閃爍 > prevtime = time.time() # 重新設定目前時間 > ``` ledOnOff.ino > ```arduino= > // These constants won't change. They're used to give names to the pins used: > const int analogInPin = A0; // Analog input pin that the potentiometer is attached to > int sensorValue = 0; > const int LedPin=13; > void setup() { > // initialize serial communications at 9600 bps: > Serial.begin(9600); > pinMode(LedPin,OUTPUT); > digitalWrite(LedPin,LOW); > } > > void loop() { > // read the analog in value: > sensorValue = analogRead(analogInPin); > Serial.println(sensorValue); > // wait 50 milliseconds before the next loop for the analog-to-digital > // converter to settle after the last reading: > delay(50); > if(Serial.available()>0){ > char comdata=Serial.read(); > if(comdata=='0'){ > digitalWrite(LedPin,LOW); > } > if(comdata=='1'){ > digitalWrite(LedPin,HIGH); > } > } > } > > ``` > * 依序點選「軟體開發→ Arduino IDE」進入編輯環境 > <div class="flex-container"><img src="https://i.imgur.com/NhRl5Yt.png" width="80%"></div></br> > > * 撰寫完成,編譯並上傳資料 > <div class="flex-container"><img src="https://i.imgur.com/ruH7Dee.png" width="80%"></div></br> > > * 打開 Terminal,執行py檔 > > ```bash > $python /home/pi/led_control.py > ``` > * 觀察 Arduino 閃爍變化的速度是否也跟著改變,亮紅燈的LED以及下方左側LED即為對應D13的LED。 > <div class="flex-container"><img src="https://i.imgur.com/gt1yry7.gif" width="80%"></div></br>