以下會簡單介紹 Raspberry Pi 的用途,安裝 Raspbain 作業系統,最後寫一個 Python 程式讓 Raspberry Pi 透過蜂鳴器唱出世界名曲-小蘋果。廢話不多說直接先 po 成果:
流水帳
Raspberry Pi 出一陣子了,突然想買是因為最近出二代了,價錢不變但 CPU 變四核心,也就還蠻心動的,在 RS 上買含運也不到1200元, 但下完單才發現三月中才能拿到(靠!我是想買來過年玩的誒),就在機器人王國又花了一千七百多買了Raspberry Pi B+ 套餐(多外殼,5V2A 電源 + 金士頓 16G micro SD 卡),現在算算反正我一時用不到很多輸出,應該就直接花五百單買出清中的 Raspberry Pi B 就夠了。總共我買了以下設備:
- Raspberry Pi 2 B(還在海上...)
- Raspberry Pi B+
- b+ 透明外殼(可用在 2 上)
- 5V2A 電源
- 金士頓 class 10 16G micro SD 卡
- 羅技無線鍵盤 k400r(含觸碰板)
- 麵包板
- 杜邦線公+母
- LED
- 電阻
- 蜂鳴器
Raspberry Pi 能做啥?
反正出發點跟百元筆電一樣,是希望大家能以比較低的價格擁有一個能寫程式的硬體,基本上可以想成一台像信用卡大小的電腦,上面跑 Linux 的作業系統,插上滑鼠鍵盤再用 HDMI 輸出到螢幕上就是一台電腦。因為價格實在太便宜了,除了拿來當電腦用以外,有人會拿來安裝軟體/作業系統,把 Raspberry Pi 搖身一變當成 Web Server,家庭娛樂中心,NAS,電動模擬器來使用。

另外 Raspberry Pi 版子上有一組 GPIO 輸入輸出界面,裝上感應器/攝影機當輸入,裝上馬達/蜂鳴器/LED Matrix 當輸出,輸出輸入都可以透過程式(Python,Java...)的方式來控制,對軟體工程師來說,瞬間突破了只能用鍵盤當輸入,螢幕顯示當輸出的限制,感覺又可以幹很多壞事了...
安裝 OS
我選的是最多人用的 Raspbain,參考官方說明絕對不會錯,大概步驟如下:- 格式化 SD 卡
- 下載 Raspbain
- 透過特殊軟體將 Raspbain 寫到 SD 卡上
- SD 卡裝到 Raspberry 後開機
- 第一次開機會進入設定畫面(鍵盤,語系,開啟 SSH...etc)
第一支 Script
因為之後這台 Raspberry Pi 可能會拿來拿去,不想每一次都要接上螢幕鍵盤進去看 IP,所以想要一開機就自己把自己取得的 IP 寄到我的 Gmail 信箱,詳細步驟如下:- 寫一個 Python Script - send_ip.py (程式碼參考下面)取得 IP 透過 Gmail 寄到你指定的信箱。
- 寫一個 Script - laucher.sh 內容為執行 send_ip.py。
- 將 laucher.sh 設定成開機時會自動執行。
- 將 launcher.sh 拷貝到 /etc/initd
- sudo update-rc.d launcher.sh defaults # 新增開機執行
- sudo chmod +x /etc/init.d/launcher.sh # 增加執行的權限
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/local/bin/python | |
import commands | |
def getIpList(): | |
ipList = commands.getoutput("/sbin/ifconfig | grep -i \"inet\" | grep -iv \"inet6\" | " + | |
"awk {'print $2'} | sed -ne 's/addr\:/ /p'") | |
return ipList | |
import smtplib | |
def sendViaGmail(title, message): | |
fromaddr = 'foo@gmail.com' | |
toaddrs = 'bar@gmail.com' | |
msg = "\r\n".join([ | |
"From: foo@gmail.com", | |
"To: bar@gmail.com", | |
"Subject: " + title, | |
"", | |
message | |
]) | |
username = 'your_gmail_id@gmail.com' | |
password = 'your_gmail_password' | |
server = smtplib.SMTP('smtp.gmail.com:587') | |
server.ehlo() | |
server.starttls() | |
server.login(username,password) | |
server.sendmail(fromaddr, toaddrs, msg) | |
server.quit() | |
import socket | |
message = socket.gethostname() + ":\n" + getIpList() | |
title = socket.gethostname() + " wake up now" | |
print "Sending mail..." | |
sendViaGmail(title, message) |
小蘋果
書看再多還不如動手做比較印象深刻,我買 Raspberry Pi 主要是想玩一些硬體的東西,未來搭配程式可以做一些小玩具,第一支程式的目標是讓 Raspberry Pi 唱出小蘋果,當然一開始是完全沒頭緒,只知道用 Python 可以控制 GPIO,GPIO 的訊號可以控制蜂鳴器發出聲音。一開始是直接 SSH 連進去用 vim 寫 Python,好處是直接在上面跑結果,但 vim 對我來說還是有些難用。後來想改用在 macbook pro 上用 IDE 寫,然後透過 git 兩邊作同步的方式,但實際應用每次修改都要上 commit / push,Raspberry Pi 又要 pull 下來才能執行,感覺更麻煩了。
最終改用 FTP + git 的方式來開發,Raspberry Pi 上裝 vftpd 當作 FTP Server,在 macbook pro 上開發透過 FTP 上傳到 Raspberry Pi(部署至硬體),Raspberry Pi 執行成功在 commit 到 git 上(版本控管)。FTP 上傳這段,應該有 IDE 支援,不過過年時間有限 + 還不確定未來都是用 Python 來開發,就先這樣。
上網找到這影片如下,最後我的接法跟他差不多。
- 硬體部分:透過 GPIO 接上蜂鳴器當輸出。
- 軟體部分:透過 Python (程式碼如下)控制 GPIO 接上蜂鳴器的針腳,改變其發生頻率和播放時間。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/local/bin/python | |
import time | |
import RPi.GPIO as GPIO | |
# http://coopermaa2nd.blogspot.tw/2010/12/arduino-lab6.html | |
B0 = 31 | |
C1 = 33 | |
CS1 = 35 | |
D1 = 37 | |
DS1 = 39 | |
E1 = 41 | |
F1 = 44 | |
FS1 = 46 | |
G1 = 49 | |
GS1 = 52 | |
A1 = 55 | |
AS1 = 58 | |
B1 = 62 | |
C2 = 65 | |
CS2 = 69 | |
D2 = 73 | |
DS2 = 78 | |
E2 = 82 | |
F2 = 87 | |
FS2 = 93 | |
G2 = 98 | |
GS2 = 104 | |
A2 = 110 | |
AS2 = 117 | |
B2 = 123 | |
C3 = 131 | |
CS3 = 139 | |
D3 = 147 | |
DS3 = 156 | |
E3 = 165 | |
F3 = 175 | |
FS3 = 185 | |
G3 = 196 | |
GS3 = 208 | |
A3 = 220 | |
AS3 = 233 | |
B3 = 247 | |
C4 = 262 # Do | |
CS4 = 277 | |
D4 = 294 # Re | |
DS4 = 311 | |
E4 = 330 # Mi | |
F4 = 349 # Fa | |
FS4 = 370 | |
G4 = 392 # So | |
GS4 = 415 | |
A4 = 440 # La | |
AS4 = 466 | |
B4 = 494 # Si | |
C5 = 523 # Do | |
CS5 = 554 | |
D5 = 587 # Re | |
DS5 = 622 | |
E5 = 659 # Mi | |
F5 = 698 # Fa | |
FS5 = 740 | |
G5 = 784 # So | |
GS5 = 831 | |
A5 = 880 # La | |
AS5 = 932 | |
B5 = 988 # Si | |
C6 = 1047 # Do | |
CS6 = 1109 | |
D6 = 1175 # Re | |
DS6 = 1245 | |
E6 = 1319 # Mi | |
F6 = 1397 # Fa | |
FS6 = 1480 | |
G6 = 1568 # So | |
GS6 = 1661 | |
A6 = 1760 # La | |
AS6 = 1865 | |
B6 = 1976 # Si | |
C7 = 2093 # Do | |
CS7 = 2217 | |
D7 = 2349 | |
DS7 = 2489 | |
E7 = 2637 | |
F7 = 2794 | |
FS7 = 2960 | |
G7 = 3136 | |
GS7 = 3322 | |
A7 = 3520 | |
AS7 = 3729 | |
B7 = 3951 | |
C8 = 4186 | |
CS8 = 4435 | |
D8 = 4699 | |
DS8 = 4978 | |
M_1 = C4 | |
M_2 = D4 | |
M_3 = E4 | |
M_4 = F4 | |
M_5 = G4 | |
M_6 = A4 | |
M_7 = B4 | |
H_1 = C5 | |
H_2 = D5 | |
H_3 = E5 | |
H_4 = F5 | |
H_5 = G5 | |
H_6 = A5 | |
H_7 = B5 | |
''' | |
http://www.chaodikong.com/article/2014/0917/article_26645.html | |
''' | |
def playLittleApple(): | |
GPIO.setmode(GPIO.BOARD) | |
#GPIO.setmode(GPIO.BCM) | |
GPIO.setup(12, GPIO.OUT) | |
p = GPIO.PWM(12, 50) # pin12(GPIO.BOARD) = GPIO14(GPIO.BCM) | |
p.start(15) # 0 <= DV <= 100 | |
play(p, H_1, 0.5) | |
play(p, H_1, 0.5) | |
play(p, H_1, 0.5) | |
play(p, H_1, 0.5) | |
play(p, H_1, 0.5) | |
play(p, H_1, 0.5) | |
play(p, H_1, 0.5) | |
play(p, M_6, 0.5) | |
play(p, H_1, 0.5) | |
play(p, H_1, 0.5) | |
play(p, H_1, 0.5) | |
play(p, H_1, 0.5) | |
play(p, H_1, 0.5) | |
play(p, H_1, 0.5) | |
play(p, H_1, 0.5) | |
play(p, M_5, 0.5) | |
play(p, M_5, 0.5) | |
play(p, M_5, 0.5) | |
play(p, M_5, 0.5) | |
play(p, M_5, 0.5) | |
play(p, M_5, 0.5) | |
play(p, M_6, 0.5) | |
play(p, M_5, 0.5) | |
play(p, M_6, 0.5) | |
play(p, M_6, 4) | |
play(p, H_1, 0.5) | |
play(p, H_1, 0.5) | |
play(p, H_1, 0.5) | |
play(p, H_1, 0.5) | |
play(p, H_1, 0.5) | |
play(p, H_1, 0.5) | |
play(p, H_1, 0.5) | |
play(p, M_6, 0.5) | |
play(p, H_1, 0.5) | |
play(p, H_1, 0.5) | |
play(p, H_1, 0.5) | |
play(p, H_1, 0.5) | |
play(p, H_1, 0.5) | |
play(p, H_1, 0.5) | |
play(p, H_1, 0.5) | |
play(p, M_5, 0.5) | |
play(p, M_5, 0.5) | |
play(p, M_5, 0.5) | |
play(p, M_5, 0.5) | |
play(p, M_5, 0.5) | |
play(p, M_5, 0.5) | |
play(p, M_6, 0.5) | |
play(p, M_5, 0.5) | |
play(p, M_6, 0.5) | |
play(p, M_6, 4) | |
play(p, M_6, 0.5) | |
play(p, M_6, 0.5) | |
play(p, M_6, 0.5) | |
play(p, M_7, 0.5) | |
play(p, H_1, 0.5) | |
play(p, H_3, 0.5) | |
play(p, H_2, 0.5) | |
play(p, H_1, 0.5) | |
play(p, M_7, 0.5) | |
play(p, M_6, 0.5) | |
play(p, M_7, 0.5) | |
play(p, M_6, 0.5) | |
play(p, M_7, 0.5) | |
play(p, M_7, 1.5) | |
play(p, M_5, 0.5) | |
play(p, M_5, 0.5) | |
play(p, M_5, 0.5) | |
play(p, M_6, 0.5) | |
play(p, M_7, 0.5) | |
play(p, H_2, 0.5) | |
play(p, H_1, 0.5) | |
play(p, M_7, 0.5) | |
play(p, M_6, 0.5) | |
play(p, M_5, 0.5) | |
play(p, M_6, 0.5) | |
play(p, M_5, 0.5) | |
play(p, M_6, 2) | |
play(p, M_6, 0.5) | |
play(p, M_6, 0.5) | |
play(p, M_6, 0.5) | |
play(p, M_7, 0.5) | |
play(p, H_1, 0.5) | |
play(p, H_3, 0.5) | |
play(p, H_2, 0.5) | |
play(p, H_1, 0.5) | |
play(p, M_7, 0.5) | |
play(p, M_6, 0.5) | |
play(p, M_7, 0.5) | |
play(p, M_6, 0.5) | |
play(p, M_7, 0.5) | |
play(p, M_7, 1.5) | |
play(p, M_5, 0.5) | |
play(p, M_5, 0.5) | |
play(p, M_5, 0.5) | |
play(p, M_6, 0.5) | |
play(p, M_7, 0.5) | |
play(p, H_2, 0.5) | |
play(p, H_1, 0.5) | |
play(p, M_7, 0.5) | |
play(p, H_1, 1) | |
play(p, H_1, 1) | |
play(p, H_1, 1) | |
play(p, H_1, 1) | |
play(p, H_3, 1) | |
play(p, H_1, 1) | |
play(p, H_2, 1) | |
play(p, M_6, 1) | |
play(p, H_3, 0.5) | |
play(p, H_2, 0.5) | |
play(p, H_1, 0.5) | |
play(p, H_2, 0.5) | |
play(p, M_6, 2) | |
play(p, H_3, 1) | |
play(p, H_1, 1) | |
play(p, H_2, 1) | |
play(p, H_2, 1) | |
play(p, H_5, 0.5) | |
play(p, H_3, 0.5) | |
play(p, M_7, 1) | |
play(p, H_1, 1) | |
play(p, H_1, 0.5) | |
play(p, M_7, 0.5) | |
play(p, M_6, 1) | |
play(p, M_7, 0.5) | |
play(p, H_1, 0.5) | |
play(p, H_2, 0.5) | |
play(p, M_5, 0.5) | |
play(p, M_5, 1) | |
play(p, H_6, 0.5) | |
play(p, H_5, 0.5) | |
play(p, H_3, 0.5) | |
play(p, H_5, 0.5) | |
play(p, H_3, 1) | |
play(p, H_2, 1) | |
play(p, H_1, 1) | |
play(p, H_2, 0.5) | |
play(p, H_3, 0.5) | |
play(p, H_2, 0.5) | |
play(p, H_3, 0.5) | |
play(p, H_2, 0.5) | |
play(p, H_5, 0.5) | |
play(p, H_5, 1) | |
play(p, H_5, 1) | |
play(p, H_5, 1) | |
play(p, H_5, 1) | |
play(p, H_3, 1) | |
play(p, H_1, 1) | |
play(p, H_2, 1) | |
play(p, M_6, 1) | |
play(p, H_3, 0.5) | |
play(p, H_2, 0.5) | |
play(p, H_1, 0.5) | |
play(p, H_2, 0.5) | |
play(p, M_6, 2) | |
play(p, H_3, 1) | |
play(p, H_1, 1) | |
play(p, H_2, 1) | |
play(p, H_2, 0.5) | |
play(p, H_2, 0.5) | |
play(p, H_5, 0.5) | |
play(p, H_3, 0.5) | |
play(p, M_7, 1) | |
play(p, H_1, 1) | |
play(p, H_1, 0.5) | |
play(p, M_7, 0.5) | |
play(p, M_6, 1) | |
play(p, M_7, 0.5) | |
play(p, H_1, 0.5) | |
play(p, H_2, 0.5) | |
play(p, M_5, 0.5) | |
play(p, M_5, 1) | |
play(p, H_6, 0.5) | |
play(p, H_5, 0.5) | |
play(p, H_3, 0.5) | |
play(p, H_5, 0.5) | |
play(p, H_3, 1) | |
play(p, H_2, 1) | |
play(p, H_1, 1) | |
play(p, H_2, 0.5) | |
play(p, H_3, 0.5) | |
play(p, H_2, 0.5) | |
play(p, M_5, 0.5) | |
play(p, M_5, 1) | |
play(p, M_6, 1) | |
play(p, M_6, 0.5) | |
play(p, H_1, 0.5) | |
play(p, M_6, 1) | |
play(p, M_6, 1) | |
p.stop | |
GPIO.cleanup() | |
def play(p, frequency, tempo): | |
p.ChangeFrequency(frequency) | |
time.sleep(0.5 * tempo) | |
def playDoReMi(): | |
GPIO.setmode(GPIO.BOARD) | |
#GPIO.setmode(GPIO.BCM) | |
GPIO.setup(12, GPIO.OUT) | |
p = GPIO.PWM(12, 50) # pin12(GPIO.BOARD) = GPIO14(GPIO.BCM) | |
p.start(25) # 0 <= DV <= 100 | |
print "Do" | |
p.ChangeFrequency(523) | |
time.sleep(1) | |
print "Re" | |
p.ChangeFrequency(587) | |
time.sleep(1) | |
print "Mi" | |
p.ChangeFrequency(659) | |
time.sleep(1) | |
p.stop() | |
GPIO.cleanup() | |
#playDoReMi() | |
#playDoReMi() | |
playLittleApple() |
結語
整篇文章看完,我們可以得到以下結論:- Raspberry Pi 不會很貴!
- Raspberry Pi 可以拿來當 Linux Server 用!
- 透過 Raspberry Pi 的 GPIO,程式設計師可以有更多種輸入/輸出的選擇!