還記得在之前的章節中,我們要分別令3個按鈕控制3顆LED燈嗎? 該指令如下:
int buttonpin_R=2,buttonpin_G=3,buttonpin_B=6;
int LEDpin_R=11,LEDpin_G=9,LEDpin_B=10;
int State_R, State_G, State_B;
void setup(){
pinMode(LEDpin_R,OUTPUT);
pinMode(LEDpin_G,OUTPUT);
pinMode(LEDpin_B,OUTPUT);
}
void loop(){
State_R=digitalRead(buttonpin_R);
if (State_R == 1 ){
digitalWrite(LEDpin_R,0);}
else {
digitalWrite(LEDpin_R,1);}
State_G=digitalRead(buttonpin_G);
if (State_G == 1){
digitalWrite(LEDpin_G,0);}
else {
digitalWrite(LEDpin_G,1);}
State_B=digitalRead(buttonpin_B);
if (State_B == 1 ){
digitalWrite(LEDpin_B,0);}
else {
digitalWrite(LEDpin_B,1);}
}
有沒有發現loop內的指令其實是由3段一樣的指令組成,不過是輸入和輸出的腳位不同而己。這個時候我們可以設定function把程式簡化一下。所謂的function其實和數學上的function概念一樣,例如我們可以設定
f(x)=4x2+3x+2
Arduino的function格式則是像如下:
void ButtonControl(int x){//當x值...,就...}
也可以加入2個或以上的參數:
void ButtonControl(int x,int y){//把x值...,把y值...}
function內的參數部份(上面的int x,int y)是所謂的局部變數, 則是只有在function的大括號{ }內才有用,在主程式避免使用同名的變數。
另外局部變數也應該對應其功能來命名,以方便往後查閱:
void ButtonControl(int button, int led){//由button的腳位訊號控制led腳位的燈光}
以下為3個按鈕控制3顆LED燈的完整例子:
int buttonpin_R=2,buttonpin_G=3,buttonpin_B=6;
int LEDpin_R=11,LEDpin_G=9,LEDpin_B=10;
int State;//用1個function判斷按鈕狀態,所以只需要1個變數
void setup(){
pinMode(LEDpin_R,OUTPUT);
pinMode(LEDpin_G,OUTPUT);
pinMode(LEDpin_B,OUTPUT);
}
void ButtonControl(int button, int led){ //這個function需要輸入2個參數:button及led
State=digitalRead(button); //讀取代表Input的腳位的button,記錄在State
if (State == 1){
digitalWrite(led,0);} //因State的結果決定代表Output腳位的LED輸出0或1
else {
digitalWrite(led,1);}
}
void loop(){
ButtonControl(buttonpin_R, LEDpin_R); //決定輸入的腳位及輸出的腳位
ButtonControl(buttonpin_G, LEDpin_G);
ButtonControl(buttonpin_B, LEDpin_B);
}
當然function也可以單純把程式簡化,不包含變數,例如上面例子setup內的指令我們可以把三句pinMode(...)"打包"成一個function。注意沒有參數也要保留function後的()
int buttonpin_R=2,buttonpin_G=3,buttonpin_B=6;
int LEDpin_R=11,LEDpin_G=9,LEDpin_B=10;
int State;
void setup(){
setLED_output(); //這個function沒有參數但也要打上()
}
void loop(){
ButtonControl(buttonpin_R, LEDpin_R);
ButtonControl(buttonpin_G, LEDpin_G);
ButtonControl(buttonpin_B, LEDpin_B);
}
//function
void setLED_output(){ //沒有參數但也要打上()
pinMode(LEDpin_R,OUTPUT);
pinMode(LEDpin_G,OUTPUT);
pinMode(LEDpin_B,OUTPUT);
}
void ButtonControl(int button, int led){
State=digitalRead(button);
if (State == 1 ){
digitalWrite(led,0);}
else {
digitalWrite(led,1);}
}
由上面的例子為基礎,試用R按鈕控制G燈,G按鈕控制B燈,B按鈕控制R燈
int buttonpin_R=2,buttonpin_G=3,buttonpin_B=6;
int LEDpin_R=11,LEDpin_G=9,LEDpin_B=10;
int State_R, State_G, State_B;
void setLED_output(){
pinMode(LEDpin_R,OUTPUT);
pinMode(LEDpin_G,OUTPUT);
pinMode(LEDpin_B,OUTPUT);
}
void ButtonControl(int button, int led){ //這個function需要輸入2個參數:button及led
State=digitalRead(button); //讀取代表Input的腳位的button,記錄在State
if (State == 1){
digitalWrite(led,0);} //因State的結果決定代表Output腳位的LED輸出0或1
else {
digitalWrite(led,1);}
}
void setup(){
setLED_output();
}
void loop(){
ButtonControl(buttonpin_R, ________); //button Red control which LED?
ButtonControl(buttonpin_G, ________);
ButtonControl(buttonpin_B, ________);
}
把1a的function部份移到新的分頁吧!
一個程式內可以包含多個function,也可以用function包覆着另一個function。 function內不可包含setup()及loop()、以及命名限制和變數一樣。
當function的數量變多,有時難免會反而找不到loop內的主要內容...像上面的例子,如果把function的部份分開放置到另一個位置,程式看起來就會更加簡潔了。通常我們會把function的部份放到另一個分頁,有點像舞台的"後台"。在IDE的按下Ctrl+Shift+N,或者在IDE右上方按下三角形的箭頭後按下New Tab:
之後會出現一個輸入方塊讓你命名新分頁的名稱。分頁命名沒有限制,但因為可以有多個分頁,最好以其功能命名方便往後查閱。這裏就命名為Function:
最後把主頁的function部份剪下( Ctrl+X ),然後到分頁把的function部份貼上( Ctrl+V )
上面介紹到的function基本都是單向的,function內部處理完的變數或者內容不會影響到主程式的其他內容(除了全域變數)
如果想在執行function後回饋一個值回到主程式,可以加入return指令以回饋一個值。注意用這種方法的話Function的開頭就不能用void,而要用你需要回饋值的種類,如int、float等。
例如參見下面的例子,我們設定一個計算圓形面積的function CircleArea()、其功能是執行後回饋一個圓面積的值:
float x=3; //這裏x的類型如果只需整數也可以設為"int x=3;"
float ans;
void setup() {
Serial.begin(9600);
}
float CircleArea(int r){ //由於要return一個值(area)、所以不是用void開頭、而是代表數值的int/float/byte...
float area = PI * r * r; //開頭的類型"float"是由這行的變數area類型決定
return area;
}
void loop() {
ans = CircleArea(x);
Serial.println(ans); //最後顯示的結果會是PI*3*3=9.42
}
而Arduino也有內置一些用於計算的數學function,可以參面下表: