步驟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啟動(dòng)后調(diào)用的 setup()方法中,LED會(huì)被打開上。一旦完成 setup(),Arduino就會(huì)一次又一次調(diào)用 loop()方法。這就是您大多數(shù)代碼的去向,讀取傳感器發(fā)送的輸出等。在上面的草圖中,第一次調(diào)用loop()時(shí), delay(10000)會(huì)在關(guān)閉LED之前停止所有動(dòng)作10秒鐘。并繼續(xù)。如果運(yùn)行此代碼,則會(huì)在啟動(dòng)后的10秒鐘內(nèi)未打印出 Run Other Code (運(yùn)行其他代碼),但是在led關(guān)閉(ledOn等于false)后,它會(huì)很快地循環(huán)打印出來
這里要注意的一點(diǎn)是,您真的不應(yīng)該在loop()代碼中完全使用delay()函數(shù)。 有時(shí)在 setup()代碼中使用 delay()有時(shí)很方便,并且您通常可以使用很小的延遲(只有很少的延遲)來擺脫很小的麻煩 loop()代碼中的毫秒數(shù),但您實(shí)際上應(yīng)該避免在 loop()方法
中完全使用:如何在Arduino中編寫非阻塞延遲
上一幅草圖使用了阻塞延遲,即在延遲等待到期時(shí),它完全停止了代碼執(zhí)行任何其他操作。下一個(gè)草圖向您展示了如何編寫非阻塞延遲,該延遲使代碼在等待延遲到期之前繼續(xù)運(yùn)行。
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 變量設(shè)置為 millis()的當(dāng)前值。
millis()是一種內(nèi)置方法,該方法返回自電路板加電以來的毫秒數(shù)。每次復(fù)位板卡時(shí),它都從0開始,并由CPU硬件計(jì)數(shù)器每毫秒增加一次。稍后有關(guān) millis()的更多信息。一旦完成 setup(),Arduino就會(huì)一遍又一遍地調(diào)用loop()方法。
每次 loop()都稱為代碼檢查。
a)延遲仍在運(yùn)行,以及 b)如果 millis()與 delayStart 中存儲(chǔ)的值相差10000 mS(10秒) 》。
當(dāng)時(shí)間經(jīng)過10000mS或更多時(shí),會(huì)將 delayRunning 設(shè)置為false,以防止再次執(zhí)行if語句中的代碼并關(guān)閉led。
如果運(yùn)行此草圖,您將很快看到運(yùn)行其他代碼的打印,并且10秒鐘后,LED將關(guān)閉,如果很快,您可能會(huì)看到Turned LED Off
請(qǐng)參見下面的第4步,了解millisDelay庫如何簡(jiǎn)化此代碼
第3步:無符號(hào)長(zhǎng)整數(shù),溢出和無符號(hào)減法
如果您熟悉無符號(hào)的long,溢出,無符號(hào)的算術(shù)以及使用無符號(hào)的long變量的重要性,那么您可以直接跳至使用millisDelay庫的第4步。
上一個(gè)草圖的重要部分是測(cè)試
(millis() - delayStart) 》= 10000
此測(cè)試必須以非常特定的方式進(jìn)行編碼才能正常工作。
無符號(hào)長(zhǎng)溢出
delayStart 變量a從 millis()內(nèi)置函數(shù)返回的數(shù)字是 unsigned long 。這是一個(gè)從0到4,294,967,295的數(shù)字。
如果將1加到保持最大值4,294,967,295的 unsigned long ,答案將為0(零)。那就是溢出的數(shù)字,然后回繞到0。您可以想象溢出位會(huì)被丟棄。例如3位無符號(hào)111是最大值(7)加1得出1000(8),但是前導(dǎo)1溢出3位存儲(chǔ)空間并被丟棄,因此回繞到000。
最終,當(dāng)cpu再加上一個(gè)變量時(shí),它的變量包含 millis()結(jié)果將環(huán)繞到0。即 millis()將再次從0開始計(jì)數(shù)。如果您讓Arduino開發(fā)板運(yùn)行4,294,967,295mS(即大約49天17小時(shí),即50天),就會(huì)發(fā)生這種情況。
現(xiàn)在讓我們考慮另一種編碼測(cè)試的方式(millis()-delayStart)》 = 10000
算術(shù)上,此測(cè)試等于 millis()》 =(delayStart + 10000)
但是,如果您在將近50點(diǎn)后開始延遲天,例如 millis()返回4,294,966,300 mS,則 delayStart + 10000 將溢出到995,而測(cè)試millis()》 =(delayStart + 10000)將立即真實(shí),不會(huì)有任何延遲。因此,這種形式的測(cè)試并不總是有效。
不幸的是,您不太可能在測(cè)試過程中遇到這種情況,但是由于它可能會(huì)意外地出現(xiàn)在長(zhǎng)時(shí)間運(yùn)行的設(shè)備中,例如車庫門控制器運(yùn)行連續(xù)數(shù)月。如果嘗試使用
delayEnd = millis()+ 10000
,然后使用測(cè)試(millis()》 = delayEnd),您也會(huì)遇到類似的問題。
最后, delayStart 變量必須為 unsigned long 。如果改用 long (即 long int )或 int 或 unsigned int ,則它們可以hold小于從 millis()返回的 unsigned long 。最終,從 millis()重新調(diào)整的值將使存儲(chǔ)在其中的較小變量溢出,并且您會(huì)發(fā)現(xiàn)時(shí)間突然倒退了。例如,如果對(duì) startDelay 使用 unsigned int ,則將在Uno板上65秒后發(fā)生。
另一個(gè)興趣點(diǎn)是 millis()-delayStart 的結(jié)果,當(dāng) delayStart 表示為4,294,966,300,而我們希望有10000mS的延遲時(shí),會(huì)發(fā)生什么。
millis()會(huì)在發(fā)生這種情況之前回繞為0。請(qǐng)記住,將無符號(hào)長(zhǎng)整數(shù)可以存儲(chǔ)的最大值加1會(huì)回繞到0。因此,一種計(jì)算millis()的方法-delayStart,其中《strong》 millis()已經(jīng)環(huán)繞并且小于 delayStart ,是說“ W 我必須將多少數(shù)字加到delayStart等于millis()(溢出后)?”,即方程式delayStart + X == millis()
例如,再次使用一個(gè)3位無符號(hào)變量,要計(jì)算2-4(無符號(hào)),請(qǐng)考慮一個(gè)從0開始的時(shí)鐘面,并將其一直加到111( 7),然后回到0。現(xiàn)在要從4變到2,您需要加上6(5,6,7,0,1,2),所以2-4 = 6,這實(shí)際上是計(jì)算的工作方式,盡管
因此,兩個(gè)無符號(hào)長(zhǎng)整數(shù)之差將始終為正數(shù),范圍為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 將始終按預(yù)期工作,無論何時(shí)
步驟4:使用MillisDelay庫
要安裝millisDelay庫。下載了millisDelay.zip文件。
將此文件解壓縮到Arduino/libraries目錄(打開IDE File-》 preferences窗口以查看本地Arduino目錄的位置)。有時(shí),有關(guān)如何安裝庫的說明-自動(dòng)安裝工作,但并非總是如此。手動(dòng)解壓縮文件是最安全的。安裝millisDelay庫后,將有三個(gè)可用的交互式示例,您可以將它們加載到Arduino板上,然后在9600baud處打開Serial Monitor(在5秒內(nèi))以使用它們。這是使用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?您可以使用自己喜歡的任何一個(gè)術(shù)語。我傾向于將。.. delay用于執(zhí)行一次的單次延遲,并使用…timer重復(fù)一次。
步驟5:延遲和計(jì)時(shí)器示例
《這是兩個(gè)基本的延遲和計(jì)時(shí)器草圖以及它們的millisDelay庫等效項(xiàng)。這些示例用于一次關(guān)閉(單發(fā))延遲和重復(fù)延遲/定時(shí)器。
單發(fā)延遲
單發(fā)延遲是僅運(yùn)行一次然后出現(xiàn)一次的延遲。停止。它是Arduino delay()方法的最直接替代。您開始延遲,然后在延遲完成后執(zhí)行一些操作。 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()上方的行繼續(xù)運(yùn)行,而不會(huì)停留在等待延遲到期之前。
在 loop()的每次通過期間,當(dāng)前《將strong》 millis()和 delayStart 時(shí)間與 DELAY_TIME 進(jìn)行比較。當(dāng)計(jì)時(shí)器超過間隔值時(shí),將采取所需的措施。在此示例中,延遲計(jì)時(shí)器停止并且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
}
}
重復(fù)計(jì)時(shí)器
這些是重復(fù)延遲/計(jì)時(shí)器的簡(jiǎn)單示例。
BasicRepeatingDelay
BasicRepeatingDelay是簡(jiǎn)單的代碼,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;
重設(shè)延遲以再次運(yùn)行,是否允許 millis()-delayStart 可能是》 DELAY_TIME ,因?yàn)?millis()剛剛增加,或者是由于 loop()中的某些其他代碼降低了它的速度。例如長(zhǎng)打印語句。 (請(qǐng)參閱第7步中的添加循環(huán)Montor)
另一點(diǎn)是在 startup()的末尾開始延遲。即使 startup()需要花費(fèi)一些時(shí)間來執(zhí)行,這也可以確保計(jì)時(shí)器在 loop()開始時(shí)是準(zhǔn)確的。
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庫函數(shù)
中使用,除了 start(延遲),公正 Finished()和 repeat()功能,millisDelay庫也具有
stop()以停止延遲超時(shí),
isRunning()以檢查其是否尚未超時(shí)且尚未停止,
restart()從現(xiàn)在開始重新延遲,使用相同的延遲間隔
finish()強(qiáng)制延遲過期
remaining()可以返回直到延遲結(jié)束為止的毫秒數(shù),并且
delay()可以返回傳遞給 start()
庫的微秒版本
millisDelay的延遲值以毫秒為單位進(jìn)行計(jì)數(shù)。您還可以按微秒計(jì)時(shí)。留給讀者練習(xí)寫該類的練習(xí)。 (提示:將類重命名為microDelay,并用micros()代替出現(xiàn)的millis())
凍結(jié)/暫停延遲
您可以凍結(jié)或通過保存剩余的()毫秒并停止延遲來暫停延遲,然后稍后以剩余的mS作為延遲重新啟動(dòng)它以解除凍結(jié)。例如參見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:警告之言–添加循環(huán)監(jiān)視器
不幸的是,許多標(biāo)準(zhǔn)Arduino庫使用 delay()或引入暫停,例如AnalogRead和SoftwareSerial。通常,這些引入的延遲很小,但是它們會(huì)加起來,所以我建議您在 loop()的頂部添加一個(gè)監(jiān)視器,以檢查其運(yùn)行速度。
循環(huán)監(jiān)視器與眨眼示例非常相似。 loop()方法頂部的一小段代碼僅在每次執(zhí)行 loop()時(shí)切換Led。然后,您可以使用具有Hz刻度的數(shù)字萬用表來測(cè)量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
}
您可以在此處下載監(jiān)視器代碼。當(dāng)我在Uno板上運(yùn)行此代碼時(shí),連接在引腳13和GND之間的Hz范圍內(nèi)的萬用表讀數(shù)為57.6Khz。即》 500hz的大約100倍。
將代碼添加到 loop()時(shí),Hz讀數(shù)將減小。只要檢查它在所有情況下都保持在500Hz以上(每個(gè)loop()執(zhí)行1mS)以上即可。
責(zé)任編輯:wv
-
編碼
+關(guān)注
關(guān)注
6文章
967瀏覽量
55481 -
計(jì)時(shí)器
+關(guān)注
關(guān)注
1文章
428瀏覽量
33461 -
Arduino
+關(guān)注
關(guān)注
188文章
6490瀏覽量
190072
發(fā)布評(píng)論請(qǐng)先 登錄
EE-109:ADSP2106x:使用2106x SPORT作為計(jì)時(shí)器

單個(gè) MSP430? 計(jì)時(shí)器模塊的多時(shí)基應(yīng)用說明

MSPM0-高級(jí)控制計(jì)時(shí)器有助于實(shí)現(xiàn)更好的控制和更好的數(shù)字輸出

用于電源門控的TPL5110毫微功耗系統(tǒng)計(jì)時(shí)器數(shù)據(jù)表

用于電源門控應(yīng)用的TPL5111毫微功耗系統(tǒng)計(jì)時(shí)器數(shù)據(jù)表

TLC555-Q1 LinCMOS?計(jì)時(shí)器數(shù)據(jù)表

TLC555 LinCMOS?技術(shù)計(jì)時(shí)器數(shù)據(jù)表

LMC555 CMOS計(jì)時(shí)器數(shù)據(jù)表

使用Arduino 1.6.8在AT STA模式下運(yùn)行Wi-Fi,“WiFi強(qiáng)制休眠開始”功能后未調(diào)用延遲功能是怎么回事?
spi_flash期間的計(jì)時(shí)器中斷導(dǎo)致崩潰怎么解決?
如何在RTOS SDK中將FRC1計(jì)時(shí)器附加到NMI的信息?
在esp8266中構(gòu)建了一個(gè)HTTP服務(wù)器,功處理HTTP請(qǐng)求后,軟件計(jì)時(shí)器停止了,為什么?
TLE986x如何定期重新啟動(dòng)計(jì)時(shí)器?
雙路精密計(jì)時(shí)器選購指南:準(zhǔn)確選擇,高效工作
SNx5DPHY440SS CSI-2/DSI DPHY 重計(jì)時(shí)器數(shù)據(jù)表

評(píng)論