之前Raspberry Pi社群聚會#3,台灣樹莓派許先生展示了許多跟相機模組相關的應用,其中有一個便是製作數位相機,我也買了相關模組試試看;不過原廠已經寫了相當詳細的文件,包括 Adafruit PiTFT - 2.8" Touchscreen Display for Raspberry Pi與DIY WiFi Raspberry Pi Touchscreen Camera,所以這裡不再重複,只是玩玩看,記錄一下而已。
底下便是主要模組,包括2.8吋觸控螢幕、相機模組,以及特別設計過的外殼,另外還有USB無線網卡。當然啦,另外還需要行動電源,也可以使用無線鍵盤。
2014/04/30
Raspberry Pi數位相機
標籤: Raspberry Pi
2014/04/27
[廣告] Arduino機器人製作聖經(Arduino Robot Bonanza)
嗨,我翻譯了一本書,在這裡打打廣告。
顧名思義,這本書以Arduino微控制器開發板為中心,打造各種機器人,包括自走車、尋跡車、機器手臂、在地上扭來扭去的蛇機 、承載樂隊的履帶坦克、等等。
書名:Arduino機器人製作聖經
原書名:Arduino Robot Bonanza
作者:Gordon McComb
譯者:我
出版社:馥林文化
出版日期:2014年4月24日
頁數:488
製作能行走、能說話、又會思考的高科技機器人!
將生命力帶進你夢想中的機器人體內,但不需要高深的電子學知識或程式設計技巧。本書將實際示範只需使用一般的工具與常見電子零件,就可以打造自主行動的機器人。並且學習如何連接電子線路建構硬體、撰寫程式成為機器人的大腦,以及添加只專屬於你自己的獨特需求。
這本著作易讀易懂,含有圖文並茂的步驟指引,而且從初步入門的教學學習用機器人開始,逐步攻克更複雜的專題,包括音樂旋律機器人、遠端遙控機器人、滑來滑去的蛇型機,以及一支能觸及16吋範圍的機器手臂!
目錄
前言
第一部分 Arduino機器人基礎知識
第1章:介紹Arduino開發平臺
第2章:讓Arduino動起來
第3章:建構教學機學習平臺
第4章:為教學機開發程式:讓它動起來吧
第5章:為教學機開發程式:看著它回應
第6章:為教學機開發程式:讓它去探索世界
第二部分 實物製作
第7章:實物製作:機械
第8章:實物製作:電子
第三部分 Arduino機器人專題實作
第9章:教學機功能升級
第10章:令人驚訝的旋律機器人
第11章:隨著遠控機器人瀏覽四周
第12章:為什麼非要是蛇不可呢?
第13章:羅比.阿姆斯壯
第四部分 附錄
附錄A:本書線上支援網站與相關資料
附錄B:零件材料何處尋
附錄C:疑難排除技巧:如何避免事情出錯!
Raspberry Pi情報彙整(25)
我將網路上看到的、感興趣的、跟Raspberry Pi相關的資訊收集如下。如果您發現任何新奇驚人的新聞或專案,還請留言告知。
An Emulated Commodore 64 Operating System for the Raspberry Pi,在rpi上模擬Commodore 64的作業系統。聽說Commodore 64賣出2千7百萬台,時至今日仍然有許多忠心的粉絲。
標籤: Raspberry Pi
2014/04/19
Raspberry Pi社群聚會 #4
Raspberry Pi社群聚會#4來囉,前幾次聚集了不少各領域的人物,希望這次也能看到各方高手。
日期:2014年4月21日,19:30~21:30,半小時前開始入場。
地點:CLBC共同工作空間,台北市大安區復興南路一段293號4樓。至捷運大安站下車,出口後直走60秒內可抵達CLBC大安館。
費用:每人150元場地費用,帶作品展示的參加者免收場地費用。提供無線網路,場地有飲料,請大家先在附近用餐再入場。
活動報名網址在此。
分享者1:邱展逢(學習樹莓派作者)
Topic:scratch和自走車
分享者2:葉難(Raspberry Pi從入門到應用作者)
Topic:用Raspberry做紅外線遙控車
希望能看到大家帶作品前往展示,互相交流。
標籤: Raspberry Pi
2014/04/15
自己以ATtiny85建構Adafruit Trinket
之前曾介紹過Adafruit公司的小型Arduino開發板Trinket,這篇則是自己在麵包板或洞洞板(萬用電路板)上建構具備相同功能的Arduino。
所需零件:
- LM7805,5V穩壓器,1個。
- 電解電容0.33μF,1個。
- 陶瓷電容0.1μF,1個。
- ATtiny85微控制器晶片,1個。
- 電解電容10μF,1個。
- 按壓開關,1個。
- 綠色LED,1個。
- 紅色LED,1個。
- 碳膜電阻470Ω,2個。
- Zener二極體3.6V,2個。
- 碳膜電阻68Ω,2個。
- 碳膜電阻1.5kΩ,1個。
- USB Type-B母座,1個。
- Schottky二極體,1個。
若先在麵包板上建構,電路圖如下。其實就跟Adafruit提供的Trinket 5V電路圖相同。
至於腳位對應則如下圖,不過其中針腳1已作為重置功能,再扣掉VCC與GND,還有5個腳位,可當做數位腳位(標示為D0~D4),有3個腳位具備PWM功能(PWM0、PWM1、PWM4),有3個腳位可作為類比輸入(Ain1、Ain2、Ain3)。其中ATtiny85的針腳2與3連接USB的資料線路。
只不過我弄出來的作品體積很大,若想要小型化,可看看底下的參考資料。
參考資料:
- Adafruit Learning System的Introducing Trinket。
- ATtiny85可用的bootloader,Adafruit開發的、micronucleus。
- Product development from the ground up: Shrinket, Arduino compatible ATtiny85 development board,使用SMD元件。
- A Trinket clone using only through-hole components,只使用穿孔元件,自己洗電路板。
- Paperduino Tiny,在紙上建構。
- micronucleus,另一套ATtiny85可使用的bootloader。
- Programming the ATtiny85 from Raspberry Pi。
2014/04/13
Arduino Yún:Bridge程式庫入門(YunServer與YunClient)
這一篇玩玩Bridge程式庫裡的YunServer與YunClient這兩個類別,程式碼主要都來自於Arduino官方文件Guide to the Arduino Yún。
我的Yún與開發主機位於同一個區域網路內,我的Arduino軟體開發環境是1.5.6-r2版。首先從瀏覽器登入Yún,開啟REST API存取權限為OPEN。
#include <Bridge.h>
#include <YunServer.h>
#include <YunClient.h>
YunServer server; // 建立YunServer物件
void setup() {
Serial.begin(19200);
Bridge.begin(); // 啟動Bridge
while(!Serial)
;
server.listenOnLocalhost(); // 設定讓伺服器聆聽本地端IP位址的連線
server.begin(); // 開始
}
void loop() {
YunClient client = server.accept(); // 有連線進來了
if(client){
process(client); // 開始處理,分析API
client.stop();
}
delay(50);
}
void process(YunClient client){
String command = client.readStringUntil('/');
if(command == "digital"){ // 數位輸入輸出
digitalCommand(client);
}
else if(command == "analog"){ // 類比輸入輸出
analogCommand(client);
}
else if(command == "mode"){ // 設定腳位模式
modeCommand(client);
}
}
void digitalCommand(YunClient client){
int pin, value;
pin = client.parseInt();
if(client.read() == '/'){ // 數位輸出,設定為1(高電位)或0(低電位)
value = client.parseInt();
digitalWrite(pin, value);
client.print("Pin ");
client.print(pin);
client.print(" set to ");
client.println(value);
}
else{ // 數位輸入,讀取該腳位的值
value = digitalRead(pin);
client.print("Pin ");
client.print(pin);
client.print(" reads ");
client.println(value);
}
}
void analogCommand(YunClient client){
int pin, value;
pin = client.parseInt();
if(client.read() == '/'){ // 類比輸出,設定PWM值為0~255
value = client.parseInt();
analogWrite(pin, value);
client.print("Pin ");
client.print(pin);
client.print(" set to analog ");
client.println(value);
}
else{ // 類比輸入,讀取該類比腳位的值
value = analogRead(pin);
client.print("Pin ");
client.print(pin);
client.print(" reads analog ");
client.println(value);
}
}
void modeCommand(YunClient client){
int pin;
pin = client.parseInt();
if (client.read() != '/') {
client.println("error");
return;
}
String mode = client.readStringUntil('\r');
if(mode == "input"){ // 設為輸入模式
pinMode(pin, INPUT);
client.print("Pin ");
client.print(pin);
client.print(" configured as INPUT.");
return;
}
else if(mode == "output"){ // 設為輸出模式
pinMode(pin, OUTPUT);
client.print("Pin ");
client.print(pin);
client.print(" configured as OUTPUT.");
return;
}
client.print("error: invalid mode ");
client.print(mode);
}
然後從別台電腦的瀏覽器,輸入類似底下的網址,請把arduino.local換成你的Yún的IP位址。
把腳位13設為輸出模式:
http://arduino.local/arduino/mode/13/output
瀏覽器上會看到回應:
Pin 13 configured as OUTPUT.
把腳位13設為高電位,其連接的LED會亮起:
http://arduino.loca/arduino/digital/13/1
瀏覽器上會看到回應:
Pin 13 set to 1
把腳位13設為高電位,其連接的LED會熄滅:
http://arduino.loca/arduino/digital/13/0
瀏覽器上會看到回應:
Pin 13 set to 0
腳位3輸出PWM128:
http://arduino.loca/arduino/analog/3/128
瀏覽器上會看到回應:
Pin 3 set to analog 128
讀取類比腳位A0(對應腳位編號18)的值:
http://arduino.loca/arduino/analog/18
瀏覽器上類似底下的回應:
Pin 18 reads analog 147
嗯,大概就這樣吧。
參考資料:
- Arduino官方文件,Guide to the Arduino Yún、YunServer類別與YunClient類別。
Arduino Yún:Bridge程式庫入門(FileIO類別)
Yún不僅可插micro SD記憶卡,用來儲存檔案,其實也可存放在Atheros AR9331它自己本身的Flash快閃記憶體空間,但只有幾MB而已。
作法是透過Bridge程式庫的FileIO類別,範例程式如下,每10秒讀取一次類比腳位A0的值,並且取得當時的日期時間,然後一併記錄在檔案裡。
#include <FileIO.h>
void setup() {
Bridge.begin();
Serial.begin(19200);
FileSystem.begin(); // 初始化檔案系統
while(!Serial)
;
}
void loop () {
// 欲儲存的路徑檔名
// 若想儲存在micro SD卡裡,路徑需改成/mnt/sda1
// 若在micro SD卡裡建立目錄arduino,那麼可使用路徑/mnt/sd
const char filenamepath[] = "/root/data.txt";
String data; // 將要寫入檔案的資料
data += getTimeStamp(); // 取得日期時間
data += ", Analog Pin A0 = ";
data += analogRead(A0); // 讀取A0的值
// 根據檔案存在與否判斷開檔模式
int mode = FileSystem.exists(filenamepath) ? FILE_APPEND : FILE_WRITE;
File file = FileSystem.open("/root/data.txt", mode); // 開檔
if(file){ // 確認開檔成功
file.println(data); // 寫入資料
file.close(); // 關檔
}
delay(10000); // 每10秒記錄一次,請注意不要用光儲存空間了
}
String getTimeStamp(){
String result;
Process p;
p.begin("date");
p.run();
while(p.available() > 0) {
char c = p.read();
if(c != '\n')
result += c;
}
return result;
}
檔案內容大概如下:
Sun Apr 13 14:00:19 CST 2014, Analog Pin A0 = 150
Sun Apr 13 14:00:29 CST 2014, Analog Pin A0 = 54
Sun Apr 13 14:00:39 CST 2014, Analog Pin A0 = 54
Sun Apr 13 14:00:49 CST 2014, Analog Pin A0 = 52
...
同時只能開啟一支檔案,所以必須先關掉前一支檔案,然後才能開啟另一支檔案。
參考資料:
- Arduino官方文件,FileIO類別。
Arduino Yún:Bridge程式庫入門(Bridge類別的put與get方法)
Bridge類別算是Bridge程式庫裡其他類別的苦力,當其他類別需要在Yún的Arduino端與Linux端之間溝通時,其實都是透過Bridge類別來完成。
Bridge類別提供了put與get方法(另外還有transfer方法),可讓我們在Linux端的記憶體裡存放鍵值配對,這一篇試著玩玩看。
存放的地方是AR9331的RAM,所以若Linux端的Bridge軟體部分重置的話,東西就會消失,譬如拔插電源、重置Linux處理器、透過WiFi或Ethernet上傳草稿碼,都會造成重置Linux端的Bridge軟體;但若重置ATmega32U4並不影響。
範例程式如下,會先存放四個鍵值配對,然後讀取序列埠,根據讀到的鍵取回相對的值。
#include <Bridge.h>
void setup() {
Serial.begin(19200);
while(!Serial)
;
Serial.print("Starting Bridge...");
Bridge.begin(); // 啟動Bridge,阻斷式呼叫
Serial.println("done.");
// 存放東西,參數是鍵與值,都是一般C字串型別
Bridge.put("a", "101");
Bridge.put("b", "abcd");
Bridge.put("c", "!@#$%");
Bridge.put("d", "0.77");
}
void loop() {
if(Serial.available()){
char c = Serial.read();
char k[2];
k[0] = c;
k[1] = '\0';
char buf[10];
// 參數是鍵、存放值的緩衝區,緩衝區的大小
Bridge.get(k, buf, 10); // 傳入鍵、取回值
Serial.println(buf);
}
}
執行結果如下,輸入a、b、c、d可取回相對應的鍵,並輸出序列埠監控視窗。
參考資料:
Arduino Yún:Bridge程式庫入門(使用Process執行命令列模式下的指令)
之前已經初步介紹過Yún的Bridge程式庫,這一篇要使用Process執行命令列模式的指令,並且試著以非同步方式執行。
至於Linux命令列模式下有哪些指令,不在本篇討論範圍。
首先以同步方式執行,意思是說,指令需完全執行完畢,才會回傳。程式碼如下:
#include <Process.h>
void setup() {
Bridge.begin();
Serial.begin(19200);
while(!Serial)
;
}
void loop() {
Process p; // 使用Process類別來執行指令
// 呼叫runShellCommand方法執行Shell指令
p.runShellCommand("iw dev wlan0 station dump");
// runShellCommand屬於阻斷式呼叫,
// 等到該方法回傳時,指令已執行完畢
while(p.available() > 0){ // 把結果送往序列埠監控視窗
char c = p.read();
Serial.print(c);
}
Serial.flush();
delay(5000); // 每5秒執行一次
}
執行結果大概如下:
Station 5d:05:a1:5a:e2:78 (on wlan0)
inactive time: 11600 ms
rx bytes: 5684813
rx packets: 55634
tx bytes: 90102
tx packets: 804
tx retries: 269
tx failed: 0
signal: -35 dBm
signal avg: -34 dBm
tx bitrate: 72.2 MBit/s MCS 7 short GI
rx bitrate: 1.0 MBit/s
authorized: yes
authenticated: yes
preamble: long
WMM/WME: yes
MFP: no
TDLS peer: no
其中signal代表的就是RSSI值。
你也可以把
p.runShellCommand("iw dev wlan0 station dump");
換成
p.runShellCommand("/usr/bin/pretty-wifi-info.lua");
可得到類似底下的輸出:
Current WiFi configuration
SSID: N10U
Mode: Client
Signal: 100%
Encryption method: WPA2 PSK (CCMP)
Interface name: wlan0
Active for: 49 minutes
IP address: 192.168.1.235/255.255.255.0
MAC address: 90:A2:DA:F1:06:36
RX/TX: 303/84 KBs
接下來試試非同步的呼叫方式,
#include <Process.h>
void setup() {
Bridge.begin();
Serial.begin(19200);
while(!Serial)
;
}
Process p; // 注意,Process物件改為全域變數
void loop() {
if(Serial.available()){ // 在序列埠監控視窗隨便輸入些什麼東西
while(Serial.read() != -1) // 就可以觸發執行指令
;
// 呼叫非同步方法runShellCommandAsynchronously
p.runShellCommandAsynchronously("iw dev wlan0 station dump");
}
while(p.available() > 0){
char c = p.read();
Serial.print(c);
}
Serial.flush();
}
其實runShellCommandAsynchronously的底層實作會去呼叫runAsynchronously,只不過再指定shell與參數-c罷了,兩者用法差不多。而run跟runShellCommand最後都是去呼叫非同步的方法,但是再加上delay,一直等到執行結束,然後再回傳。
使用非同步方法時,有不少地方需要注意,譬如底下的程式碼,看起來似乎沒錯,但執行時卻什麼東西也沒有,沒有輸出。
#include <Process.h>
void setup() {
Bridge.begin();
Serial.begin(19200);
while(!Serial)
;
}
void loop() {
Process p; // 注意
p.begin("uptime"); // 注意
if(Serial.available()){
while(Serial.read() != -1)
;
p.runAsynchronously();
}
while(p.available() > 0){
char c = p.read();
Serial.print(c);
}
Serial.flush();
}
原因在於使用非同步方法時,若Process物件位於函式內、屬於區域變數,那麼當指令尚未完成就會消失不見了;而且若每次進入loop就呼叫begin("uptime"),begin不僅會設定新的指令,也會呼叫close結束上次的指令,所以上次指令尚未執行完成就被結束了。
呼,慢慢嘗試吧。
Arduino Yún:Bridge程式庫入門(Console與Process)
Yún除了有一顆微控制器ATmega32U4(跟Leonardo相同),還有一顆Atheros AR9331,運行Linux發行套件Linino(以OpenWRT為基礎修改而成),這顆晶片連接有線網路(Ethernet)介面、無線網路(WiFi)介面、板子上的USB A埠(主方)與micro SD記憶卡插槽。
當我們撰寫ATmega32U4的草稿碼時,可透過Bridge程式庫來跟Atheros AR9331的Linino溝通,使用各種功能。請看官方網站提供的架構示意圖。
接下來就嘗試一下Console與Process,底下的程式碼大部分都是從Arduino官方網站與軟體開發環境提供的範例修改而來。
首先是Console,顧名思義就是類似主控台、終端機之類的功能,跟以前的序列埠很像,但現在可經由WiFi無線登入。
底下這支程式會從Console接收資料,若收到字元H就點亮板子上內建的LED,若收到字元L就熄滅。
#include <Console.h>
#define LED_PIN 13
void setup() {
Bridge.begin(); // 啟動Bridge,其他類別都需要它
Console.begin(); // 初始化Console
while (!Console) // 等待開啟Console
;
if(Console.connected()){
Console.println("Console is connected");
}
Console.println("type H or L to turn pin 13 on or off");
pinMode(LED_PIN, OUTPUT);
}
void loop() {
if(Console.available() > 0){
char b = Console.read();
Console.println(b);
if(b == 'H'){
digitalWrite(LED_PIN, HIGH);
}
else if(b == 'L'){
digitalWrite(LED_PIN, LOW);
}
}
}
Console類別用起來就跟Serial差不多。然後可從選單「工具-連接埠」選擇「Arduino at xxx.xxx.xxx.xx (Arduino Yún)」,此時開啟序列埠監控視窗的話,便可連接Yún的Console,畫面如下。
$ ssh root@arduino.local
root@arduino.local's password:
...省略...
登入後下指令連接Console,如下:
root@Arduino:~# telnet localhost 6571
Console is connected
type H or L to turn pin 13 on or off
然後就可以輸入H或L控制LED亮滅。
然後是Process,可要求執行某程式或Linux指令,底下程式碼會執行uptime指令,得知系統開機後已經過多少時間,然後執行curl,取回以ASCII畫出來的Arduino logo。
#include <Process.h>
void setup() {
Bridge.begin();
Serial.begin(19200);
while(!Serial)
;
run_uptime();
run_curl();
}
void loop() {
}
void run_curl() {
Process p;
p.begin("curl"); // 指令Linux指令
p.addParameter("http://arduino.cc/asciilogo.txt"); // 加上參數
p.run(); // 執行,這是阻斷式方法,執行結束後才會回傳
while(p.available() > 0){ // 將指令執行結果送往序列埠監控視窗
char c = p.read();
Serial.print(c);
}
Serial.flush();
}
void run_uptime(){
Process p;
p.begin("uptime");
p.run();
while(p.available() > 0){
char c = p.read();
Serial.print(c);
}
Serial.flush();
}
其結果如下圖:
參考資料:
- Arduino官方文件的ArduinoYun與Bridge Library for Arduino Yún。
- Arduino官方部落格Hands on: the Arduino Yún’s Bridge。
Arduino Yún:更新Linino映像檔
之前已成功設定Yún並可無線燒錄,不過繼續想要嘗試Arduino官方網站的一些範例程式時,都會停在Bridge.begin()這一行程式,找不出原因,後來更新Linino映像檔才解決。
這篇記錄一下更新步驟,注意,更新後原先建立的檔案與組態設定都會消失不見。
首先下載Arduino官方網站釋出的Linino映像檔,下載網址在此,我下載的是「Linino 1.0 Upgrade Image」,檔名是YunSysupgradeImage_v1.zip,解壓縮後得到openwrt-ar71xx-generic-linino-16M-squashfs-sysupgrade.bin。
把Linino映像檔放進一張microSD卡裡,插入Yún的記憶卡插槽,然後通電啟動。從瀏覽器登入Yún後,它會自動偵測記憶卡裡有無更新映像檔,並且顯示如下的畫面。
另外也可從SSH登入,手動下指令更新。
首先透過SSH安全連線登入。(可把arduino.local換成你的Yún的IP位址。)
$ ssh root@arduino.local
第一次SSH連線時,會詢問你認不認識該主機,請輸入yes、按Enter。
The authenticity of host 'arduino.local (arduino.local)' can't be established.
RSA key fingerprint is 61:47:86:dd:12:4f:9e:33:91:71:36:fd:e2:8e:3d:5f.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'arduino.local' (RSA) to the list of known hosts.
然後輸入設定的密碼,預設是「arduino」。
root@arduino.local's password:
BusyBox v1.19.4 (2013-08-07 16:16:02 CEST) built-in shell (ash)
Enter 'help' for a list of built-in commands.
___ ___ ___ ___
/\__\ ___ /\__\ ___ /\__\ /\ \
/:/ / /\ \ /::| | /\ \ /::| | /::\ \
/:/ / \:\ \ /:|:| | \:\ \ /:|:| | /:/\:\ \
/:/ / /::\__\ /:/|:| |__ /::\__\ /:/|:| |__ /:/ \:\ \
/:/__/ __/:/\/__/ /:/ |:| /\__\ __/:/\/__/ /:/ |:| /\__\ /:/__/ \:\__\
\:\ \ /\/:/ / \/__|:|/:/ / /\/:/ / \/__|:|/:/ / \:\ \ /:/ /
\:\ \ \::/__/ |:/:/ / \::/__/ |:/:/ / \:\ /:/ /
\:\ \ \:\__\ |::/ / \:\__\ |::/ / \:\/:/ /
\:\__\ \/__/ /:/ / \/__/ /:/ / \::/ /
\/__/ \/__/ \/__/ \/__/
_______ ________ __
| |.-----.-----.-----.| | | |.----.| |_
| - || _ | -__| || | | || _|| _|
|_______|| __|_____|__|__||________||__| |____|
|__| W I R E L E S S F R E E D O M
root@Arduino:~#
哇,登入成功囉。先檢查一下Linino映像檔。
root@ArduinoYun:~# ls /mnt/sda1
openwrt-ar71xx-generic-linino-16M-squashfs-sysupgrade.bin
然後下指令進行更新。
root@ArduinoYun:~# run-sysupgrade /mnt/sda1/openwrt-ar71xx-generic-linino-16M-squashfs
-sysupgrade.bin
kill: you need to specify whom to kill
kill: you need to specify whom to kill
Sending TERM to remaining processes ... uhttpd dbus-daemon dnsmasq avahi-daemon thd ntpd uSDaemon sleep syslogd klogd hotplug2 procd netifd ubusd
Sending KILL to remaining processes ...
Switching to ramdisk...
Performing system upgrade...
Unlocking firmware ...
Writing from
Upgrade completed
Rebooting system...
等待約3分鐘後即可完成更新。
參考資料:
- Arduino官方網站的Upgrading the Linino image on the Yún 。
- Arduino官方網站的Arduino Yún、Guide to the Arduino Yún、YÚN Package Manager。
2014/04/12
Raspberry Pi情報彙整(24)
我將網路上看到的、感興趣的、跟Raspberry Pi相關的資訊收集如下。如果您發現任何新奇驚人的新聞或專案,還請留言告知。
Learning Python with Raspberry Pi,新書,從頭開始介紹,包括變數與迴圈、3D圖學、遊戲、網路、控制硬體、還有Minecraft、等等;作者是 Linux Voice的Ben Everard與Alex Bradbury,Alex也是Raspbian的維護者。
標籤: Raspberry Pi