Arduino 開關控制小燈持續亮之具體思路
為什么寫這篇文章:
我們用開關控制燈的亮滅的時候,希望只需要按一下按鍵就可以做到燈一直亮着。而在《Arduino魔法書》中——有彈性的按鍵這一節主要講了消除抖動函數,但是沒有講這個程序的原理。
書中的代碼如下
const int LED = 9; const int BUTTON = 2; boolean lastButton = LOW; boolean currentButton = LOW; boolean ledOn = false; void setup() { pinMode(LED,OUTPUT); pinMode(BUTTON,INPUT); // put your setup code here, to run once: } boolean debounce(boolean last) { boolean current = digitalRead(BUTTON); if(last != current) { delay(5); current = digitalRead(BUTTON); } return current; } void loop() { currentButton = debounce(lastButton); if (lastButton ==LOW && currentButton == HIGH) { ledOn = !ledOn; } lastButton = currentButton; digitalWrite(LED,ledOn); // put your main code here, to run repeatedly: }
首先,我們假設沒有抖動,只關注 loop()函數的部分,currentButton = debounce(lastButton);
這時等價於current = digitalRead(BUTTON);
第一次按——開燈
首先需要想的是:
當按下的時候,燈能夠一直亮着。
如果使用digitalRead來讀當前的值,當按完以后,燈就會熄滅。所以,利用一個條件語句:條件是:按下按鍵,動作(或者結果)是燈持續亮。
用代碼表示如下
所以必須更改原來的條件和動作。先考慮動作,不妨把燈亮變成一個狀態量,而不是臨時讀取的量,這里定義為 ledOn.
那么接下來需要想的是如何更改 ledOn 這個值呢?那就是通過按鍵的狀態變化來考慮了。另外,我們也想要燈亮時再次按下按鍵的時候,能夠熄滅燈。所以可以用到一個反轉語句:ledOn = !ledOn;
接下來就是條件的問題了:無論你是想持續點亮燈還是熄滅燈,這時候按鍵的狀態總是 HIGH,而之前的狀態總是 LOW.
所以你可以用以下語句決定是否執行反轉語句:if(lastButton = LOW&& currentButton = HIGH);
來進行判斷。
第一次以后
然后之下的語句:lastButton = currentButton,此時,lastButton 的值變為 HIGH,然后重新返回 loop()函數的第一行,進入debounce()函數,此時,你已經不再按鍵了,所以返回的 currentButton 的值為LOW,然后已經返回值后執行下一條語句,也就是if()的條件語句,因為lastButton = HIGH ,currentBUTTON = LOW ,所以不滿足條件,直接執行 lastButton = currentButton,這時,lastButton 和 currentButton 的值都為 LOW。
第二次按——關燈
下一次你再進行按鍵的時候,就會反轉 ledOn的數值,ledOn熄滅。
最后,我們來考慮消除抖動
之所以要消除抖動,是因為如果不消除抖動,currentButton 的值是不確定的,所以會導致結果的無法預測,不能人為地掌控。
如何消除抖動呢,書中寫道5ms之后,抖動一般都會消失,所以 delay(5); 之后再次讀取數值。
但是需要時時刻刻讀取嗎?不需要,所以可以加一個條件語句。
也就是 if (last! = current)
如果沒必要進行5ms的等待了再次讀取,那么程序變成這樣:
boolean debounce(boolean last) { boolean current = digitalRead(BUTTON); if(last != current) return current; }
此時如果last = current ,返回值都是沒有消除抖動的,所以消除抖動需要有一個 if 也需要延時delay.
那么,如果沒有if 語句呢?我認為是可行的。經過實驗我認為只要延長時間,讀兩次數即可。
之所以會存在抖動,我認識是抖動的時間遠遠地長於程序運行一條語句的時間,此時需要延時再進行讀數。