raspberry pi 遊戲機工作坊 -...
TRANSCRIPT
姓名標示 — 非商業性 — 相同方式分享
CC (Creative Commons)
姓名標示 — 你必須給予 適當表彰、提供指向本授權條款的連結,以及 指出(本作品的原始版本)是否已被變更。你可以任何合理方式為前述表彰,但不得以任何方式暗示授權人為你或你的使用方式背書。
非商業性 — 你不得將本素材進行商業目的之使用。
相同方式分享 — 若你重混、轉換本素材,或依本素材建立新素材,你必須依本素材的授權條款來散布你的貢獻物。
3
● Raspberry Pi官方經銷商
about 台灣樹莓派
http://farnell.com/raspberrypi-consumer/approved-retailers.php?region=apac&MER=MER-LM-OB-RPICC-76315
● 專注於 Raspberry Pi 應用與推廣
● 舉辦社群聚會 / 工作坊 / 讀書會 /黑客松
● Website:● https://www.raspberrypi.com.tw/
● Facebook: ● 搜尋 RaspberryPi.Taiwan● https://www.facebook.com/RaspberryPi.Taiwan
社群 x 活動
5
● COSCUP,MakerConf,PyCon講者
● 投影片
● http://www.slideshare.net/raspberrypi-tw/presentations
● 程式碼
● https://github.com/raspberrypi-tw
分享 x 教學
8
● 硬體:Raspberry Pi 3
● 作業系統:2016-09-23-raspbian-jessie.img
● 為了可以使用USB轉TTL傳輸線
● 修改/boot/config.txt,新增三行
– dtoverlay=pi3-miniuart-bt
– core_freq=250
– enable_uart=1
● 修改/boot/cmdline.txt,將quiet splash的quiet移除
今日環境
刪除 quiet
新增三行
9
● $ sudo apt-get update● $ sudo apt-get install -y x11vnc python-dev python-pip libsdl1.2-dev
● $ sudo pip install spidev evdev
安裝今日所需套件 ( 已安裝 )
11
● General Purpose Input Output● GPIO 是一種可用軟體控制的數位訊號
什麼是 GPIO ?
http://www.tek.com/datasheet/tps2000b-series-digital-storage-oscilloscopes-datasheet
14
● GPIO高電位輸出為 3.3V● GPIO容忍輸入電位為 3.3V● 單一 Pin輸出電流為 3mA-16mA● 全部 Pin輸出總和小於 50mA● GPIO輸入低電位為小於 0.8V,高電位為大於 1.3V
幾個 GPIO 的數字
https://www.scribd.com/doc/101830961/GPIO-Pads-Control2
15
● C● C + wiringPi● C#● Ruby● Perl● Python● Scratch● Java Pi4J Library● Shell script
如何控制 Raspberry Pi 的 GPIO ?
16
● Python + RPi.GPIO = 70 kHz● C + BCM 2835 = 5.4 MHz● Ruby + wiringpi bindings = 21 kHz
GPIO Benchmark
http://www.tek.com/datasheet/tps2000b-series-digital-storage-oscilloscopes-datasheet
19
● 動態型別 (dynamic typing)
# 這是註解
i = 3 # 變數 i指到數字物件 3
i = [1, 2, 3, 4, 5] # 變數 i指到串列物件
print i[2] # 印出串列中第三個元素
i = “abcde” # 變數 i指到字串物件
print i[2] # 印出字串中第三個元素
變數 , 物件 , 型別 , 註解
22
● 自動迭代 (iterator)
for i in xrange(start, stop[, step]):
process
for i in xrange(0, 11, 5):
process
迴圈
24
def function_name():
process
def function_name(param_name):
process
def function_name(param_name = 3):
process
函式
25
電子入門套件
● 紅/黃/綠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
29
● 發光二極體● 單向導通● 省電
LED
http://upload.wikimedia.org/wikipedia/commons/c/c8/5mm_Red_LED.jpg
長腳接正極 Vcc短腳接負極GND
30
● 電路組成元件 :電源、導線、負載
● 閉路 :當三者形成一完整路徑 ,有電流經過電路
● 歐姆定律 :導體兩端的電壓與通過的電流成正比
● V = I x R
電路一分鐘速成
I
I
V RV R
I
https://zh.wikipedia.org/wiki/电路
32
● VF:順向電壓
● IF: 在順向電壓下的安全電流
LED 的特性
https://learn.adafruit.com/all-about-leds/forward-voltage-and-kvl
33
● 在順向電壓下一般的 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燒毀
如何解讀?
34
電阻阻值計算
www.digikey.tw/tw/zht/mkt/5-band-resistors.html
四環:右側為金或銀
五環:前四環很靠近1K=棕黑黑棕 (棕 )2K=紅黑黑棕 (棕 )
40
麵包板的使用
http://bugworkshop.blogspot.tw/2012/12/diy-breadboard.html
1. 藍色和綠色兩塊不通2. 藍色水平相通3. 紅色垂直相通 麵包板的內部結構
46
● 載入模組 (Import module) ● 選擇編號系統 (Define pin numbering)● 定義腳位 (Setup up a channel)● 讀取輸入 / 寫入輸出 (Input/Output)● 清理 (Cleanup)
Python Code基本流程
http://code.google.com/p/raspberry-gpio-python/wiki/BasicUsage
47
#!/usr/bin/python ●
● import RPi.GPIO as GPIO # Import module
● import time ●
● 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
一個實際的範例
50
● $ cd < 目錄 > # 跳到 <目錄 >● $ cd .. # 回上一層● $ cd ~ # 回 <家目錄 >
● $ pwd # 查看目前工作目錄
● $ ls # 列出檔案與目錄
● $ sudo reboot # 重開機
你必須知道的 Linux 指令
51
$ cd ~
$ git clone https://github.com/raspberrypi-tw/gpio-game-console.git
$ cd ~/gpio-game-console
$ cd 01-led_on
$ python led_on.py
讀寫 GPIO 會存取 /dev/mem, 需 root 權限(2015-09-24 以後的 image 可以用一般使用者身份執行 )
執行方式
52
● Wiki● http://sourceforge.net/p/raspberry-gpio-python/wiki/Home/
● Code● 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/BCM2835-ARM-Peripherals.pdf
更多 RPi.GPIO 的使用方法
55
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)
●
● GPIO.cleanup()
永不停止的 while 迴圈-按Ctrl+c跳出迴圈
56
DEMOled_blink_warning.py
$ cd ~/gpio-game-console
$ cd 02_1-led_blink_warning
$ python led_blink_warning.py
57
RuntimeWarning: This channel is already in use, continuing anyway. Use GPIO.setwarnings(False) to disable warnings.
60
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()
接住例外
65
DEMOtraffic_light_nonstructure.py
$ cd ~/gpio-game-console
$ cd 03_1-traffic_light_nonstructure
$ python traffic_light_nonstructure.py
66
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()
把亮燈拿到外面
71
● 常開 (normally open, N.O.)● 常閉 (normally close, N.C.)
按鍵 Button / 開關 Switch
http://www.engineersgarage.com/sites/default/files/imagecache/Original/wysiwyg_imageupload/4214/Switch-2_0.jpg
72
按鍵的內部結構
http://www.ladyada.net/learn/arduino/lesson5.html
● 按下前
● 長邊相連 (1&2,3&4)● 短邊不相連
● 按下後● 四點都通
1 2
3 4
77
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()
判斷條件 :這次低 && 上次高
78
DEMOpush_button_poll.py
$ cd ~/gpio-game-console
$ cd 04_1-push_button_poll
$ python push_button_poll.py
80
● 機械式開關在切換過程中會有訊號彈跳現象 (雜訊 )
開關訊號的彈跳問題 (bounce)
http://120.101.72.1/Onechip/PPT/ 實習單元三 .ppt
理想訊號輸出
實際輸出訊號
82
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
不反應在延遲時間內的觸發
83
DEMOpush_button_debounce.py
$ cd ~/gpio-game-console
$ cd 04_2-push_button_debounce
$ python push_button_debounce.py
87
● 建立回呼函數
● def mycallback()
● 綁定事件和回呼函數
● add_event_detect(gpio, # 對象
edge, # 觸發條件
callback,# 回呼函數
bouncetime)● 多個事件可以綁定同樣的回呼函數
中斷的程式寫法
source/py_gpio.c
88
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()
即使在 sleep狀態下也可立即回應
89
DEMOpush_button_interrupt.py
$ cd ~/gpio-game-console
$ cd 04_3-push_button_interrupt
$ python push_button_interrupt.py
90
● 需要硬體或軟體(作業系統)的支援
● RPi.GPIO在版本0.5.0a有了中斷功能
● 加上add_event_detect()等機制
● RPi.GPIO以建立多執行緒方式實現中斷
● 程式開始執行時, 主執行序運行
● 當加入事件後,以epoll_create建立新的fd● 當事件觸發時,第二個執行序和主執行序溝通(回呼)● 程式碼可參考source/event_gpio.c
中斷的意義
source/py_gpio.c
92
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()
要搭配內建的上拉電阻 (50k)
93
DEMOpush_button_internal_pull_up.py
$ cd ~/gpio-game-console
$ cd 04_4-push_button_internal_pull_up
$ python push_button_internal_pull_up.py
97
DEMOtilt_switch.py
$ cd ~/gpio-game-console
$ cd 05-tilt_switch
$ python tilt_switch.py
使用內建的上拉電阻
99
● 發聲原理 :聲音是由振動產生 ,其頻率稱為音頻
● 蜂鳴器發聲原理 :電流 (6)通過電磁線圈 (3)產生磁場來驅動振動膜 (11)
● 人耳可聽到 20Hz - 20KHz
原理
http://www.itianer.com/diancishifengmingqigouzaoyuyuanlijieshao.html
100
● 自激 (有源 ):只能發出同頻率的聲音
● 黑膠封裝 ,高低腳
● 他激 (無源 ): 需從外部輸入震盪方波發聲
● 綠色電路板 ,兩腳同長
● 腳位有正負之分 (看底板 )
蜂鳴器 Buzzer
http://www.buzzer-speaker.com/manufacturer/piezo%20buzzer.htm
自激式 他激式
102
def buzz(pitch, duration) :
period = 1.0 / pitch
half_period = period / 2
cycles = int(duration * pitch)
for i in xrange(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 = raw_input("Enter Pitch (200 to 2000): ")
duration_s = raw_input("Enter Duration (seconde): ")
buzz(float(pitch_s), float(duration_s))
可發出不同頻率聲音
104
●
● 標準 88鍵鋼琴 ,每個音的頻率 :● 每段音階分為 12 個半音
● 每個音的頻率是前一個的 1.05946倍 ( )
鋼琴模擬
1
2
3
4
5
6
7
0 8
http://en.wikipedia.org/wiki/Piano_key_frequencies
122
105
● 標準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
109
Pyroelectric ("Passive") InfraRed SensorPIR 人體紅外線感測器
http://www.raspberrypi-spy.co.uk/2013/01/cheap-pir-sensors-and-the-raspberry-pi-part-1/
111
應用範例
http://www.ladyada.net/learn/sensors/pir.htmlhttp://totherails.blogspot.tw/2011/09/halloween-preparations.html
113
● 輸入電壓 :DC 3.3V - 24V ● 輸出電壓 :3.3V( 可直接接上 Raspberry Pi)● 延遲時間 (Tx):2.45秒 – 248秒
● 感應之後輸出維持的時間● 封鎖時間 (Ti):2.4 秒
● 感應輸出結束之後 ,再次觸發必須等待的時間
● 感應角度 :110度 x 70度● 感應距離 :3米 - 7 米
瞭解規格
114
● 感測距離設定
● 順時針 :最高為 7米● 逆時針 :最小為 3米
● 延遲時間設定 (Tx)● 順時針 :最長為 248秒● 逆時針 :最短為 2.45秒
● 實際可調整時間要看 R10,C6,R9,C7而定
感測距離 /延遲時間設定
感測距離設定 延遲時間設定
117
PIR_PIN = 26
GPIO.setup(BTN_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()
再一次使用 interrupt 模式
121
DEMOpeople_alarm_system.py
$ cd ~/gpio-game-console
$ cd 07_2-people_alarm_system
$ python people_alarm_system.py
122
LED_PIN = 12
PIR_PIN = 26
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 xrange(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)
偵測到人 , 燈閃 3 次
124
● 聲音在 20°C (68°F) 的速度是 343公尺 /秒● 溫度每增加 1°,速度增加 0.6公尺/秒
測距離原理
http://en.wikipedia.org/wiki/Speed_of_soundhttps://www.modmypi.com/blog/hc-sr04-ultrasonic-range-sensor-on-the-raspberry-pi
125
● 內建發射(40kHz)與接收電路
● 根據發射與接收的時間差計算距離
● 特殊功能:US-020(長距離)、US-100(溫度補償)
HC-SR04超音波距離感測器
http://coopermaa2nd.blogspot.tw/2012/09/hc-sr04.html
126
● 避障 ,測距● 物體移動感測● 地鐵感測器
應用
http://letsmakerobots.com/robot/project/rock-crawlerhttps://www.dropbox.com/s/x0qdaq86rkc0zyv/MakerConf.pdf
130
● TRIG腳位收到高電位 (3.3V)後發送超聲波
● ECHO腳位維持低電位 (0V),收到回應後拉到高電位 (5V)
● Raspberry Pi腳位的容忍電位為 3.3V
=> 將 ECHO腳位的 5V降壓為 3.3V左右
分壓電路計算
https://www.modmypi.com/blog/hc-sr04-ultrasonic-range-sensor-on-the-raspberry-pi=> R1=1K, R2取 2K
131
注意 1K, 2K 電阻
ULTRASONIC RPiVcc(RED) Pin2 (5V)Trig(YELLOW) Pin16 (GPIO23)Echo(PURPLE) Pin18 (GPIO24)Grnd(BLACK) Pin6 (Ground)
1k:棕黑黑棕
2k:棕黑黑棕
VccGnd Echo Trig
132
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
測量距離
133
DEMOhc_sr04_measure_distance.py
$ cd ~/gpio-game-console
$ cd 08-hc_sr04_measure_distance
$ python hc_sr04_measure_distance.py
137
● 旋轉式 ,滑動式
● 線性關係 (B 型 ),對數關係 (A型 )● 常見規格 :0 -10k Ohm( 線性 )
可變電阻 Potentiometer(VR)
https://en.wikipedia.org/wiki/Potentiometer
接高電位
接低電位
滑動接點 (可變輸出 )
140
● 是將類比信號轉為脈波的一種技術
● 頻率不變 + 改變工作週期 , 使整體平均電壓值改變
● 改變工作週期 (duty cycle)= 改變平均電壓
脈寬調變 (Pulse-Width Modulation)
http://wiki.csie.ncku.edu.tw/embedded/PWM
141
● 輸出總功率 =脈衝寬度 (時間 )x 高電位值
公式計算
http://www.protostack.com/blog/2011/06/atmega168a-pulse-width-modulation-pwm/
142
● To create a PWM instance:
● p = GPIO.PWM(channel, frequency)
● To start PWM:
● p.start(dc) # dc is the duty cycle
● To change the duty cycle:
● p.ChangeDutyCycle(dc) # where 0.0 <= dc <= 100.0
● To stop PWM:
● p.stop()
GPIO.PWM()
http://sourceforge.net/p/raspberry-gpio-python/wiki/PWM/
144
LED_PIN = 12
● GPIO.setup(LED_PIN, GPIO.OUT)
pwm_led = GPIO.PWM(LED_PIN, 100)
● pwm_led.start(100)
●
● try:
● while True:
● duty_s = raw_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()
互動式的調光
145
DEMOadjust_led_bright.py
$ cd ~/gpio-game-console
$ cd 09_1-adjust_led_bright
$ python adjust_led_bright.py
146
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 xrange(0, 101, 5):
pwm_led.ChangeDutyCycle(dc)
time.sleep(0.1)
time.sleep(0.5)
for dc in xrange(100, -1, -5):
pwm_led.ChangeDutyCycle(dc)
time.sleep(0.1)
time.sleep(0.5)
呼吸燈就是漸明漸亮
147
● 兩者差異
● Software PWM是透過kernel做duty cycle的調整
● Hardware PWM是SoC透過DMA做調整● 使用時機
● 不需要精準時用Software PWM,例如LED調光● 需要低延遲時用Hardware PWM,例如伺服馬達
● Hardware PWM GPIO只有實體腳位Pin 12和Pin 33(Model B+以後)支援
● 目前已經內建pigpiod提供Hardware PWM函式呼叫
Software PWM vs. Hardware PWM
150
● 硫化鎘 (CdS) 或光敏電阻器 (LDR), 阻抗隨光落在表面的總量而轉變
● 光越強阻值越小 ,反之光越弱阻值則越大
● 應用 :光控開關 ,電子玩具 ,工業控制
光敏電阻
http://www2.nkfust.edu.tw/~jlkuo2/31/a6.htm
151
● Raspberry Pi沒有硬體的類比數位轉換器 (ADC)
類比訊號轉換為數位訊號
http://www.planetoftunes.com/digital-audio/how-do-analogue-to-digital-converters-work.html
IN ADC OUT
此ADC 的解析度為 4bits從 0000 到 1111(看 Y軸 )
153
● 主從式架構 , 可一對多
● 四線同步序列資料協定
● SS:週邊選擇線 (CE)● SCK:序列時脈線 (SCLK)● MOSI: 主往從送
● MISO: 從往主送
Serial Peripheral Interface(SPI)
https://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus
157
● 測試確認SPI模組已載入
● $ ls /dev/spi*
● 安裝必要套件(如果前面已裝過,就不需再裝)● $ sudo apt-get update● $ sudo apt-get install -y python-dev python-pip
● $ sudo pip install spidev
SPI 使用前的確認
160
spi = spidev.SpiDev()
spi.open(0,0) # (0,0)表示接到CE0腳位,對應到/dev/spidev0.0裝置檔
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)
162
● input一次送三個bytes● # byte 1: the start bit (always 0x01)● # byte 2: configure bits● # byte 3: don't care
● spi.xfer2([1,(8+channel)<<4,0])
● Ch0 = 1000 0000● Ch1 = 1001 0000
了解 spi.xfer2() 的意義
0x01 don't careCh0/Ch1
168
● 模擬不同的硬體架構● 常見的模擬器:
● MAME (AdvanceMAME)● Nintendo Entertainment System (RetroArch)
● Super Nintendo Entertainment System (PiSNES)
● PC / x86 (rpix86)
Video Game System Emulators
https://en.wikipedia.org/wiki/List_of_video_game_emulators
173
● $ sudo apt-get install x11vnc● $ x11vnc
● 更多設定
● x11vnc 不斷線
– $ x11vnc -forever
● 設定 x11vnc 連線視窗大小
– $ x11vnc -geometry 寬度 x高度
在 Pi 安裝和執行 x11vnc Server
英文字母小寫 x
176
● Windows:
● 下載UltraVNC (可以只安裝Viewer)
– http://www.uvnc.com/downloads/
x11vnc Client 安裝
Port 和 x11vnc 相同
178
● 下載編譯好的binary(已經下載好了)
● $ cd ~● $ wget http://goo.gl/mN5zhS -O advmame● $ chmod 755 advmame● $ ./advmame
● 2.下載rom(還沒下載)
● $ cd /home/pi/.advance/rom● Google搜尋AdvanceMAME suprmrio rom
● 3. 執行模擬器
● $ cd /home/pi● $ ./advmame suprmrio
在 x11vnc下執行 AdvanceMAME
179
● 搜尋MAME● http://www.emuparadise.me/
● 中英文對照● http://bbs.duowan.com/thread-41350071-1-1.html
● 經典遊戲● 超級瑪莉歐● 彈珠台● 小精靈● 坦克大作戰,泡泡龍...
下載 ROM放到對應的目錄下
http://en.wikipedia.org/wiki/Nintendo_Entertainment_System
180
● 執行模擬器 , 使用 keyboard 控制
● 讀取 GPIO搖桿的值
● 讓 GPIO搖桿和 keyboard對應
● 開機就啟動按鍵與 keyboard對應程式
● 開機就啟動模擬器
遊戲機製作步驟
http://bruxy.regnet.cz/web/linux/EN/housenka-bash-game/http://www.linuxuser.co.uk/tutorials/emulate-a-bluetooth-keyboard-with-the-raspberry-pi
181
● $ cd ~● $ ./advmame suprmrio
● 按 'o' 'k'進入畫面
● 按 '5'投錢
● 按 '1'開始
● 左邊 'ctrl'是加速
● 左邊 'alt'是跳
● 按 'esc'是離開
使用模擬器
183
● 3.3V-5V工作電壓
● 輸出形式:
● x,y軸 - 類比輸出
● z軸 - 數位輸出
XY雙軸搖桿
http://www.aliexpress.com/cheap/cheap-arduino-joystick.html
184http://www.raspberrypi-spy.co.uk/2014/04/using-a-joystick-on-the-raspberry-pi-using-an-mcp3008/
+5VMS VRY VRX GND
185
spi = spidev.SpiDev()
● spi.open(0,0)
●
● 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))
●
● time.sleep(0.5)
186
DEMOmcp3008_joystick
$ cd ~/gpio-game-console
$ cd 11_1-mcp3008_joystick
$ python mcp3008_joystick.py
190
● USB或 PS2 keyboard都是同一個 handler處理
● 我們可以加上 GPIO的 driver,讓 keyboard handler來接?
Linux Input Subsystem
http://www.linuxjournal.com/article/6396
USB Keyboard
PS2 Keyboard
192
● evdev● Bindings to the Linux input handling subsystem
● python-evdev● provides bindings to the generic input event interface in Linux
● 安裝(如果前面已裝過, 就不需再裝)● $ sudo pip install evdev
python-evdev
https://pypi.python.org/pypi/evdev
193
python-evdev keyboard examplefrom 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()
194
DEMOevdev_keyboard.py
$ cd ~/gpio-game-console
$ cd 11_2-evdev_keyboard
$ sudo python evdev_keyboard.py
199
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)
200
DEMOjoystick_mapping_keyboard.py
$ cd ~/gpio-game-console
$ cd 11_3-joystick_mapping_keyboard
$ sudo python joystick_mapping_keyboard.py
203
DEMOgaming_console.py
$ cd ~/gpio-game-console
$ cd 13-gaming_console
$ sudo python gaming_console.py
205
● 第二個執行搖桿按鍵對應程式(serial或ssh)
● $ cd ~/gpio-game-console/11_3-joystick_mapping_keyboard● $ sudo python joystick_mapping_keyboard.py
用搖桿控制超級瑪莉
從 serial 或 ssh 連線後執行搖桿按鍵對應程式
207
● 一次性的執行 , 可以放在 /etc/rc.local 裡
● 以服務的方式執行 ,需寫 systemd 設定檔
● 有畫面的程式前景執行 ,用 LXDE的 autostart
開機就執行?
208
● 新增黃色字的部份
● $ sudo nano /etc/rc.local
sudo python /home/pi/gpio-game-console/13-gaming_console/gaming_console.py &
# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
printf "My IP address is %s\n" "$_IP"
fi
exit 0
開機就執行搖桿對應按鍵程式
209
● 新增黃色字的部份
● $ nano ~/.config/lxsession/LXDE-pi/autostart
@lxpanel --profile LXDE-pi
@pcmanfm --desktop --profile LXDE-pi
@xscreensaver -no-splash
@lxterminal -e /home/pi/advmame suprmrio
● 設定完以後重開機試試看吧
進入桌面環境後就執行超級瑪莉
216
● 安裝gcc-4.8
● $ sudo apt-get install gcc-4.8● 下載advancemame-1.4.tar.gz
● http://www.advancemame.it/download● 安裝
● $ sudo apt-get install -y gcc-4.8 libsdl1.2-dev● $ tar zxvf advancemame-1.4.tar.gz● $ cd advancemame-1.4/● $ CC=gcc-4.8 GCC=g++-4.8 ./configure --disable-fb● $ make -j4● $ ./advmame
AdvanceMAME
217
● 1.產生rc檔● $ cd /home/pi/advancemame-1.4● $ chmod 755 advmame● $ ./advmame
● 2.下載rom● $ cd /home/pi/.advance/rom
● 3. 執行模擬器
● $ cd /home/pi/advancemame-1.4● $ ./advmame suprmrio
執行模擬器