我是一名專業程序員,但我是Arduino世界的新手。我注意到許多Arduino所有者不知道編程的基本原理,並且無法在使用這個驚人的技術方面取得好的結果。
特別是,如果沒有必要,我想建議不要使用Arduino中斷,因爲只有兩個中斷,即使您可以爲單個傳感器或執行器寫一個「美麗」代碼必須實施一個更復雜的項目,你不能使用它們。當然你在使用中斷處理單個按鈕時是正確的,但是如果你有四個按鈕來管理呢?
因此,我使用「時間片」或「單步」技術重寫了「心跳」草圖。使用這種技術,每次執行循環功能時,您只需運行控制功能的「單步」,因此您可以根據需要插入儘可能多的數據,並且可以快速響應您使用的所有傳感器。 爲此,我爲每個必須實現的控制函數使用全局計數器,並且每次執行循環函數時,都執行每個函數的單個步驟。 這是新的草圖:
// Interrupt.ino - this sketch demonstrates how to implement a "virtual" interrupt using
// the technique of "single step" to avoid heavy duty cycles within the loop function.
int maxPwm = 128; // max pwm amount
int myPwm = 0; // current pwm value
int phase = 1; // current beat phase
int greenPin = 11; // output led pin
int buttonPin = 9; // input button pin
int buttonFlag = 1; // button flag for debounce
int myDir[] = {0,1,-1,1,-1}; // direction of heartbeat loop
int myDelay[] = {0,500,1000,500,3000}; // delay in microseconds of a single step
void setup()
{
pinMode(buttonPin, INPUT); // enable button pin for input
// it's not necessary to enable the analog output
}
void loop()
{
if(phase>0) heartbeat(); // if phase 1 to 4 beat, else steady
buttonRead(); // test if button has been pressed
}
// heartbeat function - each time is executed, it advances only one step
// phase 1: the led is given more and more voltage till myPwm equals to maxPwm
// phase 2: the led is given less and less voltage till myPwm equals to zero
// phase 3: the led is given more and more voltage till myPwm equals to maxPwm
// phase 4: the led is given less and less voltage till myPwm equals to zero
void heartbeat()
{
myPwm += myDir[phase];
analogWrite(greenPin, myPwm);
delayMicroseconds(myDelay[phase]);
if(myPwm==maxPwm||myPwm==0) phase = (phase%4)+1;
}
// buttonRead function - tests if the button is pressed;
// if so, forces phase 0 (no beat) and enlightens the led to the maximum pwm
// and remains in "inoperative" state till the button is released
void buttonRead()
{
if(digitalRead(buttonPin)!=buttonFlag) // if button status changes (pressed os released)
{
buttonFlag = 1 - buttonFlag; // toggle button flag value
if(buttonFlag) // if pressed, toggle between "beat" status and "steady" status
{
if(phase) myPwm = maxPwm; else myPwm = 0;
phase = phase==0;
analogWrite(greenPin, myPwm);
}
}
}
正如你看到的,代碼是非常緊湊和快速的執行。我將心跳循環分爲四個「階段」,由myDelay陣列調節,其計數方向由myDir陣列調節。如果沒有任何反應,pwm引腳的電壓在每一步都會遞增,直到達到maxPwm值,然後環路進入階段2,電壓遞減到零,依此類推,實現原始心跳。
如果按下該按鈕,則迴路進入零相(無心跳),並且LED與maxPwm電壓一致。從現在開始,循環保持穩定的指示燈,直到釋放按鈕(這實現「去抖」算法)。如果再次按下該按鈕,buttonRead函數將重新啓動心跳功能,使其再次進入階段1,以便恢復心跳。
如果再次按下按鈕,則心跳停止,等等。所有都沒有任何exhitation或反彈。
你先生是英雄和學者!這是我需要的指導。我設法用arduino attachInterrupt(與原始的avr-libc)做到這一點,但那就是我希望它做的一切!走這條路,我不需要改變任何有關其他功能延遲的事情,實際的ISR也沒有任何延誤。我沒有注意到開關有任何反彈,但我沒有得到儘可能實施的東西,這可能是一個很好的措施。或者,也許我會用硬件解決方案來獲得它。 (RC /反轉schmidtt觸發器)主要感謝embedded.kyle –
@JoshWisotzkey非常歡迎。請記住,你的芯片和你一樣喜歡被打斷。所以請保持短暫的中斷! –