最近在學(xué)校里開(kāi)設(shè)了一門(mén)Arduino課程,因?yàn)槭歉咭粚W(xué)生,所以幾乎沒(méi)有什么基礎(chǔ),不說(shuō)編程,甚至基本的電路知識(shí)也沒(méi)有。所以基本整個(gè)學(xué)期就是讓他們接 觸一下Arduino,玩一下Arduino控制Led燈。為了方便學(xué)生學(xué)習(xí),我打算將課程里的東西寫(xiě)成博客,其實(shí)這也算最基礎(chǔ)的Arduino教程了 吧......
首先如何安裝Arduino驅(qū)動(dòng),如何打開(kāi)軟件等等都不談了。先來(lái)說(shuō)寫(xiě)入的第一段程序。
這段程序來(lái)自與Arduino軟件例子里的Blink程序
————————————————————————————————————————————
// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int led = 13;
// the setup routine runs once when you press reset:
void setup() {
// initialize the digital pin as an output.
pinMode(led, OUTPUT);
}
// the loop routine runs over and over again forever:
void loop() {
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
————————————————————————————————————————
首先程序中的“//”后面跟的是注釋語(yǔ)言,并不會(huì)運(yùn)行。“”中間的也是注釋語(yǔ)言,不會(huì)運(yùn)行。所以上面程序其實(shí)真正運(yùn)行的只有如下:
————————————————————————————————————————————
int led = 13;
=====================
void setup() {
pinMode(led, OUTPUT);
}
========================
void loop() {
digitalWrite(led, HIGH);
delay(1000);
digitalWrite(led, LOW);
delay(1000);
}
————————————————————————————————————
首先上面程序其實(shí)可以分成三部分(已經(jīng)用========隔開(kāi))
第一部分是變量定義部分,其實(shí)就是命名一些量,比如說(shuō)
int led = 13;
意思就是命名一個(gè)量,這個(gè)量的名字叫“led”,它是一個(gè)“int”類(lèi)型的量,“int”類(lèi)型就是說(shuō)明這是一個(gè)數(shù)字,并且是整數(shù)。然后這個(gè)名叫“led”的量它等于13。
第二部分是初始化部分,“void setup() { ...........}”,大括號(hào)中間的是需要初始化的語(yǔ)句。
pinMode(led, OUTPUT);
pinMode是Arduino的內(nèi)置函數(shù),就是說(shuō)Arduino它認(rèn)得pinMode。這句程序的意思就是讓led這個(gè)量所指的接口,其實(shí)這里就是13號(hào)數(shù)字輸出口,把這個(gè)端口設(shè)為OUTPUT,就是輸出端口。
第三部分才是最重要的主要程序部分void loop() {.........},大括號(hào)中間的就是我們所要讓Arduino運(yùn)行的程序,loop的意思就是大括號(hào)中的程序不停的重復(fù)執(zhí)行,從頭執(zhí)行到尾,然后再回到頭再執(zhí)行一遍。
下面來(lái)看看上面程序執(zhí)行的是什么。
digitalWrite(led, HIGH);
這句話光看字面意思就已經(jīng)很明白了,就是“數(shù)字寫(xiě)入”,讓led(其實(shí)就是代表13號(hào)數(shù)字端口)為“HIGH”,HIGH就是會(huì)使這個(gè)端口的電平達(dá)到5V左右。如果我們讓一個(gè)LED的一極接在13號(hào)端口,另一極接在GND(接地端),那么當(dāng)led為HIGH時(shí),這個(gè)led燈就會(huì)發(fā)光了。
delay(1000);
這句簡(jiǎn)單,就是休息1000毫秒(等待1秒)。
再后面相信已經(jīng)不用我解釋了,這樣最后程序?qū)懭階rduino后,執(zhí)行的結(jié)果就是一端接13號(hào)端口,一端接gnd的led燈會(huì)亮一秒然后再滅一秒然后再.......周而復(fù)始。
看到這里,相信你已經(jīng)可以用程序來(lái)控制一盞led燈的發(fā)光了,而且可以自己設(shè)定讓它如何發(fā)光,試試看吧.....
----------------------
上次講了一下Arduino自帶例程序里的blink程序?qū)W習(xí)了下面幾個(gè)程序語(yǔ)句:
pinMode(led, OUTPUT);
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH) {
digitalWrite(ledPin, HIGH);
}
else {
digitalWrite(ledPin, LOW);
}
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH) {
digitalWrite(ledPin, HIGH);
}
else {
digitalWrite(ledPin, LOW);
}
pinMode(ledPin, OUTPUT); //將ledPin端口定義為輸出
pinMode(buttonPin, INPUT); //將buttonPin端口定義為輸入
buttonState = digitalRead(buttonPin); //buttonState變量值等于buttonPin端的輸入
if (buttonState == HIGH) { //如果buttonState等于HIGH,即2端口接5V
digitalWrite(ledPin, HIGH); //使ledPin端口為5V
}
else { // 否則
digitalWrite(ledPin, LOW); //使ledPin端口為接地。
} }
pinMode(ledPin1, OUTPUT); //將ledPin1端口定義為輸出
pinMode(ledPin2, OUTPUT); //將ledPin2端口定義為輸出
pinMode(buttonPin, INPUT); //將buttonPin端口定義為輸入
buttonState = digitalRead(buttonPin); //buttonState變量值等于buttonPin端的輸入
if (buttonState == HIGH) { //如果buttonState等于HIGH,即2端口接5V
digitalWrite(ledPin1, HIGH); //使ledPin1端口為5V
}
else { // 否則
digitalWrite(ledPin2, HIGH); //使ledPin2端口為5V
digitalWrite(ledPin1, LOW); //使ledPin1端口為接地。
} }
pinMode(ledPin, OUTPUT); //將ledPin端口定義為輸出
pinMode(buttonPin, INPUT); //將buttonPin端口定義為輸入
buttonState = digitalRead(buttonPin); //buttonState變量值等于buttonPin端的輸入
if (buttonState == HIGH) { //如果buttonState等于HIGH,即2端口接5V
digitalWrite(ledPin, HIGH); //使ledPin端口為5V,第一次亮
delay(500); //亮500毫秒
digitalWrite(ledPin, HIGH); //使ledPin端口為5V,第二次亮
delay(500); //亮500毫秒
digitalWrite(ledPin, HIGH); //使ledPin端口為5V,第三次亮
delay(500); //亮500毫秒
}
else { // 否則
digitalWrite(ledPin, LOW); //使ledPin端口為接地。
} }
pinMode(13, OUTPUT); //將13端口定義為輸出
pinMode(2, INPUT); //將2端口定義為輸入
buttonState = digitalRead(2); //buttonState變量值等于buttonPin端的輸入
if (buttonState == HIGH) { //如果buttonState等于HIGH,即2端口接5V
digitalWrite(13, HIGH); //使ledPin端口為5V
}
else { // 否則
digitalWrite(13, LOW); //使ledPin端口為接地。
} }
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
bts = digitalRead(buttonPin); //讓bts等于此刻開(kāi)關(guān)的狀態(tài)
//假如開(kāi)關(guān)此刻的狀態(tài)不等于過(guò)去的狀態(tài),并且此刻開(kāi)關(guān)為閉合時(shí),執(zhí)行下面語(yǔ)句
if (bts !=btsb&&bts==1) { //&&為并且的意思,就是bts!=btsb和bts=1兩個(gè)同時(shí)滿(mǎn)足
if(leds==0) //假如燈的狀態(tài)為滅,用leds的值來(lái)記錄燈的亮和滅
{digitalWrite(ledPin, HIGH); //將燈變亮
leds=1; } //讓記錄燈狀態(tài)的leds=1,即燈已經(jīng)亮了
else //否則,如果燈的狀態(tài)為亮
{ digitalWrite(ledPin, LOW); //將燈變滅
leds=0; } //讓記錄燈的狀態(tài)的leds=0,即燈已經(jīng)滅了
btsb=bts; //最后讓btsb燈過(guò)去的狀態(tài)值等于現(xiàn)在的狀態(tài)值,即現(xiàn)
if (bts !=btsb&&bts==0) {
btsb=bts; //只執(zhí)行燈過(guò)去狀態(tài)記錄量btsb的改變。
} }
int led = 13;
digitalWrite(led, HIGH);
delay(1000);
只有輸出,沒(méi)有輸入,今天我們來(lái)學(xué)習(xí)一下輸入。
最簡(jiǎn)單的輸入當(dāng)然是開(kāi)關(guān)信號(hào)的輸入了,自帶程序中同樣有一個(gè)例子,第二項(xiàng)里的第2個(gè)button程序:
——————————————————————————————
const int buttonPin = 2;
const int ledPin = 13;
int buttonState = 0;
void setup() {
}
void loop(){
}
————————————————————————————————————————————————
以上已經(jīng)去掉了注釋語(yǔ)句。
來(lái)看一下新出現(xiàn)的幾句程序:
pinMode(buttonPin, INPUT);
這句相信不用解釋了,就是buttonPin這個(gè)端口(也就是2號(hào)端口)為輸入端口
這句意思也簡(jiǎn)單,就是讀取buttonPin這個(gè)端口的電平,然后將結(jié)果賦值于buttonState(注意在程序中大小寫(xiě)也是要嚴(yán)格區(qū)分的),如果buttonPin這個(gè)端口電平為高,則buttonState這個(gè)值為“HIGH”(或者說(shuō)等于1),否則為“LOW”(或者說(shuō)等于0)。
if......else....語(yǔ)句為判斷語(yǔ)句,意思就是假如......否則......
翻譯一下上述語(yǔ)句就是
假如(buttonState等于"HIGH")
就使ledPin端口位于高電平
否則
就是ledPin端口位于低電平
看到這里,就就能讀懂這段程序的結(jié)果,那就是當(dāng)你按下按鈕時(shí),燈亮,斷開(kāi)按鈕,燈滅,就這么簡(jiǎn)單......
下面在來(lái)說(shuō)說(shuō)這個(gè)接線問(wèn)題
當(dāng)開(kāi)關(guān)斷開(kāi)是,2號(hào)端口與GND之間用一個(gè)電阻連接,這樣2號(hào)端口實(shí)際上是低電平,開(kāi)關(guān)閉合時(shí)2號(hào)端口接到了5V,位于高電平。
------------------------------------------------------------------------------
第三節(jié) 嘗試自己編程控制燈
一、編程是不需要每個(gè)字都自己編寫(xiě),可以通過(guò)改變現(xiàn)有程序。例如這次我們來(lái)改寫(xiě)例程中的Button程序來(lái)完成下面的任務(wù)。改寫(xiě)之前可以先將程序中原有的注釋語(yǔ)句刪除。
const int buttonPin = 2; //將2號(hào)端口命名為buttonPi ,“const”說(shuō)明這個(gè)量為之后不變
const int ledPin = 13; //將13號(hào)端口命名為ledPin
int buttonState = 0; //命名一個(gè)變量,它的初始值為0,這個(gè)量之后可以改變
void setup() {
}
void loop(){
二、 任務(wù)1,用一個(gè)開(kāi)關(guān)來(lái)控制2個(gè)Led燈,當(dāng)開(kāi)關(guān)彈起時(shí),燈1亮,當(dāng)開(kāi)關(guān)按下時(shí),燈2亮。
思考:
1、需要利用幾個(gè)端口,有哪些是輸出,哪些是輸入?
2、這段程序中的判斷語(yǔ)句,if……else……語(yǔ)句該如何寫(xiě)?
3、思考線路該如何連
4、編寫(xiě)完后寫(xiě)入Arduino,觀察運(yùn)行結(jié)果。
三、 任務(wù)2,用一個(gè)開(kāi)關(guān)來(lái)控制一個(gè)Led燈,當(dāng)開(kāi)關(guān)按下時(shí)燈會(huì)閃爍三次后熄滅。
思考:
1、需要利用幾個(gè)端口,有哪些是輸出,哪些是輸入?
2、判斷語(yǔ)句中,如果開(kāi)關(guān)按下,接下去燈的閃爍改如何編寫(xiě)。
3、編寫(xiě)完后寫(xiě)入Arduino,觀察運(yùn)行結(jié)果。
四、 任務(wù)答案:
1、任務(wù)一答案:
const int buttonPin = 2; //將2號(hào)端口命名為buttonPi ,“const”說(shuō)明這個(gè)量為之后不變
const int ledPin1 = 12; //將12號(hào)端口命名為ledPin1
const int ledPin2 = 13; //將13號(hào)端口命名為ledPin2
int buttonState = 0; //命名一個(gè)變量,它的初始值為0,這個(gè)量之后可以改變
void setup() {
}
void loop(){
digitalWrite(ledPin2, LOW); //使ledPin2端口為接地。
2、任務(wù)二答案
const int buttonPin = 2; //將2號(hào)端口命名為buttonPi ,“const”說(shuō)明這個(gè)量為之后不變
const int ledPin = 13; //將13號(hào)端口命名為ledPin
int buttonState = 0; //命名一個(gè)變量,它的初始值為0,這個(gè)量之后可以改變
void setup() {
}
void loop(){
digitalWrite(ledPin, LOW); //使ledPin端口為接地。
delay(500); //滅500毫秒
digitalWrite(ledPin, LOW); //使ledPin端口為接地。
delay(500); //滅500毫秒
digitalWrite(ledPin, LOW); //使ledPin端口為接地。
delay(500); //滅500毫秒
-------------------------------------------------------------------------------------------------------
第四節(jié) 像Arduino一樣思考
一、 像程序一樣思考
有一個(gè)輕觸開(kāi)關(guān),一個(gè)led燈,如果要實(shí)現(xiàn)按下開(kāi)關(guān)led燈亮,松開(kāi)開(kāi)關(guān)led燈滅,該如何實(shí)現(xiàn)?
思考:
1、輸入和輸出器材分別是什么,如何將這些器材的動(dòng)作變成電的信號(hào)?
2、逐步思考整個(gè)過(guò)程,包括任何細(xì)節(jié)部分。
3、 該命名幾個(gè)量來(lái)記錄這些信號(hào)?
4、 該如何編寫(xiě)程序來(lái)實(shí)現(xiàn)這些功能?
解答:
輸入器材為輕觸式開(kāi)關(guān),此種開(kāi)關(guān)有兩端,當(dāng)按下時(shí)兩端連接,松開(kāi)時(shí)兩端斷開(kāi)。也就是開(kāi)關(guān)能給出兩種信號(hào),一種是斷開(kāi),一種是閉合。那么如何將斷開(kāi)與閉合兩種狀態(tài)變成相應(yīng)的電信號(hào)呢?如圖:
讓2號(hào)端口來(lái)接受這個(gè)信號(hào),當(dāng)開(kāi)關(guān)閉合時(shí),2號(hào)端口直接與5V相連,然后又通過(guò)電阻與地相連,這是2號(hào)端口上的電壓為5V。當(dāng)開(kāi)關(guān)斷開(kāi)是,2號(hào)端口只通過(guò)電阻與地相連,這時(shí)其上電壓為0V。通過(guò)這個(gè)電路就可以將開(kāi)關(guān)的開(kāi)與關(guān)信號(hào)轉(zhuǎn)變成2號(hào)端口上的0V與5V的電壓信號(hào)。(如果2號(hào)端口什么都沒(méi)接,則其上的電壓為不確定)
這樣我們就把現(xiàn)實(shí)生活中開(kāi)關(guān)的狀態(tài)轉(zhuǎn)變成了電信號(hào)。那么如何讓電信號(hào)去轉(zhuǎn)變?yōu)?span xml:lang="EN-US">led燈的亮與滅呢?其實(shí)原理也是類(lèi)似的,將led的正極(長(zhǎng)的一端),接到13號(hào)端口,負(fù)極接到GND端,當(dāng)13號(hào)端口上電壓為5V時(shí),led燈就會(huì)發(fā)光,否則就滅。這樣就完成了電信號(hào)轉(zhuǎn)變?yōu)闊艄饬僚c滅的過(guò)程。
上幾節(jié)我們已經(jīng)了解了Arduino程序的執(zhí)行過(guò)程,那就是loop(){……}內(nèi)的語(yǔ)句不停的循環(huán)執(zhí)行,如果沒(méi)有delay()語(yǔ)句的話,每執(zhí)行一遍大概在幾十微秒。所以接下去我們的思考就變成了:
每遍程序執(zhí)行時(shí),當(dāng)2號(hào)端口電壓為5V時(shí),就使13號(hào)端口電壓為5V,2號(hào)端口電壓為0V時(shí),就使13號(hào)端口電壓也為0V。那么接下去就可以進(jìn)行程序的編寫(xiě)了。
該命名幾個(gè)量呢?其實(shí)只需要一個(gè)量來(lái)記錄2號(hào)端口的值就夠了。所以語(yǔ)句可以設(shè)計(jì)成:
int buttonState = 0; //命名一個(gè)變量,它的初始值為0,這個(gè)量之后可以改變
void setup() {
}
void loop(){
觀察上述語(yǔ)句與上節(jié)課所使用的語(yǔ)句的差別?
有時(shí)候?yàn)榱耸钩绦蚋雍?jiǎn)介,修改更加方便,往往將程序中多次出現(xiàn)的值定義一個(gè)量來(lái)表示,例如:
const int ledPin = 13; //命名一個(gè)量ledPin,其值為13.
這樣接下去的程序中,就可以用ledPin來(lái)代替13了,這有什么好處呢?如果你想修改程序,讓12號(hào)端口來(lái)當(dāng)作輸出端口,如果按照未定義前,你的找到程序中所有13的地方,都修改成12,但是如果你定義了ledPin,那么只需要將“const int ledPin = 13;”改成“const int ledPin = 12;”就可以了,而不用改動(dòng)程序中的其他語(yǔ)句。
二、 任務(wù):
一個(gè)輕觸開(kāi)關(guān),一個(gè)led燈,如果要實(shí)現(xiàn)第一次按下開(kāi)關(guān)led燈亮,松開(kāi)開(kāi)關(guān)led燈不滅;第二次按下開(kāi)關(guān)led燈滅,松開(kāi)繼續(xù)滅;第三次按下開(kāi)關(guān)led燈亮,松開(kāi)繼續(xù)亮……該如何實(shí)現(xiàn)?
思考:
1、輸入量和輸出量有幾個(gè)?
2、逐步逐步思考具體的實(shí)現(xiàn)過(guò)程。
3、需要定義幾個(gè)量?
4、具體程序如何?
解答:
輸入量和輸出量與上個(gè)任務(wù)相同,下面來(lái)逐步思考整個(gè)過(guò)程:
開(kāi)始時(shí)燈是滅的,開(kāi)關(guān)沒(méi)有按下;然后按下開(kāi)關(guān),開(kāi)關(guān)的狀態(tài)從開(kāi)到關(guān),燈從滅到亮;然后斷開(kāi)開(kāi)關(guān),開(kāi)關(guān)狀態(tài)從關(guān)到開(kāi),燈的狀態(tài)不變,繼續(xù)亮;接下去再按下開(kāi)關(guān),開(kāi)關(guān)狀態(tài)沖從開(kāi)到關(guān),燈從亮到滅;最后松開(kāi)開(kāi)關(guān),開(kāi)關(guān)狀態(tài)從關(guān)到開(kāi),燈的狀態(tài)不變……
每次燈的狀態(tài)改變發(fā)生在開(kāi)關(guān)按下,即從開(kāi)到關(guān)改變瞬間。那么怎么樣解釋“改變”呢?改變的意思是事物產(chǎn)生顯著的差別。用程序的思考改變就是現(xiàn)在的狀態(tài)與過(guò)去的狀態(tài)不同,也就是說(shuō)必須要有一個(gè)量來(lái)記錄過(guò)去的狀態(tài),還有一個(gè)量來(lái)記錄現(xiàn)在的狀態(tài),注意,這里所謂的過(guò)去和現(xiàn)在都是針對(duì)某一遍程序執(zhí)行來(lái)說(shuō)的。當(dāng)記錄現(xiàn)在的量和記錄過(guò)去的量不同時(shí),即是發(fā)生改變的時(shí)刻。
當(dāng)然,開(kāi)關(guān)狀態(tài)的改變瞬間找到后,還需要關(guān)注燈的狀態(tài),因?yàn)槊看伍_(kāi)關(guān)改變的瞬間都要改變燈的狀態(tài),如果亮就要變滅,如果滅就要變量,這樣就必須還得定義一個(gè)量來(lái)記錄燈的狀態(tài)。
下面我們將上述過(guò)程像程序一樣來(lái)進(jìn)行思考:
先命名一個(gè)變量bts來(lái)記錄開(kāi)關(guān)現(xiàn)在的狀態(tài),當(dāng)開(kāi)關(guān)閉合時(shí),bts=1;當(dāng)開(kāi)關(guān)斷開(kāi)是,bts=0;然后再命名一個(gè)變量btsb來(lái)記錄開(kāi)關(guān)過(guò)去的狀態(tài)。然后再命名一個(gè)變量leds來(lái)記錄燈的狀態(tài),如果leds=1就是燈亮,否則就是滅。
然后開(kāi)始思考loop()程序每次循環(huán)需要執(zhí)行的語(yǔ)句。
首先btsb、bts、leds都等于0。然后當(dāng)開(kāi)關(guān)閉合一瞬間,bts就會(huì)等于1,這時(shí)bts就不等于了btsb,那么用if()語(yǔ)句來(lái)找到這個(gè)瞬間,if(bts!=btsb),就執(zhí)行改變燈亮滅的程序;然后再將此刻的開(kāi)關(guān)狀態(tài)變成過(guò)去的開(kāi)關(guān)狀態(tài),也就是btsb=bts;這樣下一遍執(zhí)行時(shí)開(kāi)關(guān)狀態(tài)就應(yīng)該是現(xiàn)在的狀態(tài)。但是開(kāi)關(guān)斷開(kāi)的一瞬間其實(shí)也會(huì)出現(xiàn)bts!=btsb,這時(shí)我們就不需要執(zhí)行改變燈的程序了,不過(guò)記錄開(kāi)關(guān)過(guò)去狀態(tài)的btsb還是需要改變。那么改變燈亮滅的程序該怎么寫(xiě)呢?其實(shí)很簡(jiǎn)單,那就是如果leds=0;就把燈變亮,然后再使leds=1,因?yàn)橄卤閳?zhí)行時(shí)燈的狀態(tài)其實(shí)已經(jīng)是亮了。如果leds=1;就把燈變滅,然后再使leds=0;下面是具體的程序:
int buttonPin = 2;
int ledPin = 12;
int bts = 0;
int btsb=0;
int leds=0;
void setup() {
}
void loop(){
} //在馬上就要變成過(guò)去了。
//假如開(kāi)關(guān)此刻的狀態(tài)不等于過(guò)去的狀態(tài),并且此刻開(kāi)關(guān)為斷開(kāi)時(shí),執(zhí)行下面語(yǔ)句