Arduino練習:以開關切換LED明滅狀態 - 葉難

文章推薦指數: 80 %
投票人數:10人

電路圖(Fritzing格式)與程式原始碼,可在此下載。

讀取開關的狀態: 電路圖如下: 從Arduino板子上的5V腳位、GND腳位,接線到 ... skiptomain| skiptosidebar 2012/02/15 Arduino練習:以開關切換LED明滅狀態 之前已經把Arduino的硬體與軟體安裝設定好、閃爍LED,然後寫程式透過序列埠輸出訊息到電腦上,這一篇是關於讀取開關(按鈕)的狀態,並以之切換LED的明滅。

電路圖(Fritzing格式)與程式原始碼,可在此下載。

讀取開關的狀態: 電路圖如下: 從Arduino板子上的5V腳位、GND腳位,接線到麵包板上。

瞬時型開關(momentaryswitch)的右上腳接到Arduino板子的腳位2,我們將以這個腳位讀取開關的狀態,開關的左下腳連接5V,開關的右下腳連接10kohm電阻後接地。

當開關處於平常狀態時,右上腳與右下腳是接在一起的,但左右兩邊沒有連接,此時讀取開關的狀態,會讀到LOW低電壓。

按下開關時,左右兩邊會接在一起,就會讀到HIGH高電壓。

程式碼如下: voidsetup(){  Serial.begin(115200);  pinMode(2,INPUT); } voidloop(){  intswitchStatus=digitalRead(2);  Serial.println(switchStatus); } 首先在setup()裡,設定序列埠傳輸速度,然後以pinMode()設定腳位2的模式,這裡設為INPUT模式,以讀取開關的狀態。

(後面將把另一個腳位設為OUTPUT模式,藉以控制LED的明滅。

) 然後在loop()裡,以digitalRead()讀取腳位2的狀態,會讀到LOW或HIGH,代表開關的狀態。

並輸出到序列埠。

開啟Tools-SerialMonitor可看到執行結果,開關平常狀態為0(LOW),按下後為1(HIGH),因為這是個瞬時型開關,放開手後會回到平常狀態。

在ArduinoUno板子上,有14個數位腳位(digitalpin),標示著0、1、2、3、一直到13,這些腳位可以用pinMode()設定為INPUT模式或OUTPUT模式,然後可以用digitalRead()讀取電壓狀態LOW或HIGH,可用digitalWrite()函式設定電壓LOW或HIGH。

使用數位腳位進行讀取時,有一點要注意,以上面這個例子來說,如果沒有加上10kohm電阻,那麼,當開關處於平常狀態,此時若讀取腳位2的話,或讀到環境雜訊(亂數,一下子是HIGH,一下子是LOW)。

你可以把電阻拿掉,看看結果。

當你看到LED亂閃時,可以檢查看看電路、開關、電阻是不是鬆了。

好,到這裡已經可以讀取開關的狀態了,接下來讓我們以之控制LED的明滅。

以開關控制LED明滅: 加裝一個LED,長腳插在13腳位,短腳插在GND,其餘跟之前一樣。

程式碼如下: voidsetup(){  Serial.begin(115200);  pinMode(2,INPUT);  pinMode(13,OUTPUT); } voidloop(){  intswitchStatus=digitalRead(2);  digitalWrite(13,switchStatus);  Serial.println(switchStatus); } 以pinMode()將腳位13設為OUTPUT模式,然後,讀取到開關狀態後,以digitalWrite()更新LED的明滅。

平常時,LED滅掉,按下開關才會亮起來,但放開手後LED又會滅掉。

以開關切換LED明滅狀態: 讓我們繼續修改,我希望按一下開關可點亮LED,手放開後保持著明亮狀態,然後再按一下開關,LED才會滅掉,以此類推。

程式碼如下: staticintledStatus; voidsetup(){  Serial.begin(115200);  pinMode(2,INPUT);  pinMode(13,OUTPUT);    ledStatus=LOW;  digitalWrite(13,ledStatus); } voidloop(){  intswitchStatus=digitalRead(2);  if(switchStatus==HIGH){    ledStatus=ledStatus==HIGH?LOW:HIGH;    digitalWrite(13,ledStatus);  }    Serial.println(ledStatus); } 以全域靜態變數ledStatus記錄LED的明滅狀態。

在loop()裡,若發現按下開關(switchStatus==HIGH),就切換LED的明滅。

聽起來很簡單,寫起來很直覺,可惜,實際動起來後,會很奇怪。

點按開關後,有時LED會亮、有時不亮,很奇怪。

解決bounce: 這是因為,開關有所謂的bounce問題,我們人類按一下開關,感覺是切換一次,可是在微觀的電子元件裡,可能會造成好幾次的開、關狀態變換,而且,對人類來說,按一下開關不過是一瞬間的事情,但是這段時間裡,loop函式不知道已經被執行多少次了,也就是說,已經讀取好幾次腳位2的值。

用底下程式碼可以更清楚問題所在。

staticintledStatus; staticintcount=0; voidsetup(){  Serial.begin(115200);  pinMode(2,INPUT);  pinMode(13,OUTPUT);    ledStatus=LOW;  digitalWrite(13,ledStatus); } voidloop(){  intswitchStatus=digitalRead(2);  if(switchStatus==HIGH){    ledStatus=ledStatus==HIGH?LOW:HIGH;    digitalWrite(13,ledStatus);        count++;  }    Serial.println(ledStatus);  Serial.println(count); } 你會發現,按一下開關,count不只會往上加一,可能會好幾十、幾百。

那麼要怎麼解決bounce問題呢?那就要多寫一些程式碼了。

staticintledStatus; staticunsignedlonglastDebounceTime; #defineDEBOUNCE_DELAY200 voidsetup(){  Serial.begin(115200);  pinMode(2,INPUT);  pinMode(13,OUTPUT);    ledStatus=LOW;  digitalWrite(13,ledStatus); } voidupdateLed(){  unsignedlongcurrentTime=millis();  if((currentTime-lastDebounceTime)>DEBOUNCE_DELAY){    lastDebounceTime=currentTime;       ledStatus=ledStatus==HIGH?LOW:HIGH;    digitalWrite(13,ledStatus);    Serial.println(ledStatus);  } } voidloop(){  intswitchStatus=digitalRead(2);    if(switchStatus==HIGH){    updateLed();  } } 以全域靜態變數ledStatus記錄LED的明滅狀態。

每當執行loop()時,若腳位2處於HIGH狀態(開關被按下),就執行updateLed()函式。

若腳位2處於LOW狀態,就不作事(LED狀態不變)。

在updateLed()裡,首先以Arduino內建函式millis()取得時間放在currentTime變數裡,這是Arduino板子開始執行程式後所經過的時間,單位為千分之一秒,回傳的型別是個unsignedlong,所以最多大約是50天,超過後就會溢位回到0開始算。

全域靜態變數lastDebounceTime代表的是,上次切換LED狀態的時間。

將currentTime目前時間,減去lastDebounceTime後,若大於DEBOUNCE_DELAY的話,代表距離上次切換LED狀態,已經經過一段夠久的時間了,所以繼續往下執行,先把currentTime存到lastDebounceTime(因為我們將要切換LED狀態了,把時間記錄下來),然後切換LED狀態(亮變滅、滅變亮)。

哇,成功啦,按一下開關,LED亮起,再按一下,LED滅掉,好耶。

如果你的情況仍不完美的話,請試試調整DEBOUNCE_DELAY的值,當我用50或100時,仍無法避免bounce,調到200才ok。

你可以繼續往上調,但是,這個數值代表在那一段時間內,都無法切換LED狀態,譬如假設改成3000(三秒)的話,按下開關點亮LED後,這時怎麼按開關都沒反應,要經過三秒後,按下開關才能滅掉LED。

利用別人寫好的程式庫解決bounce: 好累喔,用開關切換LED,怎麼這麼累啊,還好,已經有人把解決bounce的程式寫好了,我們把程式庫拿來用即可。

有套BouncelibraryforArduino,下載Bounce.zip,將解壓縮後的目錄,放到Arduino的Sketchbook目錄的子目錄libraries下。

先以File-Preferences,查出Sketchbook目錄的路徑所在,底下若無libraries這個子目錄,請自行建立,然後把Bounce.zip解壓縮後的整個目錄放進去。

2014.03.01更新:原網址已經變成新版Bounce2,所以請到GitHubjustjoheinz/Bounce下載這篇文章所使用的Bounce程式庫。

(Windows的Sketchbook目錄大概會位於C:\DocumentsandSettings\MyDocuments\Arduino,若是Mac,位於家目錄下的Documents/Arduino/,若是Linux,則是家目錄下的sketchbook目錄。

) 然後重新啟動Arduino軟體開發環境。

要使用這套程式庫,請選Sketch-ImportLibrary...-Bounce,匯入標頭檔#include"Bounce.h"。

(如果在Sketch-ImportLibrary...底下沒看到Bounce,代表你目錄放錯位置了。

) 改寫後的程式如下: #include Bouncebouncer=Bounce(2,50); staticintledStatus=LOW; voidsetup(){  Serial.begin(115200);  pinMode(2,INPUT);  pinMode(13,OUTPUT); } voidloop(){  if(bouncer.update()==true&&bouncer.read()==HIGH){    ledStatus=ledStatus==HIGH?LOW:HIGH;    digitalWrite(13,ledStatus);  } } 首先建立Bounce物件,第一個參數是腳位,第二個參數是延遲時間。

然後,以update()更新腳位的狀態,若回傳true,代表腳位的狀態有變(從HIGH到LOW,或從LOW到HIGH)。

然後,以read()讀取更新後的腳位狀態。

在程式進行判斷,若腳位狀態有變(bouncer.update()==true),並且,腳位狀態為高電壓(bouncer.read()==HIGH),那麼就切換LED明滅。

成功啦。

以下為2012/08/25新增內容。

行為:開關處於平常狀態時,LED滅掉;手指按著開關時,LED亮起;但放開手指後LED就立刻滅掉,另外,按著開關超過5秒的話,LED也會滅掉。

修改後的程式碼如下: #include Bouncebouncer=Bounce(2,50); staticintledStatus=LOW; voidsetup(){  Serial.begin(115200);  pinMode(2,INPUT);  pinMode(13,OUTPUT);  digitalWrite(13,ledStatus); } voidloop(){  bouncer.update();  if(bouncer.read()==HIGH){    ledStatus=bouncer.duration()>=5000?LOW:HIGH;  }  else{    ledStatus=LOW;  }  digitalWrite(13,ledStatus); } 每次進入loop時,就呼叫bouncer.update()更新開關讀取狀態,若開關狀態為HIGH(代表按下開關),繼續呼叫bouncer.duration()做判斷,此函式回傳的是該開關處於該狀態多長時間了,單位為千分之一秒,若超過5秒,就滅掉LED,若未足5秒,就點亮LED;若開關狀態為LOW(沒有按下開關),就滅掉LED。

參考資料: Arduino官方範例,Examples>Basics>DigitalReadSerial,Examples>Digital>Button,Examples>Digital>Debounce。

Arduino官方網站關於數位腳位(digitalpin)的說明文件,函式pinMode()、digitalRead()、digitalWrite()的說明。

解決bounce的程式庫,BouncelibraryforArduino。

CooperMaa的Arduino教學文章,Lab2使用按鍵控制LED燈號。

  sciguy14教學影片,Tutorial10forArduino:InterruptsandHardwareDebouncing,以硬體RC線路搭配AVR晶片的中斷系統,解決bounce問題。

位於 20:42   標籤: Arduino 349comments: dg10125/8/1211:04你好我想請問一下開關平常狀態為0,按下後為1也就是放開手會回到平常狀態,那我想設計例如開關連續按著超過5秒它會自動回復0(LOW),要怎麼去設定開關按著的時間。

ReplyDeleteRepliesReplyyehnan25/8/1221:31todg101:我已經更新文章了,不知道有無符合你的需求?ReplyDeleteRepliesdg10126/8/1211:08太感謝了,受益良多DeleteRepliesReplyReplydg10126/8/1215:26你好不好意思我剛接觸程式,想請問您ledStatus=ledStatus==HIGH?LOW:HIGH;是什麼意思,有點不太懂ReplyDeleteRepliesReplyyehnan26/8/1216:05那一行程式的意思就等同於底下的程式:if(ledStatus==HIGH){ledStatus=LOW;}else{ledStatus=HIGH;}其作用為切換ledStatus的狀態(HIGH與LOW)。

ReplyDeleteRepliesdg10126/8/1217:23了解太謝謝你了DeleteRepliesReplyReply阿檬25/9/1223:21你好,我的Arduino也是按實開關燈才能開....http://farm9.staticflickr.com/8181/8023487010_61dbff24a5_b.jpgReplyDeleteRepliesReply阿檬25/9/1223:23程序如下//Thiscodeturnsaledon/offthroughadebouncedswitch#include//Thiscodeturnsaledon/offthroughadebouncedbutton//Buildthecircuitindicatedhere:http://arduino.cc/en/Tutorial/Button#defineBUTTON2#defineLED13//InstantiateaBounceobjectwitha5milliseconddebouncetimeBouncebouncer=Bounce(BUTTON,50);voidsetup(){pinMode(BUTTON,INPUT);pinMode(LED,OUTPUT);}voidloop(){//Updatethedebouncerbouncer.update();//Gettheupdatevalueintvalue=bouncer.read();//TurnonorofftheLEDif(value==HIGH){digitalWrite(LED,HIGH);}else{digitalWrite(LED,LOW);}}ReplyDeleteRepliesReplyUnknown30/8/1323:45想請問一下如何改成多組按鈕控制呢?ReplyDeleteRepliesyehnan30/8/1323:55請再說明清楚一點。

應該是加入多個按鈕,修改程式碼,檢查所有開關的狀態,然後根據開關狀態與需求控制LED。

DeleteRepliesReplyUnknown31/8/1300:15是的,就是以多組按鈕去控制LED明亮,不知道該如何做修改,不好意思。

DeleteRepliesReplyyehnan31/8/1300:28先把開關硬體線路接好,然後運用文章裡的Bounce這套程式庫,原本程式裡有這一行if(bouncer.update()==true&&bouncer.read()==HIGH)一樣畫葫蘆,建立多個Bounce物件,並在loop裡取得每個開關的狀態,然後根據需求,執行你想要的行為。

DeleteRepliesReplyUnknown31/8/1300:33好的,謝謝,我試試看。

DeleteRepliesReplyUnknown31/8/1301:02#includeBouncebouncer=Bounce(2,50);staticintledStatus=LOW;voidsetup(){Serial.begin(115200);pinMode(2,INPUT);pinMode(13,OUTPUT);digitalWrite(13,ledStatus);}voidloop(){bouncer.update();if(bouncer.read()==HIGH){ledStatus=bouncer.duration()>=5000?LOW:HIGH;}else{ledStatus=LOW;}digitalWrite(13,ledStatus);}Bouncebouncer=Bounce(2,50);staticintledStatus=LOW;voidsetup(){Serial.begin(115200);pinMode(3,INPUT);pinMode(12,OUTPUT);digitalWrite(12,ledStatus);}voidloop(){bouncer.update();if(bouncer.read()==HIGH){ledStatus=bouncer.duration()>=5000?LOW:HIGH;}else{ledStatus=LOW;}digitalWrite(12,ledStatus);}是這樣嗎??可是這行Bouncebouncer=Bounce(2,50);會跳錯誤該如何修正DeleteRepliesReplyReplyyehnan31/8/1308:27不是。

為什麼有兩個setup()與兩個loop()?重複定義了Bouncebouncer=Bounce(2,50);,所以有錯誤。

ReplyDeleteRepliesUnknown31/8/1311:21#include#includeBouncebouncer=Bounce(2,50);staticintledStatus=LOW;voidsetup(){Serial.begin(115200);pinMode((2,3),INPUT);pinMode((13,12),OUTPUT);digitalWrite((13,12),ledStatus);}voidloop(){bouncer.update();if(bouncer.read()==HIGH){ledStatus=bouncer.duration()>=5000?LOW:HIGH;}else{ledStatus=LOW;}digitalWrite(13,ledStatus);bouncer.update();if(bouncer.read()==HIGH){ledStatus=bouncer.duration()>=5000?LOW:HIGH;}else{ledStatus=LOW;}digitalWrite(12,ledStatus);}修改成這樣,程式能順利Verify,但是燈號一直亮著。

是哪裡還有錯誤呢?不好意思DeleteRepliesReplyyehnan31/8/1317:52這樣能順利Verify?pinMode((2,3),INPUT);語法不對吧?試試看這樣吧,我假設你的開關接線與我文章內的接法相同,平時為LOW,按下為HIGH。

兩個開關,各自獨立控制一個LED。

#includeBouncebouncer1=Bounce(2,50);Bouncebouncer2=Bounce(3,50);staticintledStatus1=LOW;staticintledStatus2=LOW;voidsetup(){Serial.begin(115200);pinMode(2,INPUT);pinMode(3,INPUT);pinMode(12,OUTPUT);pinMode(13,OUTPUT);digitalWrite(12,ledStatus1);digitalWrite(13,ledStatus2);}voidloop(){if(bouncer1.update()==true&&bouncer1.read()==HIGH){ledStatus1=ledStatus1==HIGH?LOW:HIGH;digitalWrite(12,ledStatus1);}if(bouncer2.update()==true&&bouncer2.read()==HIGH){ledStatus2=ledStatus2==HIGH?LOW:HIGH;digitalWrite(13,ledStatus2);}}DeleteRepliesReplyUnknown31/8/1318:01好的,謝謝。

我也有用另外一個語法寫出來了,多謝指導!!DeleteRepliesReplyReplyUnknown3/12/1322:47大大您好我想要寫一組可以用遙控器的不同按鈕例如12來控制不同的LED讓LED亮但是程式碼一直寫不出來可以請大大提供一些意見嗎??ReplyDeleteRepliesUnknown3/12/1322:52//顯示紅外線協定與訊號#include//引用IRRemote函式庫constintirReceiverPin=2;//紅外線接收器OUTPUT訊號接在pin2constintA=4,B=5;IRrecvirrecv(irReceiverPin);//定義IRrecv物件來接收紅外線訊號decode_resultsresults;//解碼結果將放在decode_results結構的result變數裏voidsetup(){Serial.begin(9600);//開啟Serialport,通訊速率為9600bpsirrecv.enableIRIn();//啟動紅外線解碼pinMode(irReceiverPin,INPUT);pinMode(A,OUTPUT);pinMode(B,OUTPUT);}//顯示紅外線協定種類voidshowIRProtocol(decode_results*results){Serial.print("Protocol:");//判斷紅外線協定種類switch(results->decode_type){caseNEC:Serial.print("NEC");break;caseSONY:Serial.print("SONY");break;caseRC5:Serial.print("RC5");break;caseRC6:Serial.print("RC6");break;default:Serial.print("Unknownencoding");}//把紅外線編碼印到SerialportSerial.print(",irCode:");Serial.print(results->value,HEX);//紅外線編碼Serial.print(",bits:");Serial.println(results->bits);//紅外線編碼位元數}voidloop(){if(irrecv.decode(&results)){//解碼成功,收到一組紅外線訊號showIRProtocol(&results);//顯示紅外線協定種類IRaction(results.value);irrecv.resume();}//繼續收下一組紅外線訊號if(results.value==2028877){digitalWrite(A,HIGH);}if(results.value==2027887){digitalWrite(B,HIGH);}}DeleteRepliesReplyyehnan3/12/1323:08看起來好像沒問題,2028877跟2027887是不是錯了?要加上0x?DeleteRepliesReplyUnknown4/12/1300:40但是讀取程式時IRaction(results.value);這行卻出錯請問ox是什麼??DeleteRepliesReplyyehnan4/12/1300:54IRaction是什麼?0x代表十六進位。

DeleteRepliesReplyUnknown4/12/1301:54IRaction是我參考別人的文章接收到紅外線之後的動作DeleteRepliesReplyyehnan4/12/1309:32使用Serial.print(results->value,HEX);//紅外線編碼的話,印出來的編碼是HEX十六進位。

如果IRaction(results.value);已經會根據紅外線編碼進行動作,那麼為什麼還要if(results.value==2028877){digitalWrite(A,HIGH);}if(results.value==2027887){digitalWrite(B,HIGH);}}呢?DeleteRepliesReplyyehnan4/12/1309:42>IRaction(results.value);這行卻出錯咳,我沒有原始碼,沒辦法除錯。

DeleteRepliesReplyUnknown4/12/1316:29阿我真傻中間這串//顯示紅外線協定種類voidshowIRProtocol(decode_results*results){Serial.print("Protocol:");//判斷紅外線協定種類switch(results->decode_type){caseNEC:Serial.print("NEC");break;caseSONY:Serial.print("SONY");break;caseRC5:Serial.print("RC5");break;caseRC6:Serial.print("RC6");break;default:Serial.print("Unknownencoding");}//把紅外線編碼印到SerialportSerial.print(",irCode:");Serial.print(results->value,HEX);//紅外線編碼Serial.print(",bits:");Serial.println(results->bits);//紅外線編碼位元數}貌似根本不需要...繼續測試中...DeleteRepliesReplyUnknown9/12/1322:54//顯示紅外線協定與訊號#include//引用IRRemote函式庫constintirReceiverPin=2;//紅外線接收器OUTPUT訊號接在pin2constintledPinA=4;constintledPinB=5;IRrecvirrecv(irReceiverPin);//定義IRrecv物件來接收紅外線訊號decode_resultsresults;//解碼結果將放在decode_results結構的result變數裏voidsetup(){irrecv.enableIRIn();//啟動紅外線解碼pinMode(irReceiverPin,INPUT);pinMode(ledPinA,OUTPUT);pinMode(ledPinB,OUTPUT);}voidloop(){if(irrecv.decode(&results)){//解碼成功,收到一組紅外線訊號irrecv.resume();}//繼續收下一組紅外線訊號if(results.value==0x2028877){digitalWrite(ledPinA,HIGH);}if(results.value==0x2027887){digitalWrite(ledPinB,HIGH);}else{digitalWrite(ledPinA,LOW);digitalWrite(ledPinB,LOW);}}大大您好這是我最後測試出來的程式碼LED已經可以透過遙控器來控制哪顆燈亮但是實際情況就是如果只很快地按一下遙控器(紅外線只接收到一次訊號)LED就會持續亮如果按著遙控器LED就會只閃一下然後就不亮了請問我該怎麼修改才可以1.按著遙控器LED就持續亮放開就不亮2.接收到訊號後讓LED閃爍個幾秒然後暗掉或是想請問有沒有比較好的建議DeleteRepliesReplyyehnan9/12/1323:24每家的遙控器都不一樣,可以在irrecv.decode(&results)之後,將results的value、bits、decode_type輸出到序列埠,觀察一下,譬如說,某家的遙控器,按著某按鍵的話,會先發射0x2028877(舉例),若繼續按著該鍵不放,則會繼續發射0xFFFFFFFF。

想要「1.按著遙控器LED就持續亮放開就不亮」的話,我想到的作法如下:以全域變數unsignedlongx;記錄收到的results.value,根據x點亮相對應的LED,以全域變數unsignedlongtimeNow;記錄當時的millis(),LED持續亮著,每次執行loop()時,呼叫millis(),若millis()-timeNow>300(譬如),就熄滅LED,若在那之前又收到紅外線碼,若是別的紅外線碼,熄滅先前的LED,點亮相對應的LED,並更新timeNow,若收到的是0xFFFFFFFF,代表同樣的按鍵被按著不放,持續亮起同樣的LED,更新timeNow。

上述流程應該能達到「1.按著遙控器LED就持續亮放開就不亮」的需求,但要先確定你的紅外線遙控器持續按著按鍵不放的行為。

至於「2.接收到訊號後讓LED閃爍個幾秒然後暗掉」,不能直接使用delay,那會停住整支程式。

咳咳,請您自己想一想吧,可以運用「有限狀態機finitestatemachine」的程式設計技巧。

:DDeleteRepliesReplyUnknown10/12/1321:46大大您好請問可以跟您取得連絡方式嗎?想寄影片給您DeleteRepliesReplyyehnan10/12/1321:59咳咳,您可以上傳到youtube,然後留下網址。

DeleteRepliesReplyUnknown10/12/1322:39葉大您好這是我們的程式碼這是發射端的#includeconstintbuttonPinA=4;constintbuttonPinB=5;intbuttonStateA=0;intbuttonStateB=0;IRsendirsend;//定義IRsend物件來發射紅外線訊號voidsetup(){pinMode(buttonPinA,INPUT);pinMode(buttonPinB,INPUT);}voidloop(){buttonStateA=digitalRead(buttonPinA);buttonStateB=digitalRead(buttonPinB);if(buttonStateA==HIGH){irsend.sendNEC(0x2028877,32);}if(buttonStateB==HIGH){irsend.sendNEC(0x2027887,32);}}這是接收端#include//引用IRRemote函式庫constintirReceiverPin=2;//紅外線接收器OUTPUT訊號接在pin2constintledPinA=4;constintledPinB=5;IRrecvirrecv(irReceiverPin);//定義IRrecv物件來接收紅外線訊號decode_resultsresults;//解碼結果將放在decode_results結構的result變數裏voidsetup(){irrecv.enableIRIn();//啟動紅外線解碼pinMode(irReceiverPin,INPUT);pinMode(ledPinA,OUTPUT);pinMode(ledPinB,OUTPUT);}voidloop(){if(irrecv.decode(&results)){//解碼成功,收到一組紅外線訊號irrecv.resume();}//繼續收下一組紅外線訊號if(results.value==0x2028877){digitalWrite(ledPinA,HIGH);}if(results.value==0x2027887){digitalWrite(ledPinB,HIGH);}if(results.value==0xFFFFFFF){digitalWrite(ledPinA,LOW);digitalWrite(ledPinB,LOW);}else{digitalWrite(ledPinA,LOW);digitalWrite(ledPinB,LOW);}}還有影片http://www.youtube.com/watch?v=3nvau96b73w&feature=youtu.be想請問程式碼該如何修改才可以在我們將開關撥回到中間的時候讓燈熄滅還有讓LED改成以閃爍的方式來顯示還有LED好像會不是很規律地閃爍請問這方面有什麼建議嗎?DeleteRepliesReplyyehnan10/12/1323:48我寫了一份程式,但是我並沒有建構電路,所以也不知道到底行不行,試試看吧。

傳送方http://pastebin.com/LKEJbdDH接收方http://pastebin.com/w7a1WrEV不行的話,咳咳,請自行想辦法吧。

DeleteRepliesReplyUnknown11/12/1312:49測試非常成功接下來我再試試看閃爍非常感謝您的幫忙DeleteRepliesReplyUnknown17/12/1322:05葉大不好意思想請教您if(t/DELAY_A/2==0)是什麼意思?DeleteRepliesReplyyehnan17/12/1322:10t/DELAY_A後,得到一個整數倍數,然後/2若==0,代表是偶數,若不==0,代表是奇數。

DeleteRepliesReplyUnknown17/12/1323:05嗚嗚不好意思>三顆LED輪流亮5秒這又稍微麻煩一點,必須在此狀態裡,以millis()得知時間或使用Timer程式庫,進行LED的亮滅動作。

DeleteRepliesReplyReplyGraywolf13/10/1415:04您好,想請問一下這個函式庫有判斷長按的部分媽?希望說能按一下打開,長按關閉這樣。

THXReplyDeleteRepliesyehnan13/10/1416:22沒有,需要自己寫。

想要高階一點的功能的話,可搜尋「arduinobuttonlibrary」,看看有無合用的程式庫。

DeleteRepliesReplyReplyUnknown19/10/1416:41Thiscommenthasbeenremovedbytheauthor.ReplyDeleteRepliesReplyUnknown19/10/1416:46Thiscommenthasbeenremovedbytheauthor.ReplyDeleteRepliesReplyUnknown19/10/1416:48問個問題,我結合四位數七段顯示器以及步進馬達,目的讓步進馬達執行正反轉,然後顯示器再進行計數。

執行結果OK。

但想問下,為何馬達運轉時顯示器會全暗,僅顯示千位數0。

然後馬達跑完加1後四位顯示器+1顯示時正常。

//定義腳位//參考此網址接角http://yehnan.blogspot.tw/2013/08/arduino_26.html#include#definePIN_02#definePIN_g3#definePIN_c4#definePIN_h5#definePIN_d6#definePIN_e7#definePIN_b8#definePIN_19#definePIN_210#definePIN_f11#definePIN_a12#definePIN_313//共有4個七段顯示器,分別由針腳PIN_0、PIN_1、PIN_2、PIN_3控制//七段顯示器裡有8個LED(包含小數點)#definePOS_NUM4#defineSEG_NUM8constbytepos_pins[POS_NUM]={PIN_0,PIN_1,PIN_2,PIN_3};constbyteseg_pins[SEG_NUM]={PIN_a,PIN_b,PIN_c,PIN_d,PIN_e,PIN_f,PIN_g,PIN_h};//不進馬達Stepperstepper(200,14,16,15,17);//我手上的馬達轉一圈為48步(360/7.5deg),定義11,10,9,8為輸出腳位//底下定義由七段顯示器顯示數字時所需要的資料#definettrue#defineffalseconstbooleandata[10][SEG_NUM]={{t,t,t,t,t,t,f,f},//0{f,t,t,f,f,f,f,f},//1{t,t,f,t,t,f,t,f},//2{t,t,t,t,f,f,t,f},//3{f,t,t,f,f,t,t,f},//4{t,f,t,t,f,t,t,f},//5{t,f,t,t,t,t,t,f},//6{t,t,t,f,f,f,f,f},//7{t,t,t,t,t,t,t,f},//8{t,t,t,t,f,t,t,f},//9};//一支方便的函式,以格式字串輸出到序列埠voidpf(constchar*fmt,...){chartmp[128];//maxis128charsva_listargs;va_start(args,fmt);vsnprintf(tmp,128,fmt,args);va_end(args);Serial.print(tmp);}//設定某個七段顯示器所顯示的數字,//參數pos為0~3,指出想要更新哪一個七段顯示器,//參數n為0~9,顯示數字voidsetDigit(intpos,intn){if(pos<0||315000){number++;stepper.step(1000);//正半圈delay(1000);stepper.step(-1000);//反半圈delay(1000);time_previous+=15000;pf("number=%d\n",number);}//不斷地寫入數字setNumber(number);if(number>9999)number=0;}ReplyDeleteRepliesyehnan19/10/1417:38因為這是四合一型七段顯示器,採用掃描(scan)的方式來顯示,必須不斷呼叫setNumber()更新。

當loop()內因delay(1000);而停止更新時,四合一型七段顯示器就無法正常顯示。

DeleteRepliesReplyReplyJollyRoger_K14/11/1415:31看完yehnan版主的文章,發現跟CooperMa的文章都相當棒,也都很以初學者的角度去回覆問題,台灣就是需要像你們這種熱血份子阿,^^ReplyDeleteRepliesyehnan14/11/1415:39不敢,謬讚了。

DeleteRepliesReplyReplyUnknown21/11/1412:57Thiscommenthasbeenremovedbytheauthor.ReplyDeleteRepliesReplyUnknown21/11/1415:16大大們~請問一下我這樣寫七段顯示器的程式碼幫我看一下那裡有錯誤voidsetup(){pinMode(2,OUTPUT);pinMode(3,OUTPUT);pinMode(4,OUTPUT);pinMode(5,OUTPUT);pinMode(6,OUTPUT);pinMode(7,OUTPUT);pinMode(8,OUTPUT);pinMode(9,OUTPUT);pinMode(10,OUTPUT);digitalWrite(10,0);//關閉小數點}voidloop(){//顯示數字'H'digitalWrite(2,1);digitalWrite(3,1);digitalWrite(4,1);digitalWrite(5,0);digitalWrite(6,0);digitalWrite(7,0);digitalWrite(8,1);digitalWrite(9,1);digitalWrite(10,1);delay(1000);//顯示數字'L'digitalWrite(2,1);digitalWrite(3,0);digitalWrite(4,0);digitalWrite(5,1);digitalWrite(6,0);digitalWrite(7,0);digitalWrite(8,1);digitalWrite(9,1);digitalWrite(10,0);delay(1000);//設定某個七段顯示器所顯示的數字,//參數pos為0~3,指出想要更新哪一個七段顯示器,//參數n為0~9,顯示數字voidsetDigit(intpos,intn){if(pos<0||3APP的按鈕你說的APP,是ios或android的app嗎?>但是在宣告部分不知道哪裡出問題,遲遲會跳出別的迴圈什麼?看不懂。

跳出別的迴圈?>buttonState=digitalRead('a');//讀取按鈕的狀態digitalRead('a')這個寫法正確嗎?old_buttonState==buttonState;這是比較,不是assign,應該改成old_buttonState=buttonState;吧?ReplyDeleteRepliesUnknown25/11/1411:54APP是android的APP這個程式只是一部分,前面還有一部分是搭配APP要做密碼輸入的digitalRead('a')這個寫法我不知道正不正確,我沒寫過相關的我是搭配藍芽模組連接用arduino開發平台上的monitor得知按鈕輸出結果為字元a所以才會這樣撰寫,也有上網爬過文章,都沒有類似的可以參考,所以一直不知道怎麼寫才正確那段程式我是參考以下程式去修改的以下程式則是使用13腳外接的LEDif(c=='a'){readString="";digitalWrite(13,HIGH);delay(1000);digitalWrite(13,LOW);delay(1000);break;}DeleteRepliesReplyyehnan25/11/1413:03>digitalRead('a')這個寫法我不知道正不正確呃,不知道?編譯後至少知道能不能通過編譯器吧?>得知按鈕輸出結果為字元a那麼字元a應該儲存在某變數裡吧,digitalRead是去讀取Arduino的數位腳位。

你問的問題跟給的資訊,配合不起來,無法幫你。

DeleteRepliesReplyReplyUnknown26/11/1411:39程式都可以通過翻譯器,但是在執行時APP會出現BUG想請問這段是甚麼意思?if(c=='a'){readString="";是如果c=areadString讀取所輸入字串嗎?ReplyDeleteRepliesyehnan26/11/1412:02APP出現bug?你的程式是不是分為Arduino端與Android端?if(c=='a')如果變數c的內容等同於字元'a'的話,就執行{readString="";readStrng應該是個指標,指向空字串""這些跟Arduino或Android無關,是C程式語言。

DeleteRepliesReplyUnknown26/11/1416:00程式是結合HC-06和ArduinoUNO與AndroidAPP如果這個程式的按鈕用實體按鈕來宣告會相對簡單很多但是我想結合APP如果我想要利用接收字元來做開關要怎麼撰寫比較好呢?接收aLED為常開在接收一次LED為常關DeleteRepliesReplyyehnan26/11/1416:14在所有函式外面宣告全域變數,譬如intled_status=LOW;,拿個變數去接收字元,假設變數名為c,收到字元後,if(c=='a'){led_status=!led_status;切換:LOW與HIGH}digitalWrite(LED_PIN,led_status);DeleteRepliesReplyReplyUnknown27/11/1403:56你好,我想問一下對於輸入腳位與執行的問題當我的訂digital0為輸入時,UNO的序列埠送出的數值不會隨著電位變化當我的訂digital1為輸入時,UNO的序列埠會隨著電位變化暫停運作請問可能是什麼原因,謝謝附上程式碼intx=0;voidsetup(){Serial.begin(9600);pinMode(0,INPUT);}voidloop(){x=digitalRead(0);Serial.print(x);delay(100);}ReplyDeleteRepliesyehnan27/11/1408:26UNO的序列埠是digital0RX與1TX啊,把1改成輸入,自然會影響序列埠的運作。

DeleteRepliesReplyReplyAnonymous4/12/1418:30Thiscommenthasbeenremovedbyablogadministrator.ReplyDeleteRepliesyehnan4/12/1419:23Thiscommenthasbeenremovedbytheauthor.DeleteRepliesReplyReplyAnonymous4/12/1419:14Thiscommenthasbeenremovedbyablogadministrator.ReplyDeleteRepliesyehnan4/12/1419:30Thiscommenthasbeenremovedbytheauthor.DeleteRepliesReplyReplyAnonymous4/12/1419:30Thiscommenthasbeenremovedbyablogadministrator.ReplyDeleteRepliesReplyUnknown23/12/1420:26Thiscommenthasbeenremovedbytheauthor.ReplyDeleteRepliesReplyUnknown23/12/1420:43您好~有個LED燈閃爍的問題想請教您~我打算利用wifi收到的字串來做LED燈閃爍的開關收到字串"1"LED燈就做持續明滅閃爍的動作收到字串"2"LED燈就做關閉LED燈的動作以下部分是處理的程式碼if(inData[0]=='1'){while(1){digitalWrite(LED,HIGH);delay(50);digitalWrite(LED,LOW);delay(50);}}if(inData[0]=='2'){digitalWrite(LED,LOW);}但是這樣寫我只要接收到"1"他就一直持續閃爍停不下來XD不知道葉大有沒有什麼推薦的方式可以解決這個問題呢~謝謝您~~ReplyDeleteRepliesyehnan23/12/1421:10'1'是字元,"1"是字串。

while(1){...}這是無窮迴圈。

可行作法很多,譬如voidloop(){if(inData[0]=='1'){digitalWrite(LED,HIGH);delay(50);digitalWrite(LED,LOW);delay(50);}elseif(inData[0]=='2'){digitalWrite(LED,LOW);}}另可參考Arduino練習:以開關切換LED是否閃爍http://yehnan.blogspot.tw/2014/03/arduinoled.html以及「有限狀態機」的程式技巧,拙作很多範例都有使用此技巧。

《Arduino輕鬆入門:範例分析與實作設計》http://yehnan.blogspot.tw/2014/02/arduino_21.htmlDeleteRepliesReplyUnknown24/12/1409:52感謝葉大的回覆!!我研究看看~有任何問題再請教您謝謝哦DeleteRepliesReplyUnknown6/3/1512:54您好~有個LED燈閃爍的問題想請教您~在2013/08/31葉大有撰寫一程式#includeBouncebouncer1=Bounce(2,50);Bouncebouncer2=Bounce(3,50);staticintledStatus1=LOW;staticintledStatus2=LOW;voidsetup(){pinMode(2,INPUT);pinMode(3,INPUT);pinMode(12,OUTPUT);pinMode(13,OUTPUT);digitalWrite(12,ledStatus1);digitalWrite(13,ledStatus2);}voidloop(){if(bouncer1.update()==true&&bouncer1.read()==HIGH){ledStatus1=ledStatus1==HIGH?LOW:HIGH;digitalWrite(12,ledStatus1);}if(bouncer2.update()==true&&bouncer2.read()==HIGH){ledStatus2=ledStatus2==HIGH?LOW:HIGH;digitalWrite(13,ledStatus2);}}驗證時會出現_20150305-2.ino:20:4:error:'bouncer2'wasnotdeclaredinthisscope編譯時發生錯誤葉大請幫忙看一下問題在哪謝謝DeleteRepliesReplyyehnan6/3/1513:03我重新編譯後,並無問題。

請把#include改成#include左角括號Bounce.h右角括號DeleteRepliesReplyUnknown6/3/1515:11葉大謝謝我再試試看DeleteRepliesReplyUnknown7/3/1504:21Thiscommenthasbeenremovedbytheauthor.DeleteRepliesReplyReplyBehramLiu30/3/1515:40葉大你好:我無意間發現你的示意圖是不是畫錯了,這樣開關應該是沒作用才對耶BehramReplyDeleteRepliesyehnan30/3/1515:48沒錯啊。

當開關處於平常狀態,此時讀取開關的狀態,會讀到LOW低電壓。

按下開關時,就會讀到HIGH高電壓。

DeleteRepliesReplyBehramLiu31/3/1509:52應該是最上面那張圖~你最後的實體接線圖沒錯~~DeleteRepliesReplyyehnan31/3/1509:54你確定是這一篇?電路圖跟照片都一樣啊。

DeleteRepliesReplyMarkYen13/6/1515:05二號腳位在LOW的時候,應該要加個電阻接到GND喔~不然會有雜訊,就算是沒按下開關也會收到不穩定的訊號DeleteRepliesReplyReplyUnknown10/4/1516:54你好我想問.....為什麼我不管用哪台電腦unoupload一次後之後想在upload都會....Serialport'COM'alreadyinuse.....plzhelpReplyDeleteRepliesyehnan10/4/1517:03序列埠被佔用了。

是否有其他軟體使用該序列埠?ArduinoIDE序列埠監控視窗佔據該序列埠?DeleteRepliesReplyUnknown10/4/1517:09是否有其他軟體使用該序列埠?應該不是,因為我沒有開其他軟體,除了開發環境的資料夾ArduinoIDE序列埠監控視窗佔據該序列埠?IDE序列埠監控視窗佔據該序列埠->意思是說開發環境會一直占用視窗嗎?><..deleterepliesreplyunknown10>20)digitalWrite(LED2,LOW);digitalWrite(LED2,LOW);if(cm<=20){digitalWrite(LED1,HIGH);delay(5000)digitalWrite(LED2,HIGH);}}delay(100);}ReplyDeleteRepliesyehnan18/5/1523:37你的程式碼,根本就不能編譯吧。

你說的行為,A:「我們要做的是超音波距離感測,當感測障礙距離<=20cm的時候LED亮起,持續5秒鐘若持續感測到障礙蜂鳴器響起,當障礙物消失LED與蜂鳴器關閉。

」B:「問題是感測到障礙物不管是一瞬間或者是不到五秒,會經過約五秒鐘的時間,蜂鳴器叫一聲之後與LED一起延遲熄滅。

亦或是感測障礙超過五秒後挪開障礙物,蜂鳴器與LED會延遲約五秒才關閉。

」你寫的程式碼會得到B。

你在程式碼裡放進delay(5000),光這行大概就沒辦法得到A。

DeleteRepliesReplyUnknown19/5/1501:04Thiscommenthasbeenremovedbytheauthor.DeleteRepliesReplyUnknown19/5/1501:05Thiscommenthasbeenremovedbytheauthor.DeleteRepliesReplyReplyUnknown19/5/1501:06非常感謝您的指正,事實就像您所說的。

放上delay後什麼都不對了。

想要請教您怎麼改才能得出我們想要的。

ReplyDeleteRepliesyehnan19/5/1508:21可運用有限狀態機的程式撰寫技巧,一開始進入狀態1,LED與蜂鳴器關閉,並且感測障礙物,沒有障礙物就維持狀態1,發現障礙物的話,點亮LED,進入狀態2,並且記錄進入狀態2的時間。

在狀態2時,繼續感測障礙物,若障礙物沒了,回到狀態1;若在五秒後還有障礙物,(每次都抓出目前時間、與進入狀態2的時間作比較),進入狀態3。

狀態3,LED與蜂鳴器都開啟,持續感測障礙物,若有障礙物,保持狀態3,若沒障礙物,回到狀態1。

DeleteRepliesReplyReply王志群21/5/1520:50請問一下,Arduino有辦法兩個按鈕控制一個LED燈亮滅不同秒數?假如按下按鈕1,LED亮1秒,熄滅按下按鈕2,LED亮2秒,熄滅LED是同一顆有辦法嗎?感謝ReplyDeleteRepliesyehnan21/5/1522:12有啊。

請參考其他文章http://yehnan.blogspot.tw/2012/02/arduino_21.html譬如以開關切換LED明滅狀態、以開關切換LED是否閃爍、SimonSays請你跟我這樣做等等。

DeleteRepliesReply王志群25/5/1520:44我做出來,只有一個按鈕有作用constintbuttonPin=5.7;voidsetup(){Serial.begin(9600);pinMode(9,OUTPUT);pinMode(buttonPin,INPUT);digitalWrite(buttonPin,HIGH);}voidloop(){intstatus=digitalRead(buttonPin);digitalWrite(9,status);Serial.println(status);}DeleteRepliesReplyyehnan25/5/1521:19你只有讀取一個按鈕。

intstatus=digitalRead(buttonPin);而且constintbuttonPin=5.7;這不對吧,腳位編號是整數,不是浮點數。

DeleteRepliesReply王志群26/5/1520:46是這樣嗎?constintbuttonPin=5;constintbuttonPin1=7;constintledPin=9;booleanbuttonState;voidsetup(){Serial.begin(9600);pinMode(9,OUTPUT);pinMode(5,INPUT);pinMode(7,INPUT);digitalWrite(5,HIGH);digitalWrite(7,HIGH);}voidloop(){{intstatus=digitalRead(5);digitalWrite(9,status);Serial.println(status);}{intstatus=digitalRead(7);digitalWrite(9,status);Serial.println(status);}}DeleteRepliesReplyyehnan26/5/1522:11讀取按鈕狀態後,你需要控制LED點亮的時間。

按下按鈕5,點亮LED,此期間按下兩個按鈕都沒作用,過了一秒後,熄滅LED。

按下按鈕7,點亮LED,此期間按下兩個按鈕都沒作用,過了兩秒後,熄滅LED。

DeleteRepliesReply王志群2/6/1520:34那這樣要改哪裡,研究了好幾天,還是不行DeleteRepliesReplyyehnan2/6/1520:35程式碼?DeleteRepliesReply王志群2/6/1521:30對DeleteRepliesReplyyehnan2/6/1522:08大概是這樣吧http://pastebin.com/iA2qJgdL並未真的連接電路,僅供參考。

也沒有解決開關的bounce問題,不過就需求而言,應該沒必要。

#defineBTN1_PIN5#defineBTN2_PIN7#defineLED_PIN9#defineBTN1_PERIOD1000#defineBTN2_PERIOD2000voidsetup(){Serial.begin(9600);pinMode(BTN1_PIN,INPUT);digitalWrite(BTN1_PIN,HIGH);pinMode(BTN2_PIN,INPUT);digitalWrite(BTN2_PIN,HIGH);pinMode(LED_PIN,OUTPUT);digitalWrite(LED_PIN,LOW);}typedefenum{S_start,S_btn1_pressed,S_btn2_pressed,}State;Statestate=S_start;unsignedlongt_old;voidloop(){unsignedlongt;switch(state){caseS_start:if(digitalRead(BTN1_PIN)==LOW){digitalWrite(LED_PIN,HIGH);t_old=millis();state=S_btn1_pressed;}if(digitalRead(BTN2_PIN)==LOW){digitalWrite(LED_PIN,HIGH);t_old=millis();state=S_btn2_pressed;}break;caseS_btn1_pressed:t=millis();if((t-t_old)>BTN1_PERIOD){digitalWrite(LED_PIN,LOW);state=S_start;}break;caseS_btn2_pressed:t=millis();if((t-t_old)>BTN2_PERIOD){digitalWrite(LED_PIN,LOW);state=S_start;}break;}}DeleteRepliesReply王志群2/6/1522:24謝謝,我在參考看看,有問題再發問DeleteRepliesReplyReplyUnknown26/5/1520:41請問一下能用一顆開關控制8顆LED嗎..就是11111111這樣八顆如果按一下就會亮一顆是11111110按第二下就亮成11111101用2進制的方式亮如果按7下就亮11111000這樣有辦法嗎?ReplyDeleteRepliesyehnan26/5/1522:19定義全域的整數變數,初始值是00000000。

(跟你的相反)在loop()裡,偵測開關狀態,每按一下,該變數+1。

+1後若超過8,設回0。

在loop()裡,呼叫bitRead()讀取每個位元的狀態,點亮/熄滅LEDs。

http://www.arduino.cc/en/Reference/BitReadDeleteRepliesReplyReplyUnknown29/5/1516:46我想以一個按鈕做馬達正反轉控制目前做到按著按鈕馬達正轉放開按鈕反轉而且馬達會一直運轉無法控制請問有可能以一個按鈕做到控制馬達正反轉嗎?材料有:繼電器兩顆一個按鈕一個微動開關(HIGH:LOW表示開關門)ReplyDeleteRepliesyehnan29/5/1517:07控制直流馬達正反轉,通常會使用H橋電路,例如L293D。

然後根據按鈕狀態,控制流經馬達的電流方向。

我沒用過繼電器來控制馬達。

DeleteRepliesReplyReplyAnonymous29/7/1517:54intb1=2;intb2=3;intled=8;voidsetup(){digitalWrite(led,LOW);pinMode(b1,INPUT);pinMode(b2,INPUT);pinMode(led,OUTPUT);}voidloop(){digitalRead(led);digitalRead(b1);digitalRead(b2);while(led==LOW){if(b1==HIGH){b2=true;if(b2==HIGH){digitalWrite(led,HIGH);}else{digitalWrite(led,LOW);}}else{b2=false;}}delay(20);while(led==HIGH){if(b2==HIGH){b1=true;if(b1==HIGH){digitalWrite(led,HIGH);}else{digitalWrite(led,LOW);}}else{b1=false;}}delay(20);}这个code怎样让led保持亮着ReplyDeleteRepliesyehnan29/7/1521:28不懂你的問題。

改成intled=8;voidsetup(){pinMode(led,OUTPUT);digitalWrite(led,HIGH);}voidloop(){}不就一直亮著了嗎?DeleteRepliesReplyReplyUnknown5/8/1520:07請問一下為什麼pin腳2設INPUT不用電阻連GND就會出現亂數知道結果卻不明原因希望板大講解指點一下ReplyDeleteRepliesyehnan5/8/1521:43應該不會亂數才對。

詳細的電路圖?程式碼?DeleteRepliesReplyReplyUnknown6/9/1515:33請問如果想要把音樂和開關LED做結合要怎麼改程式碼我是個初學者音樂程式碼如下intspeaker=9;chartoneName[]="CDEFGABH";unsignedintfrequency[8]={523,587,659,694,784,880,988,1046};charbeeTone[]="HHGGEFAGGAGFGFECDCCCAGAGECDCEGHBAGAGEDCDGC";bytebeeBeat[]={2,1,2,1,1,1,1,2,1,1,1,1,1,1,2,1,2,2,1,2,1,4,2,1,2,1,3,2,1,3,2,1,3,1,1,1,1,1,1,2,1,2};intbeeLen=sizeof(beeTone);unsignedlongtempo=180;inti,j;voidsetup(){}voidloop(){for(i=0;i和開關LED做結合什麼意思?我猜應該是讀取開關狀態,控制播放哪首音樂吧,那就使用digitalRead,然後根據挑選音樂播放。

不過使用playTone的話,微控制器都會被它佔住,所以在播放期間,loop都不會執行,也就無法讀取開關狀態。

DeleteRepliesReplyReplyUnknown15/9/1509:12葉大您好,有些問題想請教您以下目的是要讓舵機按下按鈕轉動及放即停按下按鍵時BT接收一個'1'放開按鍵時BT接收一個'0'但寫while(1)if...傳送1後就會卡在裡面等執行到 i≠<5時才會送出'0'沒辦法隨時跳開請問有什麼好的建議嗎?#include#include#includeintval,i=0;intang[5]={0,40,80,120,160};//intreang[5]={255,192,128,64,0};intanglength=sizeof(ang)/sizeof(ang[4]);Servomyservo;SoftwareSerialBT(0,1);voidsetup(){Serial.begin(9600);BT.begin(9600);myservo.attach(3);myservo.write(0);}voidloop(){if(Serial.available()>0){val=BT.read();while(1){if(val=='1'&&i<5){i=i+1;Serial.println(val);Serial.println(ang[i]);delay(500);}if(val=='0'){Serial.println("stop");delay(200);}}//while(1)}//ifava}//loop------------------------------------------------------------------------------改這樣寫還跳不開有什麼好方法嗎?再麻煩葉大了!!if(val=='1'&&i<5){for(i=0;i<5;i++){Serial.println(val);Serial.println(ang[i]);delay(500);if(val=='0')break;}}if(val=='0'){Serial.println("stop");delay(200);}ReplyDeleteRepliesyehnan15/9/1509:38while(1)是無窮迴圈,直到break才會跳出,但在你的程式碼裡,不會執行到break。

你既想要隨時接收BT傳來的資料,又想要控制舵機,嗯...。

我想,在loop裡隨時接收BT資料,存放在全域變數裡,在loop裡判斷該全域變數,若為'1',進入另一函式,控制舵機;不可使用delay,應使用millis來計算時間,經過一段時間就改變角度。

這樣應該行得通。

DeleteRepliesReplyUnknown15/9/1518:15葉大您好,感謝您回覆我我是想用BT傳送的資料來做i的遞增或遞減再把矩陣的值丟到myservo.write(ang[i])來讓舵機轉動不好意思我是初學者,不太懂"loop裡隨時接收BT資料,存放在全域變數裡"能再給些提示嗎?另外delay是讓我監視埠時能較輕易看到有無正常停止為什麼要使用millis來計算時間呢?不好意思,問題有點多在勞煩葉大有空時回復一下謝謝您,您辛苦了DeleteRepliesReplyyehnan15/9/1519:05使用myservo.write來轉動舵機,若使用delay在兩兩角度之間插入一段時間,當delay時,微控制器的CPU就停在那裡,什麼也不做,於是你就沒辦法即時接收BT資料,但你卻想要收到1就轉、收到0就停,互相違背。

可以去找找有無非同步式的servo程式庫,要不然就要自己寫。

用millis的目的是去掉delay,讓loop不會因delay而暫停太久。

DeleteRepliesReplyReplyUnknown23/9/1522:12請教葉大:如果我想使用兩個無段開關去控制一個電燈,按一下開,按第二下關,那程式該怎寫呢?ReplyDeleteRepliesyehnan23/9/1522:18不就是這篇介紹的內容嗎?DeleteRepliesReplyUnknown24/9/1500:11葉大:太神了…因為急用才上網找,將來一定拜讀您的大作。

謝謝了…DeleteRepliesReplyReplyTony(黃志仁)16/11/1516:17葉大師,我要讓這個按鈕能夠在2秒鐘內按2次,才控制LED亮1秒.....如何撰寫程式呢?感謝你....ReplyDeleteRepliesReplyyehnan16/11/1516:29嗯,可使用「有限狀態機」的程式技巧,請參考拙作Arduino輕鬆入門:範例分析與實作設計http://yehnan.blogspot.tw/2014/02/arduino_21.html的第3.5節介紹這個技巧,之後的3.6、6.5、7.2、8.7都有運用該技巧的範例。

ReplyDeleteRepliesReplyyehnan16/11/1516:36嗯,你的需求其實不是什麼艱難的任務,但卻很特殊,因此自己寫的話,需要花上不少力氣;我不知道是否有人已經寫好相關的程式庫了。

ReplyDeleteRepliesReplyTony(黃志仁)16/11/1517:46葉大師,光是您願意回復我這個陌生人的問題,小弟就感動萬分了.....我會好好研究的除了上述問題外,我還有一個問題請教....我有一個控制的條件如下,先進行紅外線偵測,如果成立則啟動超音波偵測;超音波偵測成立則讓蜂鳴器作用.....這個控制裡有兩個感知器,是不是沒有辦法寫在同一個程式呢?兩個loop.....下列是超音波偵測所用程式...include#defineTrip3#defineEcho2Ultrasonicultrasonic(Trip,Echo);intIN1=12;intIN2=13;voidsetup(){pinMode(IN1,OUTPUT);pinMode(IN2,OUTPUT);}voidloop(){intcmMsec;longmicrosec=ultrasonic.timing();cmMsec=ultrasonic.convert(microsec,Ultrasonic::CM);digitalWrite(IN1,LOW);digitalWrite(IN2,LOW);ReplyDeleteRepliesyehnan16/11/1517:53你程式碼沒貼完吧?同樣的,你想要的功能,可運用有限狀態機的技巧來撰寫。

大致情況如下:讓Arduino進入狀態1,偵測紅外線,若成立就進入狀態2。

狀態2,這個狀態應該有限制一段時間,在時間內偵測超音波,若沒偵測到,就回到狀態1;若有,進入狀態3。

狀態3,蜂鳴器響起。

你的描述並沒有說在何種狀況下可以脫離狀態3。

DeleteRepliesReplyTony(黃志仁)16/11/1518:06狀態3作用1秒,回到狀態1.....不好意思,剛剛沒貼完.....我等等來研究有限狀態機.....#include#defineTrip3#defineEcho2Ultrasonicultrasonic(Trip,Echo);intIN1=12;intIN2=13;voidsetup(){pinMode(IN1,OUTPUT);pinMode(IN2,OUTPUT);}voidloop(){intcmMsec;longmicrosec=ultrasonic.timing();cmMsec=ultrasonic.convert(microsec,Ultrasonic::CM);digitalWrite(IN1,LOW);digitalWrite(IN2,LOW);if(cmMsec<30){digitalWrite(IN1,HIGH);digitalWrite(IN2,LOW);delay(100);}}DeleteRepliesReplyReplyTony(黃志仁)16/11/1518:17我等等去找葉大師的書來看,ReplyDeleteRepliesReplyTony(黃志仁)19/11/1517:31葉大師,我去買了您的書...裡頭的內容非常豐富,但你3.5章裡舉的範例,小弟程度不夠,實在不懂.....「有限狀態機」的程式技巧,這些不同狀態是怎麼轉換的?有沒有更簡單的例子呢?感謝#include#defineSERIAL_BAUDRATE19200#defineLED_PIN11#defineSWITCH_PIN7#defineDEBOUNCE_DELAY50//milliseconds#defineDURATION5000//millisecondsBouncebouncer=Bounce(SWITCH_PIN,DEBOUNCE_DELAY);//定義狀態機的可能狀態typedefenum{S_OFF,S_OFF_NO_PRESS,S_ON,S_ON_PRESS}State;Statestate=S_OFF;voidupdateLed(){if(state==S_OFF||state==S_OFF_NO_PRESS){digitalWrite(LED_PIN,LOW);}elseif(state==S_ON||state==S_ON_PRESS){digitalWrite(LED_PIN,HIGH);}else{Serial.print("Error:inwrongstate");Serial.print(state);}}voidsetup(){Serial.begin(SERIAL_BAUDRATE);pinMode(LED_PIN,OUTPUT);updateLed();}unsignedlongtime_previous;voidloop(){bouncer.update();booleanswitch_status=bouncer.read();//以switch述句根據狀態作相對應的動作switch(state){caseS_OFF:if(switch_status==LOW){time_previous=millis();state=S_OFF_NO_PRESS;}break;caseS_OFF_NO_PRESS:if(switch_status==LOW){unsignedlongtime_current=millis();if(time_current-time_previous>=DURATION){state=S_ON;}}else{state=S_OFF;}break;caseS_ON:if(switch_status==HIGH){time_previous=millis();state=S_ON_PRESS;}break;caseS_ON_PRESS:if(switch_status==HIGH){unsignedlongtime_current=millis();if(time_current-time_previous>=DURATION){state=S_OFF;}}else{state=S_ON;}break;}//前面更新狀態state後,接下來只要根據state更新LED即可updateLed();}ReplyDeleteRepliesReplyTony(黃志仁)19/11/1517:39我現在可以1.讓紅外線偵測到物體啟動超音波偵測,2.超音波偵測到物體啟動蜂鳴器分開可以,但我沒有辦法在同一個程式裡頭讓這兩個同時存在....ReplyDeleteRepliesyehnan19/11/1517:57嗯,現在回頭看,該範例的確稍不適合作為狀態機的第一個範例。

我把你想要的功能,大概框架寫出來了,但沒測試過,請自行斟酌採用。

http://pastebin.com/eD1YReqq程式裡有很多空白處,須自行填寫。

DeleteRepliesReplyReplyTony(黃志仁)19/11/1517:56這是紅外線作用控制超音波的程式intIRin=7;intledPin=11;intIRinStatus;voidsetup(){pinMode(ledPin,OUTPUT);pinMode(IRin,INPUT);}voidloop(){IRinStatus=digitalRead(IRin);if(IRinStatus==HIGH){digitalWrite(ledPin,HIGH);delay(2000);}else{digitalWrite(ledPin,LOW);}}ReplyDeleteRepliesReplyTony(黃志仁)19/11/1517:58這是我目前測試超音波作用的程式#include#defineTrip3#defineEcho2Ultrasonicultrasonic(Trip,Echo);intIN1=8;intIN2=9;intIN3=10;voidsetup(){pinMode(IN1,OUTPUT);pinMode(IN2,OUTPUT);pinMode(IN3,OUTPUT);}voidloop(){intcmMsec;longmicrosec=ultrasonic.timing();cmMsec=ultrasonic.convert(microsec,Ultrasonic::CM);digitalWrite(IN1,LOW);digitalWrite(IN2,LOW);digitalWrite(IN3,LOW);if(cmMsec<80andcmMsec>50){digitalWrite(IN1,HIGH);digitalWrite(IN2,LOW);digitalWrite(IN3,LOW);delay(100);}elseif(cmMsec<50andcmMsec>30){digitalWrite(IN1,HIGH);digitalWrite(IN2,HIGH);digitalWrite(IN3,LOW);delay(100);}elseif(cmMsec<30){digitalWrite(IN1,HIGH);digitalWrite(IN2,HIGH);digitalWrite(IN3,HIGH);delay(100);}else{digitalWrite(IN1,LOW);digitalWrite(IN2,LOW);digitalWrite(IN3,LOW);delay(100);}}ReplyDeleteRepliesReplyyehnan19/11/1517:59請看我上面的留言。

ReplyDeleteRepliesReplyTony(黃志仁)19/11/1518:03我去研就看看ReplyDeleteRepliesReplyTony(黃志仁)19/11/1518:07葉大師,謝謝~~~~我去研究了ReplyDeleteRepliesReplyTony(黃志仁)19/11/1518:09葉大師,我還得加入一個按鈕能夠在2秒鐘內按2次,才控制LED亮1秒.....能寫入這個程式嗎ReplyDeleteRepliesReplyTony(黃志仁)19/11/1519:15葉大師,我按照您的指導,成功了......我先自己研究如何加入一個按鈕能夠在2秒鐘內按2次,才控制LED亮1秒.....有疑問再請教您萬分感謝ReplyDeleteRepliesReplyTony(黃志仁)20/11/1508:55葉大師,程式如下,開始大約一分鐘狀態之間的轉換就會不正常有方法解決嗎#include#defineTrip3#defineEcho2Ultrasonicultrasonic(Trip,Echo);intALARM=8;intIRin=7;intIRtest=9;intULTRASONICtest=10;intIRinStatus;typedefenum{S_IR,S_ULTRASONIC,S_ALARM,}State;Statestate=S_IR;voidsetup(){pinMode(IRin,INPUT);pinMode(IRtest,OUTPUT);pinMode(ULTRASONICtest,OUTPUT);pinMode(ALARM,OUTPUT);}unsignedlongtime_old;voidloop(){switch(state){caseS_IR:{//偵測紅外線IRinStatus=digitalRead(IRin);digitalWrite(IRtest,HIGH);digitalWrite(ULTRASONICtest,LOW);digitalWrite(ALARM,LOW);if(IRinStatus==HIGH){//若偵測到,就進入狀態S_ULTRASONICstate=S_ULTRASONIC;time_old=millis();//記錄進入該狀態的起始時間}//若沒偵測到,就停在狀態S_IR,繼續偵測}break;caseS_ULTRASONIC:{//偵測超音波intcmMsec;longmicrosec=ultrasonic.timing();cmMsec=ultrasonic.convert(microsec,Ultrasonic::CM);digitalWrite(ALARM,LOW);digitalWrite(IRtest,LOW);digitalWrite(ULTRASONICtest,HIGH);if(cmMsec<30){//若偵測到,就進入狀態S_ALARMstate=S_ALARM;time_old=millis();//記錄進入該狀態的起始時間}else{//若沒偵測到,而且已經停在此狀態超過5秒,就回到狀態S_IRunsignedintt=millis();if(t-time_old>=3000){state=S_IR;}}}break;caseS_ALARM:{//蜂鳴器發聲digitalWrite(ALARM,HIGH);digitalWrite(IRtest,LOW);unsignedintt=millis();if(t-time_old>=500){//若已經停在此狀態超過3秒,就回到狀態S_IRstate=S_IR;}}break;}}ReplyDeleteRepliesReplyTony(黃志仁)20/11/1509:18每次大約1分鐘就會不正常ReplyDeleteRepliesReplyTony(黃志仁)20/11/1509:42老師,我在程式裡放了三個輸出,對應狀態接上LED燈,以瞭解狀態是否依照需求轉換,pinMode(IRtest,OUTPUT);pinMode(ULTRASONICtest,OUTPUT);pinMode(ALARM,OUTPUT);前一分鐘5秒都正常,(時間固定,跟次數無關)之後會常亮紅外線LED不滅,靠近紅外線偵測,應該要到超音波偵測,此時應該要滅紅外線LED,亮超音波LED,但是紅外線LED不滅,超音波LED極微弱亮,此時靠近超音波偵測,ALARM燈也是作用,但亮度不正常ReplyDeleteRepliesyehnan20/11/1510:03嗯,寫錯了。

把兩處unsignedintt改成unsignedlongtDeleteRepliesReplyReplyTony(黃志仁)20/11/1511:00好,謝謝老師,我來改ReplyDeleteRepliesReplyTony(黃志仁)20/11/1511:13改好了,作用持續正常.....ReplyDeleteRepliesReplyTony(黃志仁)20/11/1511:21葉老師,在目前模式之下,我如何再加入一個按鈕,當"在2秒鐘內按2次"(或是長按3秒),那個容易寫擇其一,能將前述作用取消,並且能讓LED亮一秒....拜請老師指導,感謝ReplyDeleteRepliesyehnan20/11/1513:17自己寫寫看吧。

先不管紅外線與超音波,同樣用狀態機的技巧,寫出你要的功能,然後再合併。

DeleteRepliesReplyReplyTony(黃志仁)20/11/1517:47好,我來研究,到時後再請教老師怎麼合併兩個狀態機謝謝ReplyDeleteRepliesReplyUnknown5/12/1522:35Thiscommenthasbeenremovedbytheauthor.ReplyDeleteRepliesReplyUnknown5/12/1522:37老師您好您的解釋真的很詳盡令人受益良多但小弟不才有個地方還是看不懂請問一開始只有宣告staticunsignedlonglastDebounceTime但他並沒有值呀,要怎麼與millis()做比較呢?ReplyDeleteRepliesyehnan5/12/1523:25靜態變數初始值為0DeleteRepliesReplyReply柳月飄21/12/1517:05葉老師您好,我測試一開始的開關程式,為什麼HIGHLOW的狀態是相反的呢?不管是用Mega2560還是UNO都有這個狀況,是不是都處在Highvoltageparallelprogramming狀態下編譯啊?意思是:電路接好,程式上傳完,led燈就自己亮了,按下按鈕後led才會滅如果把按鈕拿掉,也是直接亮著的,這個狀況我無解啊…還請教一下老師您ReplyDeleteRepliesyehnan21/12/1520:09>為什麼HIGHLOW的狀態是相反的呢?電路接錯了?>處在Highvoltageparallelprogramming狀態下編譯啊?啥?這麼高級的東西。

需要特別的燒錄器吧。

DeleteRepliesReplyReplyAddcommentLoadmore... NewerPost OlderPost Home Subscribeto: PostComments(Atom) SearchThisBlog Archives(bytime) ►  2021 (3) ►  07 (2) ►  03 (1) ►  2020 (1) ►  12 (1) ►  2019 (1) ►  07 (1) ►  2018 (1) ►  05 (1) ►  2017 (19) ►  12 (1) ►  11 (2) ►  09 (1) ►  04 (2) ►  03 (4) ►  02 (5) ►  01 (4) ►  2016 (73) ►  11 (2) ►  10 (3) ►  09 (14) ►  08 (4) ►  07 (2) ►  06 (2) ►  05 (10) ►  04 (23) ►  03 (1) ►  02 (1) ►  01 (11) ►  2015 (95) ►  12 (10) ►  11 (4) ►  10 (3) ►  09 (4) ►  08 (2) ►  07 (1) ►  06 (14) ►  05 (9) ►  04 (9) ►  03 (23) ►  02 (15) ►  01 (1) ►  2014 (77) ►  12 (2) ►  11 (3) ►  10 (4) ►  09 (7) ►  08 (5) ►  07 (6) ►  06 (8) ►  05 (4) ►  04 (12) ►  03 (10) ►  02 (8) ►  01 (8) ►  2013 (88) ►  12 (11) ►  11 (3) ►  10 (15) ►  09 (18) ►  08 (12) ►  07 (5) ►  06 (3) ►  05 (8) ►  04 (2) ►  03 (1) ►  02 (4) ►  01 (6) ▼  2012 (76) ►  12 (8) ►  11 (5) ►  10 (1) ►  09 (5) ►  08 (11) ►  07 (10) ►  06 (7) ►  04 (3) ►  03 (6) ▼  02 (17) RaspberryPi的第一批10000片板子開始販售也已經賣光了 Arduino小知識:enum與函式 Arduino練習:SimonSays請你跟我這樣做 Arduino練習:以LiquidCrystal程式庫控制LCD(相容於HitachiHD44780) Arduino小知識:int為2bytes Arduino練習:光敏電阻 Arduino在Windows的Cygwin命令列模式下進行編譯與上傳 Arduino練習:seven-segmentdisplay七段顯示器與時鐘 Arduino練習:霹靂車燈 Arduino軟體開發環境的設定檔preferences.txt Arduino練習:loudspeaker揚聲器 Arduino練習:RGBLED Arduino練習:呼吸燈 Arduino練習:以開關切換LED明滅狀態 ArduinoSketch基本架構與序列埠輸出 ArduinoUno開箱文與安裝設定 Arduino簡介 ►  01 (3) ►  2011 (32) ►  11 (4) ►  10 (1) ►  09 (4) ►  08 (4) ►  07 (3) ►  05 (3) ►  04 (4) ►  03 (7) ►  01 (2) ►  2010 (28) ►  12 (5) ►  11 (1) ►  10 (2) ►  09 (1) ►  08 (4) ►  06 (8) ►  05 (1) ►  04 (1) ►  02 (3) ►  01 (2) ►  2009 (34) ►  08 (7) ►  07 (3) ►  06 (4) ►  05 (3) ►  04 (1) ►  03 (7) ►  02 (3) ►  01 (6) ►  2008 (68) ►  12 (7) ►  11 (6) ►  10 (6) ►  09 (2) ►  08 (4) ►  07 (2) ►  06 (2) ►  05 (18) ►  04 (13) ►  01 (8) ►  2007 (105) ►  12 (17) ►  11 (4) ►  10 (12) ►  09 (7) ►  08 (16) ►  07 (14) ►  06 (4) ►  05 (2) ►  04 (23) ►  03 (5) ►  02 (1) Archives(bytags) Arduino (96) Arduino文章列表 (1) Australia (79) AustraliaWorkingHoliday (1) BananaPi (5) CircuitPython (1) cocos2d-iphone (4) ESP8266 (1) iOS (23) Java (2) JavaScript (1) LearningEnglish (27) LinkItONE (30) Linux (3) MicroPython (1) MUD (1) NodeMCU (1) programming (26) ProjectEuler (5) Python (18) RaspberryPi (194) UPboard (10) 咬一口蘋果 (17) 婚禮喜宴 (3) 懷舊記憶 (13) 旅遊Travel (6) 玩具 (3) 胡言亂語 (14) 遊戲 (4) 閱讀 (37) 電子Maker (26) 電影 (3) 電腦與網路 (34) AboutMe yehnan 朝曦灑落身俯仰似流雲 Viewmycompleteprofile  



請為這篇文章評分?