所有关于电路
项目

Arduino多任务!如何在Arduino代码中使用Milli

2017年10月11日通过瑞安琼斯

延迟陈述很棒,尤其是他们的简单性,但在尝试多次arduino时,他们可以真正对东西的阻碍。忘记延迟并跳上米兰()火车!

延迟陈述很棒,尤其是他们的简单性,但在尝试多次arduino时,他们可以真正对东西的阻碍。忘记延迟并跳上米兰()火车!

物料清单:

为什么?

当你需要微控制器短暂暂停时,插入一个延迟语句是很容易的,但当你试图做其他事情时,比如监视按钮的按下,这是一个真正的麻烦。随着我Arduino技能的提高,我想是时候放下延迟,学习如何在Arduino中同时处理多个任务了。是的,它确实为程序添加了更多代码,但反过来,它使您成为一个更熟练的程序员,并增加了Arduino的潜力。为此,我们需要学习如何使用“millis()”命令。

如何?

你看,延迟暂停你的Arduino程序,让它在那段时间内无法做任何其他事情。我们将学会这样做,而不是把整个节目暂停一段特定的时间在完成一个动作之前所经过的时间。当然,这是通过我们的好朋友“millis()”和一些用于存储数据的变量来完成的。为了简单起见,我们从每个人的第一个草图开始,《眨眼》但我们改为《毫不延迟的眨眼》

首先是像任何其他程序一样,声明任何必要的引脚或变量,例如引脚13上的LED。我们还需要一个整数来存储LED的当前状态。随着初始LED状态关闭,这将设置为低。然后声明“unsigned long”类型的变量“上一个梅里斯”。而不是使用“int,”无符号长变量是32位,对于其中值可能变得非常大的变量,我们可能想要等待在采取动作之前的潜在的时间。

“previous smillis”将用于存储我们的LED最后一次闪烁。"const long"也是32位,但永远不会改变,或者是不变。我们将将其设置为1000并将其用作暂停时间,以毫秒为单位(因为我们)总是想暂停1000毫秒。然后,当然,记得像往常一样为你的LED声明你的pinMode。

//常量不会改变。这里用于设置引脚编号:const int ledPin = 13;// LED引脚的数量//变量会改变:int ledState = LOW;//通常,你应该对保存时间的变量使用"unsigned long" //值会很快变得太大,对于int型存储unsigned long previoussmillis = 0;const long interval = 1000; // const long interval = 1000;// interval at which to blink(毫秒)void setup(){//设置数字pin为输出:pinMode(ledPin, output);}

然后我们进入循环!记住,我们不需要延迟,而是要计算从上一次眨眼到现在已经过去了多少时间,在我们的例子中是1000毫秒。如果规定的时间通过了,是时候改变了状态我们的LED,要么反之亦然,反之亦然。

首先,我们将unsigned long "currentMillis"设置为"millis()",它将当前的米兰的时间数。这将有助于我们确定是否有区别当前的时间和以前的时间超过了1000毫秒。为了做到这一点,我们说,如果当前时间-上一次我们的LED闪烁大于或等于我们的赋值是1000ms,将最近一次眨眼的时间存储为之前的smillis。这将帮助我们记住,从上一次眨眼到下一次循环已经有多久了。

如果LED状态为LOW,则设置为HIGH,否则设置为LOW。然后根据之前的状态数字写LED的HIGH或LOW。

Void loop(){//这里是你放置代码需要一直运行。//查看是否到了闪烁LED的时候;也就是说,如果//当前时间与上次闪烁时间之间的差异// LED大于您想要的间隔时间//闪烁LED。unsigned long currentMillis = millis();if (currentMillis - previousMillis >= interval){//保存上次闪烁的LED previousMillis = currentMillis;//如果LED是关闭的,则打开它,反之亦然:if (ledState == LOW) {ledState = HIGH;} else {ledState = LOW;} //用变量ledState设置LED: digitalWrite(ledPin, ledState);}}

记住要慢慢来,把代码分成更小的部分,这样你更容易理解。如果你现在还不懂,那也没关系——这需要一些练习。如果你理解了它并让它工作,试着在混合中添加第二个LED,让它们以不同的速率闪烁。关于这个主题的更多信息可以在Adafruit Industries网站上找到,在那里Bill Earl提供了一个关于arduino多任务的三部分系列,甚至添加电机和可寻址led到混合所以一探究竟!再次感谢您的跟进!

其他我的创新:

为自己提供这个项目!BOM。

4评论
  • W
    沃伦的冬天 2017年11月04

    祝贺你转换成milli 's(),但是在推荐给读者的代码中仍然有一些问题需要纠正。

    该陈述效率低下:
    if (currentMillis - previousMillis >= interval)

    这种低效率是由这句话引起的:
    previousMillis = currentMillis;

    你可以这样编码:
    time_to_do_work = currentmillis +间隔;
    -这只做一次数学工作在'间隔'。

    然后,测试将是:
    if (currentMillis >= Time_To_Do_Work)
    -没有数学工作,你节省了几个循环在每个循环。虽然对于这个琐碎的任务来说不是一个重要的考虑因素,但是您试图向读者展示他们应该如何编写自己的代码。

    ___
    下一个问题更为严重。

    此语句中再次出现错误:
    previousMillis = currentMillis;

    由于编码如此,您的应用程序的时间准确性将漂移。

    更准确的做法是这样编写语句:
    时间to_do_work =时间to_do_work +时间间隔;

    此编码将允许应用程序在达到时间“间隔”或过期时尽快采取行动。

    这是对计划重复事件的时间进行编码的一种更精确的方法。对于随机发生的事件,这是安排下一次所需时间的准确方法:
    time_to_do_work = currentmillis +间隔;

    因此,编写代码的最佳方式取决于应用程序的时间管理要求。

    当事情变得忙碌时,每循环节省一些循环可能会派上用场。

    ___
    您推荐的编码方法也错过了向您的读者介绍子例程的机会。

    这可以极大地提高代码的可读性,并减少维护任务期间的错误。

    考虑这种方法:
    if (currentMillis >= Time_To_Do_Work)
    {
    Update_LED_Status ();
    }

    我通常会在一行上编写这样的SIMPLE语句,各种测试相互对齐(因此您可以很容易地看到差异)。

    我还将对齐各种操作(子例程调用),以便您可以看到代码可以执行的各种操作。

    ___
    最后,您可以建议读者使用“有限状态机”方法研究编码。
    -https://en.m.wikipedia.org/wiki/Finite-state_machine

    喜欢的。 回复
    • F
      fabelizer 2017年11月18日
      正如我所理解的那样,随着减法操作,添加操作不会调整定时器溢出。这就是为什么在Arduino工作中的减法方法是首选。但是,我肯定不是一个中小企业。可以通过仔细选择当您的工作定时器复位发生时进行调整定时器蠕变,但是当包括功能时,由于执行的不同时间,它可能非常难以准确调整。
      喜欢的。 回复
  • R
    Raju17133 2018年12月16日

    大家好,我是raju ahmmed,来自孟加拉国,我需要一些帮助,请我有麻烦的编码编码arduino线追随者车,请给我代码电子邮件:.(必须启用JavaScript才能查看此电子邮件地址)
    请帮我
    谢谢你!

    喜欢的。 回复