1. 程式人生 > >Arduino 開關控制小燈持續亮之具體思路

Arduino 開關控制小燈持續亮之具體思路

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 語句呢?我認為是可行的。經過實驗我認為只要延長時間,讀兩次數即可。

之所以會存在抖動,我認識是抖動的時間遠遠地長於程式執行一條語句的時間,此時需要延時再進行讀數。