步骤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文章
935浏览量
54765 -
计时器
+关注
关注
1文章
419浏览量
32638 -
Arduino
+关注
关注
187文章
6464浏览量
186669
发布评论请先 登录
相关推荐
评论