Professional Documents
Culture Documents
EXP2 Arduino
EXP2 Arduino
Ardduino的使
使用
目的
認識Arduinno微處理器
器,並能藉由
由程式設計
計透過微處理
理器偵測按
按鈕狀態及控
控制LED及
及壓電揚聲
器。
原理
Arduinno的基本介介紹請參閱附附錄"Arduinno的介紹"講講義;程式式運作原理請請參閱附錄錄。
發光二極體 體(LED)簡介介
LED 類似於
於燈泡,當 當有電流通過過時,LED 就
就會產生亮
亮光。不同於
於燈泡的是,LED 元件
件有方向性,
電流方向必 必須由正極 極流向負極,
,LED 才能
能發光。如果
果電流的方方向不對的話
話,LED 將
將無法正常發
發
光。圖 1 是 LED 外型
型及電路符號號的示意圖圖。
負
負端這一側是
是平的
圖 1 LED 零件
件圖(上)和電路
路符號(下)
判斷
斷極性的方法 法有二,一是長長腳為正;另一一是塑膠封裝
裝平面側為負。
元件
件符號三角形 形的方向是指電電流由正流向 向負的方向。
1
普物實驗講義
義
電阻是是必須的。請請記得使用限限流電阻,
如果沒有它它,會造成太 太多的電流流 流過線路。
將會造成許許多零件的損 損壞,包括 UNO、電源 源 圖 5 UNO 控制
制 LED 線路
供應裝置甚甚至是 LED 等都可能會 會燒毀。
b.鍵入
入 LedOnOff
ff.ino 程式碼
碼至 Arduinno Editor。並
並設定好檔
檔名另存新檔
檔。
2
普物實驗講義
義
//LedOnOff.inno
//開啟及關閉 閉 LED 燈,亮 亮 0.5s;暗 0.5s。
//組別、組員 員姓名
//雙斜線為註 註解指令,編譯 譯程式會自動 動忽略雙斜線之 之後的文字, ,主要目的是幫
是幫忙理解程式 式碼。
void setup(){ //本函數只執 執行一次
Serial.begiin(9600); //設定鮑率 96600
pinMode(113,OUTPUT); //設定接腳 113 為輸出模式 式
}//程式碼最好 好根據不同的 的程式區塊有不 不同的縮排,可以讓程式碼 碼容易閱讀
void loop(){
Serial.printtln("The LED
D connected to Pin13 is blinkking!");
//Serial.printlln()函數是把雙 雙引號內的字 字串輸出到序列 列埠監控視窗 窗
digitalWritte(13,HIGH);
//digitalWritee(接腳名,輸 輸出狀態)指令是 是設定某輸出 出接腳的輸出狀 狀態,其中 H
HIGH 為輸出
出高電壓(5V)
delay(500));//delay(數字))指令是指暫停 停指定的時間 間,其中數字的 的單位為毫秒
秒(ms)
digitalWritte(13,LOW);///接腳 13 輸出 出低電壓(0V)
delay(500));
} //loopp 函數執行結束 束會重新執行 行
c.重新
新連接你的 U
UNO 的電源 源、執行程程式;點選工 工具列序列埠 列埠監控視窗 窗,檢查是否否出現設定
定
字串
串。
d.執行 的 for 迴圈__程式前面鍵
行特定次數的 鍵入"int couunter;"並把 vvoid loop()函
函數內的程
程式改用下列
列
程式
式取代。
Serial.println("The LED coonnected to Pinn13 is blinkinng!");
//程式由counnter=0開始執行 行,每執行一 一次,counter就 就+1,直到ccounter=10就停
停止執行,離 離開for迴圈,共
共執行10次
for(counterr=0;counter<110;counter=counter+1){ ///可用counter+++取代counterr=counter+1
digitalW
Write(13,HIGH H);
delay(5000);
digitalW
Write(13,LOW));
delay(5000);
Serial.prrintln(counter,,DEC);
}
Serial.printtln("All done!");
for(;;);//參數
數沒有任何設
設定,因此執
執行到此函數時
時,程式就會
會卡在這裡,可
可當作停止執
執行的指令。
e.檢查 十次後停止?完成後請助
查是否亮暗十 助教檢查。
二、按鈕測 測試電路
5V
a.拔出出 USB 連接線 線(即切斷 P13
UNO
O 的電源)後 後接妥電路圖 圖
6。 P11
b.鍵入入 PushbuttonnControlLedd 圖6
程式碼碼至 Arduiino Editor。 和 LED 電路
按鈕迴路和 路
並設定定好檔名另 另存新檔。
// PushbuttonnControlLed.inno
// Check pushhbutton state 10
1 times per seecond and blinnk LED when pressed.
//組別、組員 員姓名
const byte SWW = 11; //定 定義常數 SW 代 代表 11
const byte LEED = 13; //定 定義接腳 13 為 led 控制端
void setup() {
Serial.begiin(9600);//定義義鮑率
pinMode(S SW, INPUT);///設定接腳 111 為輸入模式
pinMode(L LED,OUTPUT T);//設定接腳 腳 13 為輸出模 模式
3
普物實驗講義
義
}
void loop() {
boolean vaal = digitalReaad(SW); //將 S
SW 接腳狀態讀
讀入後存入資 布林變數的 val
資料型態為布
if(val){ //val 是否為 HIGH
Serial.prrintln("SW=1"");//是若輸出"SW=1"字串,並閃爍 LED
D
digitalW
Write(LED,HIG GH);
delay(500);
digitalW
Write(LED,LOW W);
delay(500);}
else{//否若 若輸出"SW=0""字串
Serial.prrintln("SW=0"");
delay(1000);
}
}//本程式設定 定為當按下按 按鈕時,LED 將以 10Hz 的頻率閃爍。
的
c.重新
新連接你的 U
UNO 的電源
源、執行程程式;點選工具
具列序列埠
埠監控視窗,檢查是否
否出現設定字
字
串及
及測試結果
果是否符合預 預期?完成後
後請助教檢查查。
三、揚聲器 器電路 P8
a.拔出出 USB 連接線 線(即切斷 UNO 的電源 源)
後接妥 妥電路圖 77。
b.鍵入入 ActionTonnes.ino 程式
式碼至 Arduino 圖7
Editoor。並設定好 好檔名另存 存新檔。 壓
壓電揚聲器回
回路的電路圖
//ActionTonees.ino
//Send a tone to the piezo speaker
s using tthe tone() com
mmand.
//組別、組員 員姓名
const byte SPP_PIN=8;
int duration;
int frequencyy;
//設定函數------------------------------
void setup() {{//接腳輸出模 模式的設定
pinMode(S SP_PIN,OUTP PUT);
Serial.begiin(9600);
}
//主程式--------------------------------
void loop() {
Serial.printtln("Alarm...");
delay(10000);
tone(SP_PIN, 1500); dellay(500); noToone(SP_PIN);; delay(500);///響1.5kHz聲音
音0.5秒,停止
止0.5秒
tone(SP_PIN, 1500); dellay(500); noToone(SP_PIN);; delay(500);
tone(SP_PIN, 1500); dellay(500); noToone(SP_PIN);; delay(500);
tone(SP_PIN, 1500); dellay(500); noToone(SP_PIN);; delay(500);
Serial.printtln("Robot repplay...");
delay(100));
tone(SP_PIN, 2800); delay(100); noTone(SP_P
PIN);
tone(SP_PIN, 2400); delay(200); noTone(SP_P
PIN);
tone(SP_PIN, 4200); delay(140); noTone(SP_P
PIN);
tone(SP_PIN, 2000); delay(30); noTone(SP_P
PIN);
delay(500));
Serial.printtln("Hyperspaace...");
delay(100));
for(duratioon=15;durationn>=1;durationn--){//duration--代表duration=duration-1
for(frequuency=2000;fr
frequency<=25500;frequencyy=frequency+220){
4
普物實驗講義
義
tone(S
SP_PIN,frequeency);
delay((duration);
noTonne(SP_PIN);
}
}
Serial.printtln("Done");
for(;;);
}
c.重新
新連接你的 U
UNO 的電源
源、執行程程式;點選工具
具列序列埠
埠監控視窗,檢查是否
否出現設定字
字
串及
及測試結果
果是否符合預 預期?完成後
後請助教檢查查。
四、設計__反應計時電 電路
假如你已經 經是遊戲公 公司的嵌入系系統工程師,市場部門要 要你藉由電電路來測試玩
玩家使用遊
遊戲把手的反
反
應時間,你你的下一個工 工作是開發發一個反應計 計時電路。這個實驗程程序中,你要
要建立並且
且測試你的解
解
決方法,是 是這一個設 設定程式並解解決問題的例 例子。
a.拔出
出 USB 連接線
線(即切斷 UNO 的電源
源)後接妥電
電路圖。
5V
P8
P11
圖8
反應
應計時電路
b.鍵入
入 ReactionTimer.ino 程
程式碼至 Ardduino Editorr。並設定好
好檔名另存
存新檔。
// ReactionTimer.ino
// 反應計時電 電路
//組別、組員 員姓名
//宣告變數名 名稱------------------------------------
int timeCounter=0;
int counter=00;
boolean val=00;
const byte Buutton = 11;
const byte SP P_PIN =8;
const byte LE ED =13;
//-----------------------------------
void setup() {
Serial.begiin(9600);
pinMode(B Button,INPUT T);
pinMode(S SP_PIN,OUTP PUT);
pinMode(L LED,OUTPUT T);
Serial.printtln("When thee ringtone is ovver, press the button");//顯示
示提示字串
Serial.printtln("go as fastt as you can."));
}
//-----------------------------------
void loop() {
tone(SP_PIN, 1500); dellay(500); noToone(SP_PIN);;delay(500);
tone(SP_PIN, 1500); dellay(500); noToone(SP_PIN);;delay(500);
tone(SP_PIN, 1500); dellay(500); noToone(SP_PIN);;delay(500);
tone(SP_PIN, 3000); dellay(1000); noT Tone(SP_PIN);
do{ //計時 時函數
delay(1));
timeCouunter++;
val=digiitalRead(Buttoon);
}while(!vaal);//按下按鈕 鈕,脫離迴圈
5
普物實驗講義
digitalWrite(LED,HIGH);//LED亮,計時結束
delay(1000); //Delay 1 second.
6
普物實驗講義
選擇變數的名字有許多規則 話,這個方法是很有用的,再加上
移除//雙斜線會比起重新輸入程式
1.名字不能是Arduino已經定義的字。這些字叫做關鍵字 碼要來的簡單多了。另外若程式碼
(keyword),其實你已經接觸過一些例子如:delay、 很大超過一行以上的話,我們可以
HIGH、LOW、for和LOOP。 在第一行的前面加上"/*"而在最後
2.名字中間不能有空格。 一行的後面加上"*/",則整段都視
3.名字只能包含英文字母、數字或是底線。但它必須要 為註解。
以字母為起頭。
4.名字不能有全形字。
5.最好以變數所代表的意義來取名,可以降低閱讀及除錯的困難度,但應避免過長。
6.大小寫有別,因此led與LED視為不同變數。
設定初始
值
不同的變數形態,可以儲存不同的數字
範圍。當然,儲存的數字範圍越大,所需要
不符合 的儲存記憶體空間也越大。因此選取適當的
設定執
行條件
脫離迴圈 變數形態是很重要的。Arduino有很多不同形
態的變數。每一種可以儲存不同範圍的數
符合條件 字。除了數字之外,尚有字元及字串的變數
形態。
boolean:true or fasle 布林變數
主要程式 byte:0~255 位元組
char: 'a', 'b', 'c' 字元
int:-32768 ~ 32767 整數
unsigned int:0 ~ 65535 無號整數
設定變數 long:-2147483648 ~ 2147483647 長整數
變化量 圖 9 for()流程圖
7
普物實驗講義
Serial.println(counter,DEC);指令中的DEC是一個顯示格式,告訴電腦要用十進位的方式顯示counter變
數值在序列埠監控視窗上。
for格式語法如下所示:
for(設定變數初始值;設定執行條件;設定變數變化量){主要程式}
for()函數內有三個參數(分別以;分號隔開),第一個參數為設定變數初始值,其中變數需事先宣
告,本例中變數名稱為counter,設定為0即counter=0。第二個參數為設定執行條件,其中只要符
合條件就繼續執行for()函數,不符合就離開for()函數。本例中為counter<10,只要counter變數小
於10就執行大括弧內程式。第三個變數為設定變數變化量,只要for()函數內的程式執行完後即重
新設定變數後再依據第二個參數作判斷是否離開迴圈。本例為counter=counter+1代表每次將
counter變數內的數值取出加1後再儲存回counter,即counter變數加1的意思(可簡化為counter++)。
因此執行for(counter=0;counter<10;counter=counter+1)告訴UNO要先設定counter的值為0然後根據條件判
斷是否要執行主要程式。若符合條件將執行程式後把counter的值加1,接著再檢查counter的值有
沒有小於10。如果沒有,它會再重複程序。當counter最後到達10時,程式會自動跳出for()迴圈,
並且繼續執行之後的指令。流程圖如圖9所示。
for(counter=0;counter<10;counter=counter+1){
digitalWrite(13,HIGH);
delay(500);
digitalWrite(13,LOW);
delay(500);
Serial.println(counter,DEC);
}
在for()函數之後的指令為
Serial.println("All done!");
for(;;);//停止執行
這個指令只是要表示程式已經完成十次的for()迴圈。最後它會停在for(;;);指令上。若無此行指令
程式將會重新重頭執行。
最後我們來說明for(;;);指令,當我們了解了for()函數的語法後,就知道這個指令內並無第二個參
數,即設定執行的條件,因此一旦進入函數內後,就會無條件執行迴圈,不會再跳脫迴圈,因此
可以暫時充當停止程式的指令。
PushbuttonControlLed.ino如何運作
在說明之前,我們先討論 if()指令的語法。當程式中有需要因應
不同的條件,執行不同程式時,就可以用 if-else 敘述處理,當 圖 10 if()流程圖
判斷條件成立時,則執行 if 後程式 A,判斷條件不成立,則執
行 else 後面程式 B。流程圖如圖 10 所示。if-else 語法如下
判斷條件
if(判斷條件)
{
程式 A; //若判斷條件成立,則執行此部份 true false
}
else
{ 程式 A 程式 B
程式 B; //若判斷條件不成立,則執行此部份
}
8
普物實驗講義
9
普物實驗講義
for(duration=15;duration>=1;duration--){//duration--代表 duration=duration-1
for(frequency=2000;frequency<=2500;frequency=frequency+20){
tone(SP_PIN,frequency);
delay(duration);
noTone(SP_PIN);
}
}
ReactionTimer.ino 如何運作
因為程式必須追蹤下壓前所累積的時間,所以宣告一個 timeCounter 變數。另外也宣告一個布林
變數 val 來儲存按鈕的按壓情形。最後為了提高程式碼的可讀性,同時也分定義了三個接腳名稱。
int timeCounter=0;
int counter=0;
boolean val=0;
const byte Button = 11;
const byte SP_PIN =8;
const byte LED =13;
這些字串是序列埠監控視窗給玩家的指示
Serial.println("When the ringtone is over, press the button");//顯示提示字串
Serial.println("go as fast as you can.");
程式開始執行後,首先出現幾聲音效,模擬賽車出發前的提示,提醒玩家於最後一聲結束時,必
須按下按鈕。
tone(SP_PIN, 1500); delay(500); noTone(SP_PIN);delay(500);
tone(SP_PIN, 1500); delay(500); noTone(SP_PIN);delay(500);
tone(SP_PIN, 1500); delay(500); noTone(SP_PIN);delay(500);
tone(SP_PIN, 3000); delay(1000); noTone(SP_PIN);
一旦提示音效結束,就開始計時玩家多久才按下按鍵。timeCounter 變數初始值設為 0,do_while()
函數開始重複運作,直到玩家按下按鍵(val =1)。每次運作這個迴圈,Arduino 會因為使用 delay(1);
而延遲 1ms,而它會同時將 1 加入 timeCounter 變數。
do{ //計時函數
delay(1);
timeCounter++;
val=digitalRead(Button);
}while(!val);//按下按鈕,脫離迴圈
10
普物實驗講義
while() do while()
設定 設定
迴圈 迴圈
圖 11
false 迴圈 while()及 do while()程式流程圖
判斷 離開 兩者的差別在於 while()先檢查
主體
條件 迴圈 條件再執行迴圈主體,而 do
while()則至少執行一次迴圈主
體再檢查條件。
true 改變
條件
迴圈
主體
true false
判斷 離開
改變 條件 迴圈
條件
離開 do_whil()函數之後,會繼續執行之後的程式敘述。點亮 LED,提醒玩家計時結束,延遲 1
秒後再出現提示字串。
digitalWrite(LED,HIGH);//LED 亮,計時結束
delay(1000); //Delay 1 second.
序列埠監控視窗中會展現出結果
Serial.print("\n Your time was "); //Display time measurement.
Serial.print(timeCounter,DEC);
Serial.println(" ms.\n"); //"\n"為換行指令
Serial.println("To play again, press the button down again."); //Play again instructions.
結束後,有一個 while()迴圈。迴圈內程式主體只是讀取按鈕狀態。離開迴圈的條件就是按下按
鈕。目的是就等待玩家準備重啟遊戲。一旦離開迴圈會將一些變數回復預設值,關閉 LED 及延
遲 1s 後繼續往下執行程式。
val=0; //為什麼 val 要重設為 0?
while(!val){ //等待按鈕,重啟遊戲
val = digitalRead(Button);
}
timeCounter=0;
digitalWrite(LED,LOW); delay(1000);
程式的最後一個敘述是右大括弧},它讓程式回到最開始的 void loop()敘述。
換你試試看 - 修正這個設計 ReactionTimer.ino
1.當玩家持續約 33 秒後才壓住按鈕,它的成績卻出現負的秒數。
變數 timeCounter 是以整數(int)宣告,範圍為-32768~32767。因此約 33 秒後,就超出變數設定
範圍,產生奇怪的數字。我們可以改用無號整數宣告(unsigned int),可以把範圍改為 0~65535。
這樣可以計時延長至 65 秒。這樣應該夠用了,沒有人會這樣遲鈍吧。否則就改用無號長整數(unsigned
11
普物實驗講義
long)。你可以查一下它的範圍有多大?
unsigned int timeCounter; //修正這個
除了擴大變數範圍外,另一種方式是限制最大時間。例如限制 10 秒,之後就不再計數,統一以
>10 方式呈現結果。
boolean over=0; //再宣告一個 over 變數來記錄 timeCounter 是否大於 10 的狀態。
在程式末的 timeCounter=0;之後再加上 over=0;記得每次都要先歸零,不然只有第一次正常。
在 timeCounter++;之後再加上
if(timeCounter==10000){//判斷是否計數到 10s,其中雙等號"=="是判斷是否相等的運算子
val=1; //設定將結束迴圈
over=1;//記錄已超出 10 的狀態
}
將 Serial.println(timeCounter,DEC);改為
if(over){//若超出 10s 則
Serial.print(">10000");//直接呈現>10s 結果
}
else{//否則就呈現實際結果
Serial.print(timeCounter,DEC);
}
2.玩家很快地發現,第三聲時間是 1 秒,在玩過幾次之後,他們開始很會預測時間,所以成績不
再是準確的反應時間。
Arduino 有一個 random()指令,以下是如何使用 random() 指令修正程式:
a.在程式的一開始,宣告一個新的變數 value,將它初始值設定在 0。
int timeCounter=0;
int value=0; //加入這個
12