在我們前幾章運用到的程式練習中,都是digitalWrite/digitalRead這兩個指令去控制I/O。例如LED燈只有亮和關2個狀態(State),按鈕也是只有按下和放手2個狀態State;而我們稱這類只有2種state的訊號為數位/數字/Digital訊號。
如果要做更進階的應用,就要提到另一類的訊號,就是模擬/類比/Analog訊號了。
先說說可以做到Analog輸入的零件。相對只有兩種State的按鈕或開關,Joystick或旋轉式的開關就可以做到階段式的輸入訊號
而一般的輸出零件則可以透過控制供電的大小做到類似類比的效果,例如LED可以有光暗的變化,馬達可以有速度的變化,喇叭可以有音量的變化等。
PWM是一種技術,能讓Arduino在只能輸出5V或0V digital訊號轉換成5V~0V之間的analog訊號(例如2.5V,具體的表演即是可以讓LED的亮度有變化)
但並不是每一位Arduino腳位都能輸出PWM的訊號,只有腳位旁邊有代表Analog的"~"符號的腳位才能輸出
不同型號的PWM腳位未必一樣,以UNO為例3,5,6,9,10,11是PWM腳、以Leonardo為例是3,5,6,9,10,11,13(見右圖)
PWM的原理簡單理解就是把輸出的電壓訊號在極短的時間內不斷重覆放電和斷電,我們稱放電工作的部份(凸起的部份)為Pulse width(脈衝寬度),通過modulate(調節)這個寬度,就會改變了輸出的電壓值,所以這就是PWM,Pulse width modulation(調節脈衝寬度)的意思。
比如最大的電壓是5V,放電工作的時間比例佔一個循環的是50%(打開下圖),那麼得出的最終電壓就會是5V的50%、即2.5V;
放電工作(凸起的部份,也就是Pulse width)的時間比例我們稱為duty cycle,單位是%。
如果最大的電壓是5V,放電工作的時間比例 duty cycle是10%(下圖二),那麼得出的最終電壓就會是5V的10%、即0.5V;
由上方的原理我們可以得出PWM的3個參數之間的關係為:
analog output voltage(V) = maximum voltage (V) x duty cycle(%)
透過移項我們可以得出另外二條公式(打開下圖)
What is the relation between duty cycle, maximum voltage and analog output voltage?
What is the output voltage when the duty cycle and maximum voltage are 66% and 9V respectively?
What is the maximum voltage when the duty cycle and output voltage are 40% and 6V?
What is the duty cycle when the output voltage and maximum voltage are 2.65V and 7.5V respectively?
Vout (V) = VMax (V) x duty cycle (%)
Vout = VMax * duty cycle = 9V*66% = 5.94V
VMax = Vout / duty cycle = 6V/40% = 15V
duty cycle = Vout / VMax *100% = 35.33% (cor. to 2 d.p.)
今次的練習題目:讓綠色LED的亮度在最亮(255)和最暗(0)之間來回變化
今次會使用PWM的輸出指令analogWrite(/*Output pin*/,/*0~255*/); 和digitalWrite()相似,可以供給Output腳位0~255的電位(0V~5V)。
打開File➡Examples➡01.Basics➡Fade找到呼吸燈的程式
在刪除所有註解後的式如下圖。
其中if內的條件(brightness<=0 || brightness>=255)的意思是乎合brightness<=0 或者brightness>=255的條件都會執行下面fadeAmount = -fadeAmount;的指令。
整個程式的結果是LED會由亮度0開始 0, 5, 10, 15, 20...250, 255然後255, 250, 245, 240...5, 0不斷循環。
在模擬器內試試同一段程式,分別用9號腳和8號腳作輸出腳, 看看能否做到呼吸燈的效果
雖然上面提到了不少的零件可以實現analog的訊號輸出/輸入,可是在Arduino控制板上並不是每隻pin都可以做到analog的輸入/輸出,像analog output(PWM)就只有3,5,6,9,10,11...等腳才能實行。
在開始其他編程練習前我們要先了解一下Arduino板上關於digital及analog訊號的配置,順便也了解一下其供電的方法
Arduino的供電主要有3個方法:
分別是:
a. The power jack (7-12V, >250mA)
b. The USB connection (5V, 500mA)
c. The VIN (+) and GND (-) pin (7-12V, >250mA)
常用的0~13pin及A0~A5pin,它們都是可以做到基本的digital I/O(input/output),可是只有A0~A5的pin可以接收到analog類的訊號,所以它們的編號都是以代表analog的A字命名。
練習完analog輸出後我們接着就做Analog的輸入訊號練習。可是我們的擴充板在連接可變電阻(Variable resistor)或光敏電阻(Photoresistot/LDR)時皆需要做一點硬件連接。見下圖左方黃綠色的部份、右方是其放大的畫面:
中間黃色的橫行由左到右分別是A1,A2,A3及A0腳位,在沒有額外零件的情況下是什麼都沒連接。如果要連上可變電阻,就需要用Jumper這個零件(或者電綫)把相對的腳位連上上行藍行的腳位,如下圖:
今次的練習題目是讀取可變電阻的A1可變電阻的輸入訊號。先參接上圖左方的方法加入jumper完成硬件連接;
int analogpin_1=A1;
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.print("The input signal is: ");
Serial.println(analogRead(analogpin_1));
}
上載後可以試試調節可變電阻改變電阻值,並觀察數值的變化
連接A2腳的讀取來源為光敏電阻的A2。參考2a右上方的方法加入jumper完成硬件連接;基本把2a的程式稍改就可:
int analogpin_1=A2; //把輸入改為A2
....
上載後可以試試用手遮蔽光敏電阻改變電阻值,並觀察數值的變化
之後的練習題目是讀取可變電阻的A1可變電阻的輸入訊號,並以其數值改變LED的亮度
可變電阻(Analog input)的數值範圍是0~1023、而LED的亮度(Analog output/PWM)的數值範圍是0~255,不能直接用Input值控制Output
故我們要用一個指令map把analog input的值縮少。
map的功能就像是把A比例的東西縮放成B比例,然後找回新比例中某個立置的值,
語法為 map(/*reference*/,/*Original Min*/, /*Original Max*/,/*New Min*//*New Max*/);
所以我們可以把analoginput的值(範圍是0~1023)用map轉換成analogoutput可承受的範圍(0~255)。
brightness_1=map(analoginput_1,0,1023,0,255); //把analoginput的值由0~1023等比變成0~255
如果要求出map運算的精確值,可以參考書中的公式(按下圖)
試完成下方的練習
讀取可變電阻的A1可變電阻的輸入訊號,並以其數值改變LED的亮度
完整的指令如下:
int analogpin_1=A1;
int led = 9; // the PWM pin the LED is attached to
int analoginput_1,brightness_1; // how bright the LED is
void setup() {
pinMode(led, OUTPUT);
Serial.begin(9600);
}
void loop() {
analoginput_1=analogRead(analogpin_1);
brightness_1=map(analoginput_1,_,____,_,___); //把analoginput的值由0~1023等比變成0~255
analogWrite(led, brightness_1);
Serial.print("The input signal is: ");
Serial.print(analoginput_1);
Serial.print(" The output signal is: ");
Serial.println(brightness_1);
}
上載後可以試試調節可變電阻改變電阻值,並觀察LED亮度的變化。
以3a為基礎,以3個可變電阻分別控制LED燈的RGB亮度。
以3a為基礎,以3個光敏電阻分別控制LED燈的RGB亮度。當光敏電阻調到其中一個方向的盡頭時,LED要完全熄滅、當光敏電阻調到反方向的盡頭時,LED要最亮。
*提示:要完成這部份,你必須要知道光敏電阻輸入值的上下限。可以參考2b的練習,顯示出光敏電阻的數值範圍
有需要的情況要用constrain(x,上限,下限)指令切走多餘的數值
經過這個章節後,你基本已經可以完成不同類型的輸入訊號和輸出訊號互動了。要注意的是,比起PWM的原理你更需要知道其用途,以及不記得哪個腳位可以做analog I/O時知道去哪裏找到答案。下一章節我們會教學把程式簡化整理的技巧:Function