步驟1:
這是否以便在草圖中編寫延遲。
int led = 13;
unsigned long delayStart = 0; // the time the delay started
bool delayRunning = false; // true if still waiting for delay to finish
void setup() {
pinMode(led, OUTPUT); // initialize the digital pin as an output.
digitalWrite(led, HIGH); // turn led on
delayStart = millis(); // start delay
delayRunning = true; // not finished yet
}
void loop() {
// check if delay has timed out after 10sec == 10000mS
if (delayRunning && ((millis() - delayStart) 》= 10000)) {
delayRunning = false; // // prevent this code being run more then once
digitalWrite(led, LOW); // turn led off
Serial.println(“Turned LED Off”);
}
// Other loop code here 。 . 。
Serial.println(“Run Other Code”);
}
在Arduino啟動后調用的 setup()方法中,LED會被打開上。一旦完成 setup(),Arduino就會一次又一次調用 loop()方法。這就是您大多數代碼的去向,讀取傳感器發送的輸出等。在上面的草圖中,第一次調用loop()時, delay(10000)會在關閉LED之前停止所有動作10秒鐘。并繼續。如果運行此代碼,則會在啟動后的10秒鐘內未打印出 Run Other Code (運行其他代碼),但是在led關閉(ledOn等于false)后,它會很快地循環打印出來
這里要注意的一點是,您真的不應該在loop()代碼中完全使用delay()函數。 有時在 setup()代碼中使用 delay()有時很方便,并且您通常可以使用很小的延遲(只有很少的延遲)來擺脫很小的麻煩 loop()代碼中的毫秒數,但您實際上應該避免在 loop()方法
中完全使用:如何在Arduino中編寫非阻塞延遲
上一幅草圖使用了阻塞延遲,即在延遲等待到期時,它完全停止了代碼執行任何其他操作。下一個草圖向您展示了如何編寫非阻塞延遲,該延遲使代碼在等待延遲到期之前繼續運行。
int led = 13;
unsigned long delayStart = 0; // the time the delay started
bool delayRunning = false; // true if still waiting for delay to finish
void setup() {
pinMode(led, OUTPUT); // initialize the digital pin as an output.
digitalWrite(led, HIGH); // turn led on
delayStart = millis(); // start delay
delayRunning = true; // not finished yet
}
void loop() {
// check if delay has timed out after 10sec == 10000mS
if (delayRunning && ((millis() - delayStart) 》= 10000)) {
delayRunning = false; // // prevent this code being run more then once
digitalWrite(led, LOW); // turn led off
Serial.println(“Turned LED Off”);
}
// Other loop code here 。 . 。
Serial.println(“Run Other Code”);
}
在上面的草圖中, setup()方法,將 delayStart 變量設置為 millis()的當前值。
millis()是一種內置方法,該方法返回自電路板加電以來的毫秒數。每次復位板卡時,它都從0開始,并由CPU硬件計數器每毫秒增加一次。稍后有關 millis()的更多信息。一旦完成 setup(),Arduino就會一遍又一遍地調用loop()方法。
每次 loop()都稱為代碼檢查。
a)延遲仍在運行,以及 b)如果 millis()與 delayStart 中存儲的值相差10000 mS(10秒) 》。
當時間經過10000mS或更多時,會將 delayRunning 設置為false,以防止再次執行if語句中的代碼并關閉led。
如果運行此草圖,您將很快看到運行其他代碼的打印,并且10秒鐘后,LED將關閉,如果很快,您可能會看到Turned LED Off
請參見下面的第4步,了解millisDelay庫如何簡化此代碼
第3步:無符號長整數,溢出和無符號減法
如果您熟悉無符號的long,溢出,無符號的算術以及使用無符號的long變量的重要性,那么您可以直接跳至使用millisDelay庫的第4步。
上一個草圖的重要部分是測試
(millis() - delayStart) 》= 10000
此測試必須以非常特定的方式進行編碼才能正常工作。
無符號長溢出
delayStart 變量a從 millis()內置函數返回的數字是 unsigned long 。這是一個從0到4,294,967,295的數字。
如果將1加到保持最大值4,294,967,295的 unsigned long ,答案將為0(零)。那就是溢出的數字,然后回繞到0。您可以想象溢出位會被丟棄。例如3位無符號111是最大值(7)加1得出1000(8),但是前導1溢出3位存儲空間并被丟棄,因此回繞到000。
最終,當cpu再加上一個變量時,它的變量包含 millis()結果將環繞到0。即 millis()將再次從0開始計數。如果您讓Arduino開發板運行4,294,967,295mS(即大約49天17小時,即50天),就會發生這種情況。
現在讓我們考慮另一種編碼測試的方式(millis()-delayStart)》 = 10000
算術上,此測試等于 millis()》 =(delayStart + 10000)
但是,如果您在將近50點后開始延遲天,例如 millis()返回4,294,966,300 mS,則 delayStart + 10000 將溢出到995,而測試millis()》 =(delayStart + 10000)將立即真實,不會有任何延遲。因此,這種形式的測試并不總是有效。
不幸的是,您不太可能在測試過程中遇到這種情況,但是由于它可能會意外地出現在長時間運行的設備中,例如車庫門控制器運行連續數月。如果嘗試使用
delayEnd = millis()+ 10000
,然后使用測試(millis()》 = delayEnd),您也會遇到類似的問題。
最后, delayStart 變量必須為 unsigned long 。如果改用 long (即 long int )或 int 或 unsigned int ,則它們可以hold小于從 millis()返回的 unsigned long 。最終,從 millis()重新調整的值將使存儲在其中的較小變量溢出,并且您會發現時間突然倒退了。例如,如果對 startDelay 使用 unsigned int ,則將在Uno板上65秒后發生。
另一個興趣點是 millis()-delayStart 的結果,當 delayStart 表示為4,294,966,300,而我們希望有10000mS的延遲時,會發生什么。
millis()會在發生這種情況之前回繞為0。請記住,將無符號長整數可以存儲的最大值加1會回繞到0。因此,一種計算millis()的方法-delayStart,其中《strong》 millis()已經環繞并且小于 delayStart ,是說“ W 我必須將多少數字加到delayStart等于millis()(溢出后)?”,即方程式delayStart + X == millis()
例如,再次使用一個3位無符號變量,要計算2-4(無符號),請考慮一個從0開始的時鐘面,并將其一直加到111( 7),然后回到0。現在要從4變到2,您需要加上6(5,6,7,0,1,2),所以2-4 = 6,這實際上是計算的工作方式,盡管
因此,兩個無符號長整數之差將始終為正數,范圍為0到4,294,967,295。例如,如果 startDelay 為1,并且 millis()換為0(50天后),則 millis()-startDelay 將等于4,294,967,295 。這意味著您可以在0到4,294,967,295毫秒之間的任意位置指定 DELAY_TIME ,并且(millis()-delayStart)》 = DELAY_TIME 將始終按預期工作,無論何時
步驟4:使用MillisDelay庫
要安裝millisDelay庫。下載了millisDelay.zip文件。
將此文件解壓縮到Arduino/libraries目錄(打開IDE File-》 preferences窗口以查看本地Arduino目錄的位置)。有時,有關如何安裝庫的說明-自動安裝工作,但并非總是如此。手動解壓縮文件是最安全的。安裝millisDelay庫后,將有三個可用的交互式示例,您可以將它們加載到Arduino板上,然后在9600baud處打開Serial Monitor(在5秒內)以使用它們。這是使用millisDelay庫重寫的先前的非阻塞延遲草圖。
#include “millisDelay.h”
int led = 13;
millisDelay ledDelay;
void setup() {
pinMode(led, OUTPUT); // initialize the digital pin as an output.
digitalWrite(led, HIGH); // turn led on
ledDelay.start(10000); // start a 10sec delay
}
void loop() {
// check if delay has timed out
if (ledDelay.justFinished()) {
digitalWrite(led, LOW); // turn led off
Serial.println(“Turned LED Off”);
}
// Other loop code here 。 . 。
Serial.println(“Run Other Code”);
}
如果查看millisDelay庫代碼,您將看到先前草圖的代碼已被移至庫中的 start()和 just Finished()方法。
這是ledDelay還是ledTimer?您可以使用自己喜歡的任何一個術語。我傾向于將。.. delay用于執行一次的單次延遲,并使用…timer重復一次。
步驟5:延遲和計時器示例
《這是兩個基本的延遲和計時器草圖以及它們的millisDelay庫等效項。這些示例用于一次關閉(單發)延遲和重復延遲/定時器。
單發延遲
單發延遲是僅運行一次然后出現一次的延遲。停止。它是Arduino delay()方法的最直接替代。您開始延遲,然后在延遲完成后執行一些操作。 BasicSingleShotDelay是普通代碼,而SingleShotMillisDelay使用millisDelay庫。
BasicSingleShotDelay
此草圖可在BasicSingleShotDelay.ino
int led = 13; // Pin 13 has an LED connected on most Arduino boards.
unsigned long DELAY_TIME = 10000; // 10 sec
unsigned long delayStart = 0; // the time the delay started
bool delayRunning = false; // true if still waiting for delay to finish
void setup() {
pinMode(led, OUTPUT); // initialize the digital pin as an output.
digitalWrite(led, HIGH); // turn led on
// start delay
delayStart = millis();
delayRunning = true;
}
void loop() {
// check if delay has timed out
if (delayRunning && ((millis() - delayStart) 》= DELAY_TIME)) {
delayRunning = false; // finished delay -- single shot, once only
digitalWrite(led, LOW); // turn led off
}
}
中找到。 loop()上方的行繼續運行,而不會停留在等待延遲到期之前。
在 loop()的每次通過期間,當前《將strong》 millis()和 delayStart 時間與 DELAY_TIME 進行比較。當計時器超過間隔值時,將采取所需的措施。在此示例中,延遲計時器停止并且LED熄滅。
SingleShotMillisDelay
這里是使用millisDelay庫重寫的BasicSingleShotDelay草圖。此草圖可在SingleShotMillisDelay.ino中找到。
這里是millisDelay版本,其中上面的代碼已包裝在millisDelay類的類方法中。
#include
int led = 13;
// Pin 13 has an LED connected on most Arduino boards.
millisDelay ledDelay;
void setup() {
// initialize the digital pin as an output.
pinMode(led, OUTPUT);
digitalWrite(led, HIGH); // turn led on
// start delay
ledDelay.start(10000);
}
void loop() {
// check if delay has timed out
if (ledDelay.justFinished()) {
digitalWrite(led, LOW); // turn led off
}
}
重復計時器
這些是重復延遲/計時器的簡單示例。
BasicRepeatingDelay
BasicRepeatingDelay是簡單的代碼,RepeatingMillisDelay使用millisDelay庫。
BasicRepeatingDelay.h
int led = 13; // Pin 13 has an LED connected on most Arduino boards.
unsigned long DELAY_TIME = 1500; // 1.5 sec
unsigned long delayStart = 0; // the time the delay started
bool delayRunning = false; // true if still waiting for delay to finish
bool ledOn = false; // keep track of the led state
void setup() {
pinMode(led, OUTPUT); // initialize the digital pin as an output.
digitalWrite(led, LOW); // turn led off
ledOn = false;
// start delay
delayStart = millis();
delayRunning = true;
}
void loop() {
// check if delay has timed out
if (delayRunning && ((millis() - delayStart) 》= DELAY_TIME)) {
delayStart += DELAY_TIME; // this prevents drift in the delays
// toggle the led
ledOn = !ledOn;
if (ledOn) {
digitalWrite(led, HIGH); // turn led on
} else {
digitalWrite(led, LOW); // turn led off
}
}
}
使用
delayStart + = DELAY_TIME;
重設延遲以再次運行,是否允許 millis()-delayStart 可能是》 DELAY_TIME ,因為 millis()剛剛增加,或者是由于 loop()中的某些其他代碼降低了它的速度。例如長打印語句。 (請參閱第7步中的添加循環Montor)
另一點是在 startup()的末尾開始延遲。即使 startup()需要花費一些時間來執行,這也可以確保計時器在 loop()開始時是準確的。
RepeatingMillisDelay
這是使用millisDelay庫重寫的BasicRepeatingDelay草圖。該草圖可在RepeatingMillisDelay.ino
#include
int led = 13;
// Pin 13 has an LED connected on most Arduino boards.
bool ledOn = false; // keep track of the led state
millisDelay ledDelay;
void setup() {
// initialize the digital pin as an output.
pinMode(led, OUTPUT); // initialize the digital pin as an output.
digitalWrite(led, LOW); // turn led off
ledOn = false;
// start delay
ledDelay.start(1500);
}
void loop() {
// check if delay has timed out
if (ledDelay.justFinished()) {
ledDelay.repeat(); // start delay again without drift
// toggle the led
ledOn = !ledOn;
if (ledOn) {
digitalWrite(led, HIGH); // turn led on
} else {
digitalWrite(led, LOW); // turn led off
}
}
}
步驟6:其他MillisDelay庫函數
中使用,除了 start(延遲),公正 Finished()和 repeat()功能,millisDelay庫也具有
stop()以停止延遲超時,
isRunning()以檢查其是否尚未超時且尚未停止,
restart()從現在開始重新延遲,使用相同的延遲間隔
finish()強制延遲過期
remaining()可以返回直到延遲結束為止的毫秒數,并且
delay()可以返回傳遞給 start()
庫的微秒版本
millisDelay的延遲值以毫秒為單位進行計數。您還可以按微秒計時。留給讀者練習寫該類的練習。 (提示:將類重命名為microDelay,并用micros()代替出現的millis())
凍結/暫停延遲
您可以凍結或通過保存剩余的()毫秒并停止延遲來暫停延遲,然后稍后以剩余的mS作為延遲重新啟動它以解除凍結。例如參見FreezeDelay.ino示例
mainRemainingTime = mainDelay.remaining(); // remember how long left to run in the main delay
mainDelay.stop(); // stop mainDelay NOTE: mainDelay.justFinished() is NEVER true after stop()
…
mainDelay.start(mainRemainingTime); // restart after freeze
步驟7:警告之言–添加循環監視器
不幸的是,許多標準Arduino庫使用 delay()或引入暫停,例如AnalogRead和SoftwareSerial。通常,這些引入的延遲很小,但是它們會加起來,所以我建議您在 loop()的頂部添加一個監視器,以檢查其運行速度。
循環監視器與眨眼示例非常相似。 loop()方法頂部的一小段代碼僅在每次執行 loop()時切換Led。然后,您可以使用具有Hz刻度的數字萬用表來測量LED引腳(在這種情況下為引腳13)上的輸出頻率
代碼為:-
// Loop Monitor – this checks that the loop() is executed at least once every 1mS
// (c)2013 Forward Computing and Control Pty. Ltd.
// www.forward.com.au》
//
// This example code is in the public domain.
int led = 13; // don‘t use on FioV3 when battery connected
// Pin 13 has an LED connected on most Arduino boards.
// if using Arduino IDE 1.5 or above you can use pre-defined
// LED_BUILTIN instead of ’led‘
// the setup routine runs once when you press reset:
void setup() {
// initialize the digital pin as an output.
pinMode(led, OUTPUT);
// add your other setup code here
}
// the loop routine runs over and over again forever:
void loop() {
// toggle the led output each loop The led frequency must measure 》500Hz (i.e. 《1mS off and 《1mS on)
if (digitalRead(led)) {
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
} else {
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
}
// add the rest of your loop code here
}
您可以在此處下載監視器代碼。當我在Uno板上運行此代碼時,連接在引腳13和GND之間的Hz范圍內的萬用表讀數為57.6Khz。即》 500hz的大約100倍。
將代碼添加到 loop()時,Hz讀數將減小。只要檢查它在所有情況下都保持在500Hz以上(每個loop()執行1mS)以上即可。
責任編輯:wv
-
編碼
+關注
關注
6文章
959瀏覽量
54976 -
計時器
+關注
關注
1文章
426瀏覽量
32887 -
Arduino
+關注
關注
188文章
6477瀏覽量
188029
發布評論請先 登錄
相關推薦
EE-109:ADSP2106x:使用2106x SPORT作為計時器
![EE-109:ADSP2106x:使用2106x SPORT作為<b class='flag-5'>計時器</b>](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
使用Arduino 1.6.8在AT STA模式下運行Wi-Fi,“WiFi強制休眠開始”功能后未調用延遲功能是怎么回事?
spi_flash期間的計時器中斷導致崩潰怎么解決?
如何在RTOS SDK中將FRC1計時器附加到NMI的信息?
雙路精密計時器選購指南:準確選擇,高效工作
具有可編程復位延遲功能的TPS3430-Q1汽車類窗口看門狗計時器數據表
![具有可編程復位<b class='flag-5'>延遲</b>功能的TPS3430-Q1汽車類窗口看門狗<b class='flag-5'>計時器</b>數據表](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
具有內部延遲計時器的2節至5節串聯鋰離子電池BQ7718過壓保護器數據表
![具有內部<b class='flag-5'>延遲</b><b class='flag-5'>計時器</b>的2節至5節串聯鋰離子電池BQ7718過壓保護<b class='flag-5'>器</b>數據表](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
具有內部延遲計時器、適用于3節至5節串聯鋰離子電池的過壓保護器BQ77205數據表
![具有內部<b class='flag-5'>延遲</b><b class='flag-5'>計時器</b>、適用于3節至5節串聯鋰離子電池的過壓保護<b class='flag-5'>器</b>BQ77205數據表](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
具有內部延遲計時器、適用于3節至16節串聯鋰離子電池的電壓和溫度保護器BQ77216數據表
![具有內部<b class='flag-5'>延遲</b><b class='flag-5'>計時器</b>、適用于3節至16節串聯鋰離子電池的電壓和溫度保護<b class='flag-5'>器</b>BQ77216數據表](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
具有可調節延遲和看門狗計時器的TPS386000和TPS386040四路電源電壓監視器數據表
![具有可調節<b class='flag-5'>延遲</b>和看門狗<b class='flag-5'>計時器</b>的TPS386000和TPS386040四路電源電壓監視<b class='flag-5'>器</b>數據表](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
具有可編程復位延遲功能的 TPS3430 窗口看門狗計時器數據表
![具有可編程復位<b class='flag-5'>延遲</b>功能的 TPS3430 窗口看門狗<b class='flag-5'>計時器</b>數據表](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
評論