Slide 1

Slide 1 text

Raspberry Pi 遊戲機工作坊 - 從 GPIO 開始和世界連接 台灣樹莓派 1

Slide 2

Slide 2 text

CC (Creative Commons) 姓名標示 — 非商業性 — 相同方式分享 姓名標示 — 你必須給予 適當表彰、提供指向本授權 條款的連結,以及 指出(本作品的原始版本)是否已 被變更。你可以任何合理方式為前述表彰,但不得以 任何方式暗示授權人為你或你的使用方式背書。 非商業性 — 你不得將本素材進行商業目的之使 用。 相同方式分享 — 若你重混、轉換本素材,或依本 素材建立新素材,你必須依本素材的授權條款來 散布你的貢獻物。

Slide 3

Slide 3 text

關於我們 ● Raspberry Pi 官方經銷商 ● 專注 Raspberry Pi 應用與推廣 , 舉辦社群活動 3

Slide 4

Slide 4 text

分享 x 教學 ● COSCUP,MakerConf,PyCon,HKOSCon 講者 ● 投影片 https://speakerdeck.com/piepie_tw ● 程式碼 ● ● https://github.com/piepie-tw 4

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

本教學適合 ● ● ● ● ● ● ● ● ● ● ☑ Raspberry Pi 5B ☑ Raspberry Pi Zero 2W ☑ Raspberry Pi 4B ☑ Raspberry Pi 3B+ ☑ Raspberry Pi 3A+ ☑ Raspberry Pi Zero W ☑ Raspberry Pi 3B ☑ Raspberry Pi 2B ☑ Raspberry Pi B+ ☑ Raspberry Pi Model B 6

Slide 7

Slide 7 text

本次主題 ● Raspberry Pi GPIO 介紹 環境設定 ● 輸入 / 輸出 ● 數位 / 類比 ● 練習與實做 ● 7

Slide 8

Slide 8 text

目標 了解電子電路原理 ● 學習如何根據規格撰寫控制程式 ● 親手完成遊戲機 ● 8

Slide 9

Slide 9 text

今日環境 ● ● 硬體 :Raspberry Pi 5B 作業系統 :2026-06-18-raspios-trixiearm64-full.img ● 系統下載: https://reurl.cc/yWMryO ● 燒錄系統: https://reurl.cc/Vn1D6R 9

Slide 10

Slide 10 text

安裝今日所需套件 ● $ sudo apt update ● $ sudo apt remove python3-rpi.gpio ● ● $ sudo apt install -y python3-dev python3-pip libsdl1.2-dev vim $ sudo apt install -y python3-evdev python3-libevdev python3-rpi-lgpio python3-spidev 10

Slide 11

Slide 11 text

Raspberry Pi GPIO 介紹 11

Slide 12

Slide 12 text

什麼是 GPIO ? ● General Purpose Input Output ● GPIO 是一種可用軟體控制的數位訊號 http://www.tek.com/datasheet/tps2000b-series-digital-storage-oscilloscopes-datasheet 12

Slide 13

Slide 13 text

用軟體控制什麼 ? 決定是輸入還是輸出 ● 輸出:寫值到某根腳位 ● 輸入:從某根腳位讀值 ● 等待中斷 (interrupt) 的發生 ● ● 決定是正緣觸發還是負緣觸發 13

Slide 14

Slide 14 text

GPIO 腳位在哪裡? Z 字型的腳位編號 Pin1 Pin3 Pin25 http://www.raspberrypi-spy.co.uk/ Z Pin2 Pin4 Pin26 14

Slide 15

Slide 15 text

幾個 GPIO 的數字 ● GPIO 高電位輸出為 3.3V ● GPIO 容忍輸入電位為 3.3V ● 單一 Pin 輸出電流為 3mA-16mA ● 全部 Pin 輸出總和小於 50mA ● GPIO 輸入低電位為小於 0.8V, 高電位為大於 1.3V https://www.scribd.com/doc/101830961/GPIO-Pads-Control2 15

Slide 16

Slide 16 text

如何控制 Raspberry Pi 的 GPIO ? ● C ● C + wiringPi ● C# ● Ruby ● Perl ● Python ● Scratch ● Java Pi4J Library ● Shell script 16

Slide 17

Slide 17 text

GPIO Benchmark ● Python + RPi.GPIO = 70 kHz ● C + BCM 2835 = 5.4 MHz ● Ruby + wiringpi bindings = 21 kHz http://www.tek.com/datasheet/tps2000b-series-digital-storage-oscilloscopes-datasheet 17

Slide 18

Slide 18 text

Python + GPIO 18

Slide 19

Slide 19 text

Python3 五分鐘速成 ● 變數 , 物件 , 型別 , 註解 模組 ● 縮排 ● 迴圈 ● 條件判斷 ● 函式 ● 19

Slide 20

Slide 20 text

變數 , 物件 , 型別 , 註解 ● 動態型別 (dynamic typing) # 這是註解 i = 3 # 變數 i 指到數字物件 3 i = [1, 2, 3, 4, 5]# 變數 i 指到串列物件 print(i[2]) i = "abcde" print(i[2]) # 印出串列中第三個元素 # 變數 i 指到字串物件 # 印出字串中第三個元素 20

Slide 21

Slide 21 text

模組 # import MODULE import RPi.GPIO # import MODULE as ALIAS import RPi.GPIO as GPIO 21

Slide 22

Slide 22 text

縮排 用縮排取代大括號 ● 程式碼的區塊是用縮排分隔 ● ● 不使用 tab, 使用空白鍵 ● 常見縮排為 4 個空白鍵 22

Slide 23

Slide 23 text

迴圈 ● 自動迭代 (iterator) for i in range(start, stop[, step]): process for i in range(0, 11, 5): print(iU+0029 23

Slide 24

Slide 24 text

條件判斷 if condition_1: process_1 elif condition_2: process_2 else: process_3 process_4 24

Slide 25

Slide 25 text

函式 def function_name(): process def function_name(param_name): process def function_name(param_name = 3): process 25

Slide 26

Slide 26 text

兩種執行 Python 的方法 ● ● 1. 存成檔案以後 , 用 python 執行 ● $ nano test.py ● $ python3 test.py 2. 進到互動模式 , 可直接看輸出結果 ● ● ● ● $ python3 Python 3.11.2 (main, Mar 13 2023, 12:18:29) [GCC 12.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> 26

Slide 27

Slide 27 text

電子入門套件 ● 紅 / 黃 / 綠 LED x2 ● 1/4W 電阻 ,1Kx5,2Kx5 ● 830 洞大型麵包板 x1 ● 按鍵 x4 ● 蜂鳴器 x2 ● 人體紅外線感測器 (PIR) x1 ● 傾斜開關 x1 ● MCP3008 ADC IC x1 ● 光敏電阻 x1 ● XY 搖桿 x1 ● HC-SR04 超音波距離感測器 ● 10K 可變電阻 ● 20pin 公對公 / 公對母 / 母對母排線 x1 27

Slide 28

Slide 28 text

本套件相容於全系列 Raspberry Pi 購買 : https://www.piepie.com.tw/buy/2557/ 28

Slide 29

Slide 29 text

數位輸出 29

Slide 30

Slide 30 text

實驗 1: 硬體的 Hello World 目的 : 從硬體到軟體的思維 30

Slide 31

Slide 31 text

LED 發光二極體 ● 單向導通 ● 省電 ● 短腳接負極 GND 長腳接正極 Vcc http://upload.wikimedia.org/wikipedia/commons/c/c8/5mm_Red_LED.jpg 31

Slide 32

Slide 32 text

電路一分鐘速成 ● 電路組成元件 : 電源、導線、負載 ● 閉路 : 當三者形成一完整路徑 , 有電流經過電路 I I V R V R I ● 歐姆定律 : 導體兩端的電壓與通過的電流成正比 ● V=IxR https://zh.wikipedia.org/wiki/ 电路 32

Slide 33

Slide 33 text

Raspberry Pi + LED 直接插入嗎 ? 先看看規格吧 33

Slide 34

Slide 34 text

LED 的特性 ● VF: 順向電壓 ● IF: 在順向電壓下的安全電流 https://learn.adafruit.com/all-about-leds/forward-voltage-and-kvl 34

Slide 35

Slide 35 text

如何解讀? ● 在順向電壓下一般的 LED 能承受的安全電流是 20mA ● 由於順向電壓 (Typical) 為 1.85V ● Raspberry Pi 的 GPIO 腳位能提供 3.3V ● 計算公式:電阻 = 電壓 / 電流 R =V/I R =(3.3-1.85)/0.02=72.5 歐姆 ● 表示最小要接 72.5 歐姆的電阻 , 才能避免 LED 燒毀 35

Slide 36

Slide 36 text

電阻阻值計算 四環:右側為金或銀 1K= 棕黑黑棕 ( 棕 ) 2K= 紅黑黑棕 ( 棕 ) 五環:前四環很靠近 www.digikey.tw/tw/zht/mkt/5-band-resistors.html 36

Slide 37

Slide 37 text

要接哪一個腳位? 37

Slide 38

Slide 38 text

要接哪一個腳位? 目標 : 一隻腳接地 , 一隻腳給電 38

Slide 39

Slide 39 text

接線圖 LED 長腳 (RED) 短腳 (BLACK) RPi Pin12 (GPIO18) Pin6 (Ground) 1k 電阻 : 棕黑黑棕 ( 棕 ) 39

Slide 40

Slide 40 text

接線圖 LED 長腳 (RED) 短腳 (BLACK) RPi Pin12 (GPIO18) Pin6 (Ground) 1k 電阻 : 棕黑黑棕 ( 棕 ) 40

Slide 41

Slide 41 text

麵包板的種類 https://goo.gl/JipVgH 41

Slide 42

Slide 42 text

麵包板的使用 https://www.slideshare.net/eoinbrazil/imediaarduino08

Slide 43

Slide 43 text

使用麵包板方便多了 LED 長腳 (RED) 短腳 (BLACK) RPi Pin12 (GPIO18) Pin6 (Ground) 1k 電阻 43

Slide 44

Slide 44 text

不會亮嗎? 因為你沒寫程式阿 ● 試試看這樣接 44

Slide 45

Slide 45 text

各腳位的意義 https://goo.gl/f2rPpN 45

Slide 46

Slide 46 text

開始用 Python 控制 GPIO 吧 46

Slide 47

Slide 47 text

Python Code 基本流程 ● 載入模組 (Import module) ● 選擇編號系統 (Define pin numbering) ● 定義腳位 (Setup up a channel) ● 讀取輸入 / 寫入輸出 (Input/Output) ● 清理 (Cleanup) http://code.google.com/p/raspberry-gpio-python/wiki/BasicUsage 47

Slide 48

Slide 48 text

一個實際的範例 #!/usr/bin/python3 ● import RPi.GPIO as GPIO # Import module import time 以下都是使用別名 (alias) GPIO.setmode(GPIO.BOARD) # Define pin numbering LED_PIN = 12 GPIO.setup(LED_PIN, GPIO.OUT) # Setup up a channel print("LED is on") GPIO.output(LED_PIN, GPIO.HIGH) # Input/Output status time.sleep(3) GPIO.cleanup() # Cleanup 48

Slide 49

Slide 49 text

DEMO led_on.py $ python3 led_on.py 49

Slide 50

Slide 50 text

nano 編輯器使用 使用 :nano < 檔名 , 例如 led_on.py> 離開 :Ctrl + x > 令存新檔 :y > 不存離開 :n > 離開 :Ctrl + c 50

Slide 51

Slide 51 text

執行方式 $ cd ~ $ git clone https://github.com/piepie-tw/gpio-game-console $ cd ~/gpio-game-console $ cd 01-led_on $ python3 led_on.py 讀寫 GPIO 會存取 /dev/mem, 需 root 權限 (2015-09-24 以後的 image 可以用一般使用者身份執行 ) 51

Slide 52

Slide 52 text

更多 RPi.GPIO 的使用方法 ● Wiki ● ● Code ● ● http://sourceforge.net/p/raspberry-gpio-python/wiki/ Home/ http://sourceforge.net/p/raspberry-gpio-python/code/ ci/default/tree/ Reference detail ● http://elinux.org/RPi_Low-level_peripherals ● http://elinux.org/RPi_BCM2835_GPIOs ● http://www.raspberrypi.org/wp-content/uploads/2012/02/ 52 BCM2835-ARM-Peripherals.pdf

Slide 53

Slide 53 text

實驗 2: 控制 LED 閃爍 目的 : 熟悉 Python 語法 53

Slide 54

Slide 54 text

一樣的接線圖 LED 長腳 (RED) 短腳 (BLACK) RPi Pin12 (GPIO18) Pin6 (Ground) 1k 電阻 54

Slide 55

Slide 55 text

永不停止的 while 迴圈 - 按 Ctrl+c 跳出迴圈 GPIO.setmode(GPIO.BOARD) LED_PIN = 12 GPIO.setup(LED_PIN, GPIO.OUT) while True: print("LED is on") GPIO.output(LED_PIN, GPIO.HIGH) time.sleep(1) print("LED is off") GPIO.output(LED_PIN, GPIO.LOW) time.sleep(1) 55 GPIO.cleanup()

Slide 56

Slide 56 text

DEMO led_blink_warning.py $ cd ~/gpio-game-console $ cd 02_1-led_blink_warning $ python3 led_blink_warning.py 56

Slide 57

Slide 57 text

RuntimeWarning: This channel is already in use, continuing anyway. Use GPIO.setwarnings(False) to disable warnings. 說明: 該警告在 Bookworm 之後版本是使用 rpi-lgpio 套件,因此不會看到。 因為舊版 RPI.GPIO 是將暫存寄直接映射到記憶體後操作硬體, 而 rpi-lgpio 是採用 Linux 核心標準的 GPIO character device 介面。 但建議使用者還是注意 GPIO.cleanup() 函式的使用時機和程式邏輯。57

Slide 58

Slide 58 text

為什麼出現 Warning ? 說明: 該警告在 Bookworm 之後版本是使用 rpi-lgpio 套件,因此不會看到。 因為舊版 RPI.GPIO 是將暫存寄直接映射到記憶體後操作硬體, 而 rpi-lgpio 是採用 Linux 核心標準的 GPIO character device 介面。 但建議使用者還是注意 GPIO.cleanup() 函式的使用時機和程式邏輯。58

Slide 59

Slide 59 text

程式何時會結束 ? 在正常情況下執行完畢結束 ● 遇到錯誤跳出 ● ● 受到中斷停止 ( 收到終止訊號 , 例如 Ctrl+c) 59

Slide 60

Slide 60 text

接住例外 try: while True: print "LED is on" GPIO.output(LED_PIN, GPIO.HIGH) time.sleep(1) print("LED is off") GPIO.output(LED_PIN, GPIO.LOW) time.sleep(1) except KeyboardInterrupt: print("Exception: KeyboardInterrupt") finally: GPIO.cleanup() 60

Slide 61

Slide 61 text

DEMO led_blink.py $ cd ~/gpio-game-console $ cd 02_2-led_blink $ python3 led_blink.py 61

Slide 62

Slide 62 text

實驗 3: 用 LED 做交通號誌 目的 : 結構化程式設計 62

Slide 63

Slide 63 text

設計一個紅綠燈 ● 紅 , 黃 , 綠燈依序亮燈 ● 紅燈亮 4 秒 , 黃燈亮 2 秒 , 綠燈亮 4 秒 http://www.clipartbest.com/traffic-light-photo 63

Slide 64

Slide 64 text

接線圖 64

Slide 65

Slide 65 text

DEMO traffic_light_nonstructure.py $ cd ~/gpio-game-console $ cd 03_1-traffic_light_nonstructure $ python3 traffic_light_nonstructure.py 65

Slide 66

Slide 66 text

把亮燈拿到外面 def TrafficLight(pin, duration): GPIO.output(pin, GPIO.HIGH) time.sleep(duration) GPIO.output(pin, GPIO.LOW) try : while True: TrafficLight(RED_PIN, 4); TrafficLight(YEL_PIN, 2); TrafficLight(GRN_PIN, 4); finally: GPIO.cleanup() 66

Slide 67

Slide 67 text

DEMO traffic_light.py $ cd ~/gpio-game-console $ cd 03_2-traffic_light $ python3 traffic_light.py 67

Slide 68

Slide 68 text

數位輸入 68

Slide 69

Slide 69 text

實驗 4: 讀取按鍵輸入 目的 : 了解硬體和軟體的差異 69

Slide 70

Slide 70 text

按鍵 Button / 開關 Switch ● 開關:按鍵式 , 滑動式 , 傾斜式 ... http://nicegear.co.nz/ 70

Slide 71

Slide 71 text

按鍵 Button / 開關 Switch ● 常開 (normally open, N.O.) ● 常閉 (normally close, N.C.) 71 http://www.engineersgarage.com/sites/default/files/imagecache/Original/wysiwyg_imageupload/4214/Switch-2_0.jpg

Slide 72

Slide 72 text

按鍵的內部結構 1 2 ● 按下前 長邊相連 (1&2,3&4) ● 短邊不相連 ● 3 4 ● 按下後 ● 四點都通 http://www.ladyada.net/learn/arduino/lesson5.html 72

Slide 73

Slide 73 text

簡單的按鍵接法 BUTTON 腳1 腳3 RPi Pin6 (Ground) Pin11 (GPIO17) 73

Slide 74

Slide 74 text

問題在哪裡? ● Input 空接會讀到雜訊 按鍵按下後 , 讀到低電位 按鍵按下前未導通 , 讀到?? 74

Slide 75

Slide 75 text

更好的按鍵接法 ( 上拉電阻 ) http://geekgurldiaries.blogspot.tw/2012/12/part-2.html 75

Slide 76

Slide 76 text

線路圖 BUTTON 腳1 腳3 RPi Pin6 (Ground) Pin11 (GPIO17) Pin1 (3.3V) 1k 電阻 76

Slide 77

Slide 77 text

判斷條件 : 這次低 && 上次高 BTN_PIN = 11 GPIO.setup(BTN_PIN, GPIO.IN) previousStatus = None try: while True: input = GPIO.input(BTN_PIN) if input == GPIO.LOW and previousStatus == GPIO.HIGH: print("Button pressed") previousStatus = input except KeyboardInterrupt: print("Exception: KeyboardInterrupt") finally: GPIO.cleanup() 77

Slide 78

Slide 78 text

DEMO push_button_poll.py $ cd ~/gpio-game-console $ cd 04_1-push_button_poll $ python3 push_button_poll.py 78

Slide 79

Slide 79 text

按一次出現兩次?這樣子對不對啊? 79

Slide 80

Slide 80 text

開關訊號的彈跳問題 (bounce) ● 機械式開關在切換過程中會有訊號彈跳現象 ( 雜訊 ) 理想訊號輸出 實際輸出訊號 http://120.101.72.1/Onechip/PPT/ 實習單元三 .ppt 80

Slide 81

Slide 81 text

解決彈跳問題 (de-bounce) ● 硬體方法 : 以 RC 電路或正回授的比較器電路解決 ● 軟體方法 : 調整觸發的延遲時間 ● 不同的按鍵會有不同的延遲時間 10ms - 20ms 81

Slide 82

Slide 82 text

不反應在延遲時間內的觸發 GPIO.setup(BTN_PIN, GPIO.IN) previousStatus = None previousTime = time.time() currentTime = None try: while True: input = GPIO.input(BTN_PIN) currentTime = time.time() if input == GPIO.LOW and \ previousStatus == GPIO.HIGH and \ (currentTime - previousTime) > 0.2: previousTime = currentTime print("Button pressed”) previousStatus = input 82

Slide 83

Slide 83 text

DEMO push_button_debounce.py $ cd ~/gpio-game-console $ cd 04_2-push_button_debounce $ python3 push_button_debounce.py 83

Slide 84

Slide 84 text

如何看系統效能? ● PID 先以背景方式執行單一程式 ( 加上 &) ● $ python3 push_button_debounce.py & 84

Slide 85

Slide 85 text

如何看系統效能? ● PID ● 先以背景方式執行單一程式 ( 加上 &) ● $ python3 push_button_debounce.py & 再看整體系統使用狀況 ( 可以按 q 離開 ) ● $ top -c 85

Slide 86

Slide 86 text

在 top 指令中止程序 ( 按 k) 輸入要中止的程序 PID 輸入 KILL 訊號 9 中止程序 86

Slide 87

Slide 87 text

低 CPU 使用率 ( 按 q 離開 ) 87

Slide 88

Slide 88 text

輪詢與中斷 ● 輪詢 (polling) ● ● SoC 每隔一段時間檢查週邊硬體的資料 中斷 (interrupt) ● 當週邊硬體的狀態改變時 , 對 SoC 發出中斷要求 88

Slide 89

Slide 89 text

中斷的程式寫法 ● 建立回呼函數 ● ● def mycallback() 綁定事件和回呼函數 ● add_event_detect(gpio, # 對象 edge, # 觸發條件 callback, # 回呼函數 bouncetime) ● 多個事件可以綁定同樣的回呼函數 source/py_gpio.c 89

Slide 90

Slide 90 text

即使在 sleep 狀態下也可立即回應 BTN_PIN = 11 GPIO.setup(BTN_PIN, GPIO.IN) def mycallback(channel): print("Button pressed") try: GPIO.add_event_detect(BTN_PIN, \ GPIO.FALLING, \ callback=mycallback, \ bouncetime=200) while True: time.sleep(10) finally: GPIO.cleanup() 90

Slide 91

Slide 91 text

DEMO push_button_interrupt.py $ cd ~/gpio-game-console $ cd 04_3-push_button_interrupt $ python3 push_button_interrupt.py 91

Slide 92

Slide 92 text

觀察使用中斷的寫法 CPU 使用率 92

Slide 93

Slide 93 text

使用中斷 , 低 CPU 使用率 ( 按 q 離開 ) 93

Slide 94

Slide 94 text

中斷的意義 需要硬體或軟體 ( 作業系統 ) 的支援 ● RPi.GPIO 在版本 0.5.0a 有了中斷功能 ● 加上 add_event_detect() 等機制 ● RPi.GPIO 以建立多執行緒方式實現中斷 ● 程式開始執行時 , 主執行序運行 ● 當加入事件後 , 以 epoll_create 建立新的 fd ● 當事件觸發時 , 第二個執行序和主執行序溝通 ( 回 呼) ● 程式碼可參考 source/event_gpio.c ● source/py_gpio.c 94

Slide 95

Slide 95 text

簡單的按鍵接法沒有錯 , 但是 ... BUTTON 腳1 腳3 RPi Pin6 (Ground) Pin11 (GPIO17) 95

Slide 96

Slide 96 text

要搭配內建的上拉電阻 (50k) GPIO.setup(BTN_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP) def mycallback(channel): print("Button pressed") try: GPIO.add_event_detect(BTN_PIN, \ GPIO.FALLING, \ callback=mycallback, \ bouncetime=WAIT_TIME) while True: time.sleep(10) finally: GPIO.cleanup() 96

Slide 97

Slide 97 text

DEMO push_button_internal_pull_up.py $ cd ~/gpio-game-console $ cd 04_4-push_button_internal_pull_up $ python3 push_button_internal_pull_up.py 97

Slide 98

Slide 98 text

實驗 5: 傾斜開關 目的 : 認識不同的硬體 98

Slide 99

Slide 99 text

傾斜開關 Tilt Switch 99

Slide 100

Slide 100 text

線路圖 SWITCH 第一腳 (RED) 第二腳 (BLACK) RPi Pin11 (GPIO17) Pin6 (Ground) 100

Slide 101

Slide 101 text

要搭配內建的上拉電阻 (50k) GPIO.setup(BTN_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP) def mycallback(channel): print("Button pressed") try: GPIO.add_event_detect(BTN_PIN, \ GPIO.FALLING, \ callback=mycallback, \ bouncetime=WAIT_TIME) while True: time.sleep(10) finally: GPIO.cleanup() 101

Slide 102

Slide 102 text

使用內建的上拉電阻 DEMO tilt_switch.py $ cd ~/gpio-game-console $ cd 05-tilt_switch $ python3 tilt_switch.py 102

Slide 103

Slide 103 text

實驗 6: 蜂鳴器樂器 目的 : 聲音輸出 103

Slide 104

Slide 104 text

原理 ● ● ● 發聲原理 : 聲音是由振動產生 , 其頻率稱為音頻 蜂鳴器發聲原理 : 電流 (6) 通過電磁線圈 (3) 產生 磁場來驅動振動膜 (11) 人耳可聽到 20Hz - 20KHz http://www.itianer.com/diancishifengmingqigouzaoyuyuanlijieshao.html 104

Slide 105

Slide 105 text

蜂鳴器 Buzzer ● 自激 ( 有源 ): 只能發出同頻率的聲音 ● ● 黑膠封裝 , 高低腳 他激 ( 無源 ): 需從外部輸入震盪方波發聲 ● 綠色電路板 , 兩腳同長 ● 腳位有正負之分 ( 看底板 ) 自激式 他激式 http://www.buzzer-speaker.com/manufacturer/piezo%20buzzer.htm 105

Slide 106

Slide 106 text

線路圖 BUZZER +(RED) - (BLACK) RPi Pin12 (GPIO18) Pin6 (Ground) 106

Slide 107

Slide 107 text

可發出不同頻率聲音 def buzz(pitch, duration) : period = 1.0 / pitch half_period = period / 2 cycles = int(duration * pitch) for i in range(cycles) : GPIO.output(buzzer_pin, GPIO.HIGH) time.sleep(half_period) GPIO.output(buzzer_pin, GPIO.LOW) time.sleep(half_period) while True : pitch_s = input("Enter Pitch (200 to 2000): ") duration_s = input("Enter Duration (seconde): ") buzz(float(pitch_s), float(duration_s)) 107

Slide 108

Slide 108 text

DEMO buzzer.py $ cd ~/gpio-game-console $ cd 06_1-buzzer $ python3 buzzer.py 108

Slide 109

Slide 109 text

鋼琴模擬 0 2 4 6 8 ● 1 3 5 ● 標準 88 鍵鋼琴 , 每個音的頻率 : ● 每段音階分為 12 個半音 ● 每個音的頻率是前一個的 1.05946 倍 ( http://en.wikipedia.org/wiki/Piano_key_frequencies 7 12 2 ) 109

Slide 110

Slide 110 text

鋼琴頻率 ● 標準 88 鍵鋼琴 , 以第 49 鍵 A4 為基準 (440Hz) ● 各半音頻率如下: ● C5 (52th, DO): 523Hz ● D5 (54th, RE): 587Hz ● E5 (56th, ME): 659Hz ● F5 (57th, FA): 698Hz ● G5 (59th, SO): 784Hz ● A5 (61th, LA): 880Hz ● B5 (63th, SI): 988Hz http://en.wikipedia.org/wiki/Piano_key_frequencies 110

Slide 111

Slide 111 text

線路圖 RPi Pin7 Buzzer Pin11 Do Pin12 Re Pin13 Me Pin15 Fa Pin16 So Pin18 La Pin22 Si 111

Slide 112

Slide 112 text

DEMO paino_buzzer.py $ cd ~/gpio-game-console $ cd 06_2-paino_buzzer $ python3 paino_buzzer.py 112

Slide 113

Slide 113 text

實驗 7: 人體紅外線感測器 目的 : 常見感測器使用 113

Slide 114

Slide 114 text

Pyroelectric ("Passive") InfraRed Sensor PIR 人體紅外線感測器 114 http://www.raspberrypi-spy.co.uk/2013/01/cheap-pir-sensors-and-the-raspberry-pi-part-1/

Slide 115

Slide 115 text

使用示意圖 http://www.ladyada.net/learn/sensors/pir.html 115

Slide 116

Slide 116 text

應用範例 http://www.ladyada.net/learn/sensors/pir.html http://totherails.blogspot.tw/2011/09/halloween-preparations.html 116

Slide 117

Slide 117 text

元件說明 http://www.ladyada.net/learn/sensors/pir.html 117

Slide 118

Slide 118 text

瞭解規格 ● 輸入電壓 :DC 3.3V - 24V ● 輸出電壓 :3.3V( 可直接接上 Raspberry Pi) ● 延遲時間 (Tx):2.45 秒 – 248 秒 感應之後輸出維持的時間 ● 封鎖時間 (Ti):2.4 秒 ● ● 感應輸出結束之後 , 再次觸發必須等待的時間 ● 感應角度 :110 度 x 70 度 ● 感應距離 :3 米 - 7 米 118

Slide 119

Slide 119 text

感測距離 / 延遲時間設定 ● ● 感測距離設定 ● 順時針 : 最高為 7 米 ● 逆時針 : 最小為 3 米 延遲時間設定 (Tx) ● ● ● 順時針 : 最長為 248 秒 逆時針 : 最短為 2.45 秒 感測距離設定 延遲時間設定 實際可調整時間要看 R10,C6,R9,C7 而定 119

Slide 120

Slide 120 text

觸發模式 ● 可重複觸發模式 (H) ● 不可重複觸發模式 (L) H: 可重複觸發 感應 & 輸出 感應 & 等待 & 輸出 L: 不可重複觸發 ( 預設 ) 120

Slide 121

Slide 121 text

線路圖 Pin16 Pin16(GPIO23) 121

Slide 122

Slide 122 text

再一次使用 interrupt 模式 PIR_PIN = 16 GPIO.setup(PIR_PIN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) def mycallback(channel): print("Motion detected") try: GPIO.add_event_detect(PIR_PIN, GPIO.RISING, \ callback=mycallback, \ bouncetime=200) while True: time.sleep(1) finally: GPIO.cleanup() 122

Slide 123

Slide 123 text

觸發才拉高電位 , 因此用內建的下拉電阻 DEMO pir.py $ cd ~/gpio-game-console $ cd 07_1-pir $ python3 pir.py 123

Slide 124

Slide 124 text

加上警示的 LED 燈吧 124

Slide 125

Slide 125 text

線路圖 1k 電阻 Pin16 Pin16(GPIO23) 125

Slide 126

Slide 126 text

DEMO people_alarm_system.py $ cd ~/gpio-game-console $ cd 07_2-people_alarm_system $ python3 people_alarm_system.py 126

Slide 127

Slide 127 text

偵測到人 , 燈閃 3 次 LED_PIN = 12 PIR_PIN = 16 GPIO.setup(PIR_PIN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) GPIO.setup(LED_PIN, GPIO.OUT) def mycallback(channel): print("Motion detected") for i in range(3) : GPIO.output(LED_PIN, GPIO.HIGH) time.sleep(0.5) GPIO.output(LED_PIN, GPIO.LOW) time.sleep(0.5) try: GPIO.add_event_detect(PIR_PIN, GPIO.RISING, callback=mycallback, bouncetime=200) while True: time.sleep(1) 127

Slide 128

Slide 128 text

實驗 8: 超音波距離感測器 目的 : 根據規格撰寫程式 128

Slide 129

Slide 129 text

測距離原理 ● 聲音在 20°C (68°F) 的速度是 343 公尺 / 秒 ● 溫度每增加 1°, 速度增加 0.6 公尺 / 秒 http://en.wikipedia.org/wiki/Speed_of_sound 129 https://www.modmypi.com/blog/hc-sr04-ultrasonic-range-sensor-on-the-raspberry-pi

Slide 130

Slide 130 text

HC-SR04 超音波距離感測器 ● 內建發射 (40kHz) 與接收電路 ● 根據發射與接收的時間差計算距離 ● 特殊功能 :US-020( 長距離 ) 、 US-100( 溫度補 償) http://coopermaa2nd.blogspot.tw/2012/09/hc-sr04.html 130

Slide 131

Slide 131 text

應用 ● 避障 , 測距 物體移動感測 ● 地鐵感測器 ● http://letsmakerobots.com/robot/project/rock-crawler https://www.dropbox.com/s/x0qdaq86rkc0zyv/MakerConf.pdf 131

Slide 132

Slide 132 text

地鐵感測器 http://makezine.com/magazine/ultrasonic-train-detector-in-stockholm-subway/ 132

Slide 133

Slide 133 text

地鐵感測器 http://makezine.com/magazine/ultrasonic-train-detector-in-stockholm-subway/ 133

Slide 134

Slide 134 text

HC-SR04 ● 規格與時序圖 建議測量間隔 >60ms http://coopermaa2nd.blogspot.tw/2012/09/hc-sr04.html 134

Slide 135

Slide 135 text

分壓電路計算 ● TRIG 腳位收到高電位 (3.3V) 後發送超聲波 ● ECHO 腳位維持低電位 (0V), 收到回應後拉到高電位 (5V) ● Raspberry Pi 腳位的容忍電位為 3.3V => 將 ECHO 腳位的 5V 降壓為 3.3V 左右 => R1=1K, R2 取 2K 135 https://www.modmypi.com/blog/hc-sr04-ultrasonic-range-sensor-on-the-raspberry-pi

Slide 136

Slide 136 text

注意 1K, 2K 電阻 Gnd Echo Trig Vcc 這是背面 1k: 棕黑黑棕 2k: 紅黑黑棕 ULTRASONIC Vcc(RED) Trig(YELLOW) Echo(PURPLE) Grnd(BLACK) RPi Pin2 (5V) Pin16 (GPIO23) Pin18 (GPIO24) Pin6 (Ground) 136

Slide 137

Slide 137 text

測量距離 v = 343 # (331 + 0.6*20) def measure() : GPIO.output(TRIGGER_PIN, GPIO.HIGH) time.sleep(0.00001) # 10uS GPIO.output(TRIGGER_PIN, GPIO.LOW) pulse_start = None pulse_end = None while GPIO.input(ECHO_PIN) == GPIO.LOW: pulse_start = time.time() while GPIO.input(ECHO_PIN) == GPIO.HIGH: pulse_end = time.time() t = pulse_end - pulse_start d = t * v d = d/2 return d*100 137

Slide 138

Slide 138 text

DEMO hc_sr04_measure_distance.py $ cd ~/gpio-game-console $ cd 08-hc_sr04_measure_distance $ python3 hc_sr04_measure_distance.py 138

Slide 139

Slide 139 text

看看準不準? 139

Slide 140

Slide 140 text

實驗 9: 呼吸燈 目的 : 瞭解訊號模擬 140

Slide 141

Slide 141 text

數位與類比 ● 數位 :0 與 1 的訊號 ● 類比 : 連續的訊號 http://www.bitscope.com/software/blog/DJ/?p=DJ19A 141

Slide 142

Slide 142 text

從 LED 的角度來看 ● 數位 : 亮和不亮 ● 類比 : 亮 , 有點亮 , 有點不亮 ..., 不亮 ● 可是 GPIO 腳位輸出都是固定值 , 怎麼辦? 142

Slide 143

Slide 143 text

可變電阻 Potentiometer(VR) ● 旋轉式 , 滑動式 ● 線性關係 (B 型 ), 對數關係 (A 型 ) ● 常見規格 :0 -10k Ohm( 線性 ) 接低電位 滑動接點 ( 可變輸出 ) 接高電位 https://en.wikipedia.org/wiki/Potentiometer 143

Slide 144

Slide 144 text

利用可變電阻改變 LED 亮度 144

Slide 145

Slide 145 text

有不使用額外硬體的方法嗎? 145

Slide 146

Slide 146 text

脈寬調變 (Pulse-Width Modulation) ● 是將數位信號轉為脈波的一種技術 ● 頻率不變 + 改變工作週期 , 使整體平均電壓值改變 ● 改變工作週期 (duty cycle)= 改變平均電壓 http://wiki.csie.ncku.edu.tw/embedded/PWM 146

Slide 147

Slide 147 text

公式計算 ● 輸出總功率 = 脈衝寬度 ( 時間 )x 高電位值 147 http://www.protostack.com/blog/2011/06/atmega168a-pulse-width-modulation-pwm/

Slide 148

Slide 148 text

GPIO.PWM() ● To create a PWM instance: ● ● To start PWM: ● ● p.start(dc) # dc is the duty cycle To change the duty cycle: ● ● p = GPIO.PWM(channel, frequency) p.ChangeDutyCycle(dc) # where 0.0 <= dc <= 100.0 To stop PWM: ● p.stop() 148 http://sourceforge.net/p/raspberry-gpio-python/wiki/PWM/

Slide 149

Slide 149 text

接線圖 LED 長腳 (RED) 短腳 (BLACK) RPi Pin12 (GPIO18) Pin6 (Ground) 1k 電阻 149

Slide 150

Slide 150 text

互動式的調光 LED_PIN = 12 ● GPIO.setup(LED_PIN, GPIO.OUT) pwm_led = GPIO.PWM(LED_PIN, 100) ● pwm_led.start(0) ● ● ● try: while True: ● duty_s = input("Enter Brightness (0 to 100):") ● duty = int(duty_s) ● ● ● if duty >= 0 and duty <=100 : pwm_led.ChangeDutyCycle(duty) ● ● except KeyboardInterrupt: ● pwm_led.stop() ● GPIO.cleanup() 150

Slide 151

Slide 151 text

DEMO adjust_led_bright.py $ cd ~/gpio-game-console $ cd 09_1-adjust_led_bright $ python3 adjust_led_bright.py 151

Slide 152

Slide 152 text

呼吸燈就是漸明漸亮 LED_PIN = 12 GPIO.setup(LED_PIN, GPIO.OUT) pwm_led = GPIO.PWM(LED_PIN, 100) pwm_led.start(0) while True: for dc in range(0, 101, 5): pwm_led.ChangeDutyCycle(dc) time.sleep(0.1) time.sleep(0.5) for dc in range(100, -1, -5): pwm_led.ChangeDutyCycle(dc) time.sleep(0.1) time.sleep(0.5) 152

Slide 153

Slide 153 text

DEMO pwm_led.py $ cd ~/gpio-game-console $ cd 09_2-pwm_led $ python3 pwm_led.py 153

Slide 154

Slide 154 text

Software PWM vs. Hardware PWM ● ● ● ● 兩者差異 ● Software PWM 是透過 kernel 做 duty cycle 的調整 ● Hardware PWM 是 SoC 透過 DMA 做調整 使用時機 ● 不需要精準時用 Software PWM, 例如 LED 調光 ● 需要低延遲時用 Hardware PWM, 例如伺服馬達 Hardware PWM GPIO 只有 GPIO12(Pin32), GPIO13(Pin33), GPIO18(Pin12), GPIO19(Pin35) 目前已經內建 pigpio 提供 Hardware PWM 函式呼叫 154

Slide 155

Slide 155 text

實驗 10: 光敏電阻 目的 : 類比訊號的讀取 155

Slide 156

Slide 156 text

光敏電阻 ● 硫化鎘 (CdS) 或光敏電阻器 (LDR), 阻抗隨光落 在表面的總量而轉變 ● 光越強阻值越小 , 反之光越弱阻值則越大 ● 應用 : 光控開關 , 電子玩具 , 工業控制 http://www2.nkfust.edu.tw/~jlkuo2/31/a6.htm 156

Slide 157

Slide 157 text

類比訊號轉換為數位訊號 ● Raspberry Pi 沒有硬體的類比數位轉換器 (ADC) IN ADC OUT 此 ADC 的解析度為 4bits 從 0000 到 1111( 看 Y 軸 ) 157 http://www.planetoftunes.com/digital-audio/how-do-analogue-to-digital-converters-work.html

Slide 158

Slide 158 text

利用 MCP3008 ● 類比數位轉換器 (Analog to Digital Converter) ● 8 通道 ,10 bits 解析度 ● SPI 協議 158

Slide 159

Slide 159 text

Serial Peripheral Interface(SPI) ● 主從式架構 , 可一對多 ● 四線同步序列資料協定 ● SS: 週邊選擇線 (CE) ● SCK: 序列時脈線 (SCLK) ● MOSI: 主往從送 ● SPI Master SCLK MOSI MISO SS1 SS2 SS3 MISO: 從往主送 https://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus SCLK MOSI MISO SS SPI Slave SCLK MOSI MISO SS SPI Slave SCLK MOSI MISO SS SPI Slave 159

Slide 160

Slide 160 text

啟用 Raspberry Pi 的 SPI ● $ sudo raspi-config 160

Slide 161

Slide 161 text

啟用 Raspberry Pi 的 SPI ● $ sudo raspi-config 161

Slide 162

Slide 162 text

啟用 Raspberry Pi 的 SPI ● $ sudo raspi-config 162

Slide 163

Slide 163 text

SPI 使用前的確認 ● 測試確認 SPI 模組已載入 ● ● $ ls /dev/spidev* 安裝必要套件 ( 如果前面已裝過 , 就不需再裝 ) ● $ sudo apt-get update ● $ sudo apt-get install python3-spidev 163

Slide 164

Slide 164 text

MCP3008 CLK Din Dout CS RPi Pin23 (SCLK) Pin19 (MOSI) Pin21 (MISO) Pin24 (CE0) 接線圖 1k 電阻 缺口朝左 164

Slide 165

Slide 165 text

再看一次腳位定義 ● SPI 會用到的腳位是 MOSI,MISO,SCLK 和 CE0/CE1 165

Slide 166

Slide 166 text

spi = spidev.SpiDev() spi.open(0,0) # (0,0) 表示接到 CE0 腳位 , 對應到 /dev/spidev0.0 裝置檔 spi.max_speed_hz = 1800000 # 10kHz to 3.6 MHz ● ● def ReadChannel(channel): adc = spi.xfer2([1,(8+channel)<<4,0]) data = ((adc[1]&3) << 8) + adc[2] return data def ConvertVolts(data,places): volts = (data * 3.3) / float(1023) volts = round(volts,places) return volts light_channel = 0 delay = 1 while True: light_level = ReadChannel(light_channel) light_volts = ConvertVolts(light_level, 2) print("Light:{} ({}V)".format(light_level,light_volts)) time.sleep(delay) 166

Slide 167

Slide 167 text

程式要照硬體規格撰寫 167

Slide 168

Slide 168 text

了解 spi.xfer2() 的意義 ● input 一次送三個 bytes ● # byte 1: the start bit (always 0x01) ● # byte 2: configure bits ● # byte 3: don't care 0x01 Ch0/Ch1 ● don't care spi.xfer2([1,(8+channel)<<4,0]) ● Ch0 = 1000 0000 ● Ch1 = 1001 0000 168

Slide 169

Slide 169 text

169 http://wolfpaulus.com/

Slide 170

Slide 170 text

Output 也是一次回傳三個 bytes 因為是 10bits 解析度 , 所以我們只取最後有用的 10bits 170 http://wolfpaulus.com/

Slide 171

Slide 171 text

DEMO photoresistor.py $ cd ~/gpio-game-console $ cd 10-photoresistor $ python3 photoresistor.py 171

Slide 172

Slide 172 text

再透過分壓電路回推光敏電阻阻值 光越強,電壓值越低 172

Slide 173

Slide 173 text

實驗 13: 模擬器 目的 : 系統整合 173

Slide 174

Slide 174 text

遊戲機 = 硬體 + 遊戲 http://www.emulatorworld.com/ 174

Slide 175

Slide 175 text

Video Game System Emulators 模擬不同的硬體架構 ● 常見的模擬器: ● ● ● ● ● MAME (AdvanceMAME) Nintendo Entertainment System (RetroArch) Super Nintendo Entertainment System (PiSNES) PC / x86 (rpix86) https://en.wikipedia.org/wiki/List_of_video_game_emulators 175

Slide 176

Slide 176 text

MAME(Multiple Arcade Machine Emulator) ● 模擬大台電動玩具 http://www.williamsamusements.co.uk/mame.html 176

Slide 177

Slide 177 text

用 Virtual Network Computing 看畫面 ● RFB 協定 + 螢幕畫面分享及遠端操作軟體 ● 與作業系統無關 , 可跨平台使用 ● Client/Server 架構 Raspberry Pi 當 VNC Server Laptop/PC 當 VNC client 177

Slide 178

Slide 178 text

啟用 Raspberry Pi 的 VNC Server ● $ sudo raspi-config 178

Slide 179

Slide 179 text

啟用 Raspberry Pi 的 VNC Server ● $ sudo raspi-config 179

Slide 180

Slide 180 text

啟用 Raspberry Pi 的 VNC Server ● $ sudo raspi-config 180

Slide 181

Slide 181 text

VNC Client 安裝 ● 下載 RealVNC Viewer https://www.realvnc.com/en/connect/download/viewer port 預設從 5900 開始 181

Slide 182

Slide 182 text

182

Slide 183

Slide 183 text

在 VNC 下執行 AdvanceMAME ● ● ● 下載編譯好的 binary ● $ cd ~ ● $ wget https://bit.ly/advmame -O ~/advmame ● $ chmod 755 advmame ● $ ./advmame 2. 下載 ROM 大寫的英文 " 歐 " ● $ cd ~ ● $ wget https://bit.ly/suprmrio -O ~/.advance/rom/suprmrio.zip 3. 執行模擬器 ● $ cd ~ ● $ ./advmame suprmrio 大寫的英文 " 歐 " 183

Slide 184

Slide 184 text

下載 ROM 放到對應的目錄下 ● 搜尋 MAME ● ● 中英文對照 ● ● http://www.emuparadise.me/ http://bbs.duowan.com/thread-41350071-11.html 經典遊戲 ● 超級瑪莉歐 ● 彈珠台 ● 小精靈 ● 坦克大作戰 , 泡泡龍 ... 184 http://en.wikipedia.org/wiki/Nintendo_Entertainment_System

Slide 185

Slide 185 text

使用模擬器 ● $ cd ~ ● $ ./advmame suprmrio ● 按 'o' 'k' 進入畫面 ● 按 '5' 投錢 ● 按 '1' 開始 ● 左邊 'ctrl' 是加速 ● 左邊 'alt' 是跳 ● 按 'esc' 是離開 185

Slide 186

Slide 186 text

遊戲機製作步驟 ● 執行模擬器 , 使用 keyboard 控制 ● 讀取 GPIO 搖桿的值 ● 讓 GPIO 搖桿和 keyboard 對應 ● 開機就啟動按鍵與 keyboard 對應程式 ● 開機就啟動模擬器 186 http://www.linuxuser.co.uk/tutorials/emulate-a-bluetooth-keyboard-with-the-raspberry-pi

Slide 187

Slide 187 text

搖桿 (joystick) 187

Slide 188

Slide 188 text

XY 雙軸搖桿 ● 3.3V-5V 工作電壓 ● 輸出形式: ● x,y 軸 - 類比輸出 ● z 軸 - 數位輸出 http://www.aliexpress.com/cheap/cheap-arduino-joystick.html 188

Slide 189

Slide 189 text

MS VRY VRX +3.3V GND 189 http://www.raspberrypi-spy.co.uk/2014/04/using-a-joystick-on-the-raspberry-pi-using-an-mcp3008/

Slide 190

Slide 190 text

spi = spidev.SpiDev() ● spi.open(0,0) ● spi.max_speed_hz = 1800000 ● ● def ReadChannel(channel): ● adc = spi.xfer2([1,(8+channel)<<4,0]) ● data = ((adc[1]&3) << 8) + adc[2] ● return data ● ● vrx_channel = 1 ● vry_channel = 2 ● ● while True: ● vrx_pos = ReadChannel(vrx_channel) ● vry_pos = ReadChannel(vry_channel) ● ● print("X : {} ● ● Y : {} ".format(vrx_pos,vry_pos)) 190 time.sleep(0.5)

Slide 191

Slide 191 text

DEMO mcp3008_joystick $ cd ~/gpio-game-console $ cd 11_1-mcp3008_joystick $ python3 mcp3008_joystick.py 191

Slide 192

Slide 192 text

觀察結果 192

Slide 193

Slide 193 text

搖桿如何和 keyboard 對應? 193

Slide 194

Slide 194 text

Linux 輸入與輸出的處理流程 https://en.wikipedia.org/wiki/Evdev 194

Slide 195

Slide 195 text

Linux Input Subsystem http://www.linuxjournal.com/article/6396 195

Slide 196

Slide 196 text

Linux Input Subsystem ● USB 或 PS2 keyboard 都是同一個 handler 處理 USB Keyboard PS2 Keyboard ● 我們可以加上 GPIO 的 driver, 讓 keyboard handler 來接? http://www.linuxjournal.com/article/6396 196

Slide 197

Slide 197 text

除了在 kernel space 做以外 , 可以在 user space 做嗎? 197

Slide 198

Slide 198 text

python3-evdev ● evdev(event device) ● ● python3-evdev ● ● 是 linux kenel 的通用輸入事件介面 , 可從 driver 產生原始的 input event, 並透過 /dev/input/ 發送事件 和 evdev 的 user space 實做 uinput 綁定 , 提供 python 介面的呼 叫來發送 input event 安裝 ( 如果前面已裝過 , 就不需再裝 ) ● $ sudo apt install python3-evdev python3-libevdev https://pypi.python.org/pypi/evdev 198

Slide 199

Slide 199 text

python-evdev keyboard example from evdev import UInput, ecodes as e ui = UInput() ui.write(e.EV_KEY, e.KEY_H, 1) # KEY_H down ui.write(e.EV_KEY, e.KEY_H, 0) # KEY_H up ui.write(e.EV_KEY, e.KEY_E, 1) ui.write(e.EV_KEY, e.KEY_E, 0) ui.write(e.EV_KEY, e.KEY_L, 1) ui.write(e.EV_KEY, e.KEY_L, 0) ui.write(e.EV_KEY, e.KEY_L, 1) ui.write(e.EV_KEY, e.KEY_L, 0) ui.write(e.EV_KEY, e.KEY_O, 1) ui.write(e.EV_KEY, e.KEY_O, 0) ui.syn() ● ui.close() 199

Slide 200

Slide 200 text

需要有 root 權限才能發送鍵盤事件 DEMO evdev_keyboard.py $ cd ~/gpio-game-console $ cd 11_2-evdev_keyboard $ sudo python3 evdev_keyboard.py 200

Slide 201

Slide 201 text

看不到結果嗎? 201

Slide 202

Slide 202 text

用 VNC 連進去開終端機看結果 202

Slide 203

Slide 203 text

上下左右鍵與搖桿的對應 203

Slide 204

Slide 204 text

上下左右鍵與搖桿的對應 - 觀察操作搖桿與畫面輸出值的關係 204

Slide 205

Slide 205 text

vrx_channel = 1 while True: vrx_pos = ReadChannel(vrx_channel) if vrx_pos > 700 : ui.write(e.EV_KEY, e.KEY_DOWN, 1) ui.write(e.EV_KEY, e.KEY_UP, 0) ui.syn() elif vrx_pos < 200 : ui.write(e.EV_KEY, e.KEY_DOWN, 0) ui.write(e.EV_KEY, e.KEY_UP, 1) ui.syn() else : ui.write(e.EV_KEY, e.KEY_DOWN, 0) ui.write(e.EV_KEY, e.KEY_UP, 0) ui.syn() time.sleep(0.1) 205

Slide 206

Slide 206 text

DEMO joystick_mapping_keyboard.py $ cd ~/gpio-game-console $ cd 11_3-joystick_mapping_keyboard $ sudo python3 joystick_mapping_keyboard.py 206

Slide 207

Slide 207 text

搖桿 + 按鍵的應用 MakerFaire 2014 Raspberry Jam 207

Slide 208

Slide 208 text

接線圖 Pin7 Pin12 208

Slide 209

Slide 209 text

DEMO gaming_console.py $ cd ~/gpio-game-console $ cd 13-gaming_console $ sudo python3 gaming_console.py 209

Slide 210

Slide 210 text

用搖桿控制超級瑪莉 - 需要開啟兩個視窗 ● 第一個執行超級瑪莉 (VNCViewer) ● $ cd ~ ● $ ./advmame suprmrio 從 x11vnc 連線後執行超級瑪莉 ( 顯示畫面 ) 210

Slide 211

Slide 211 text

用搖桿控制超級瑪莉 ● 第二個執行搖桿按鍵對應程式 (serial 或 ssh) ● $ cd ~/gpio-game-console/13-gaming_console ● $ sudo python3 gaming_console.py 從 serial 或 ssh 連線後執行搖桿按鍵對應程式 211

Slide 212

Slide 212 text

好麻煩 ! 如何開機就執行 ? 212

Slide 213

Slide 213 text

開機就執行? ● 一次性的執行可以使用工作排程 , 修改 crontab ● 有畫面的程式前景執行 , 用 LXDE 的 autostart ● 以服務的方式執行 , 需寫 systemd 設定檔 213

Slide 214

Slide 214 text

開機就執行搖桿對應按鍵程式 ● 先建立搖桿對應按鍵程式的腳本 ● $ nano ~/my-script.sh ● #!/bin/bash ● sudo python3 /home/pi/gpio-gameconsole/13-gaming_console/gaming_co nsole.py ● $ chmod 755 ~/my-script.sh 這是同一行 214

Slide 215

Slide 215 text

建立工作排程 ● 第一次會詢問編輯工作排程用的編輯器 , 選 nano ● $ sudo crontab -e 215

Slide 216

Slide 216 text

開機就執行 my-script.sh ● 新增 @reboot /home/pi/my-script.sh 216

Slide 217

Slide 217 text

進入桌面環境後就執行超級瑪莉 ● $ nano ~/.config/lxsession/LXDE-pi/autostart 或是 ● $ sudo nano /etc/xdg/lxsession/LXDE-pi/autostart ● 新增黃色字的部份 @lxpanel --profile LXDE-pi @pcmanfm --desktop --profile LXDE-pi @xscreensaver -no-splash @lxterminal -e /home/pi/advmame suprmrio ● 設定完以後重開機試試看吧 217

Slide 218

Slide 218 text

三種自動程式方案比較 方案 cron @reboot autostart .desktop systemd 執行時機 開機 桌面登入後 開機,可精確控制 順序 需要 root 可選 否 可選 適合情境 簡單一次性指令 GUI 相關程式 所有情境,最彈性 執行搖桿對 應按鍵程式 執行超級瑪 莉遊戲畫面 218

Slide 219

Slide 219 text

超音波距離感測器的應用 ● 手勢拉搖桿演算法範例: 1. 握拳靠近感測器觸發 2. 握拳平行向後 15cm 3. 手掌打開 = 放開拉桿 219

Slide 220

Slide 220 text

自製遊戲機 - 機構外殼很重要 demo board 小台 gameboy 正面 大台 gameboy 內裝 大台 gameboy 正面 小台 gameboy 內裝 220 大台電動玩具

Slide 221

Slide 221 text

Raspberry Pi Rocks the World Thanks 221

Slide 222

Slide 222 text

補充:自己編譯 AdvanceMAME 222

Slide 223

Slide 223 text

AdvanceMAME ● 安裝 gcc ● ● 下載 advancemame-5.0.tar.gz ● ● $ sudo apt-get install gcc http://www.advancemame.it/download 安裝 ● $ sudo apt-get install -ylibsdl1.2-dev ● $ tar zxvf advancemame-5.0.tar.gz ● $ cd advancemame-5.0 ● $ ./configure --disable-fb ● $ make -j4 ● $ ./advmame 223

Slide 224

Slide 224 text

執行模擬器 ● ● 1. 產生 rc 檔 ● $ cd /home/pi/advancemame-5.0 ● $ chmod 755 advmame ● $ ./advmame 2. 下載 rom ● ● $ cd /home/pi/.advance/rom 3. 執行模擬器 ● $ cd /home/pi/advancemame-5.0 ● $ ./advmame suprmrio 224

Slide 225

Slide 225 text

補充: AdvanceMAME 性能調校 225

Slide 226

Slide 226 text

我的 AdvanceMAME 很慢? ● 修改解析度 , 改為 256x240x60 ● tab 鍵進入選單 , 選擇 Video Mode, ESC 離開 226

Slide 227

Slide 227 text

我的 AdvanceMAME 很慢? ● 修改解析度 , 改為 256x240x60 ● tab 鍵進入選單 , 選擇 Video Mode, ESC 離開 227

Slide 228

Slide 228 text

我的 AdvanceMAME 很慢? ● 修改解析度 , 改為 256x240x60 ● tab 鍵進入選單 , 選擇 Video Mode, ESC 離開 228