如何在arduino中背景睡眠? [英] How to background a sleep in arduino?

查看:31
本文介绍了如何在arduino中背景睡眠?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚开始使用 arduino,我已经喜欢上了它.我想尝试处理以下伪代码流程的项目之一:

I am just starting with arduino and I already love it. One of the projects I would like to try deals with the follwing pseudo-code flow:

def switch():
    set_pin_2_to_HIGH
    wait_10_seconds
    set_pin_2_to_LOW

loop()
  // some time sensitive code, which should be executed on a
  // reasonably regular cycle
  if_pin_1_is_HIGH:
     switch()
  // some more code where the state of pin_2 will be tested, that code also need
  // to run in a reasonably regular cycle

因此,当条件满足时,我需要循环在 switch() 中循环而不停止 10 秒.换句话说,一个函数可以被后台处理,或者是否有类似于例如的机制after()Tkinter ?

I therefore need the loop to loop without stopping 10 seconds in switch() when the condition is met. In other words, can a function be backgrounded, or is there a mechanism similar to e.g. after() in Tkinter ?

我发现了一种巧妙的解决方法,其中手动"检查时间间隔但希望更多arduinoic解决方案.

I found a clever workaround where one "manually" checks time intervals but hope for a more arduinoic solution.

推荐答案

也许您可以尝试相反的方法.您可以使用时分复用或换句话说..线程,而不是遵循非阻塞睡眠"概念.

Maybe you could try the other way around. Instead of following a "non-blocking sleep" concept you can use time-division multiplexing or in other words.. threading.

使用线程来闪烁可能听起来过于复杂,但原型线程在处理非时间关键的任务时效果很好.快速介绍和 arduino 端口可以在这里找到:http://waynemay.com/threading-in-arduino/ 来自链接的帖子展示了如何实现连续闪烁,这不是您正在寻找的,但您的问题可以通过处理闪烁序列来解决.

Using threads for blinking may sound overcomplicated but protothreads work well in handling not time-critical tasks. Quick introduction and arduino port can be found here: http://waynemay.com/threading-in-arduino/ Post from the link shows how to implement continuous blinking which is not exactly what you are looking for but your problem can be solved by handling blinking sequences.

线程如何用于处理闪烁序列的想法是您修改全局变量(所需的闪烁计数)并使用线程来处理闪烁,而无需您的逻辑和任何阻塞调用的任何关注.每次执行闪烁时,线程也会递减变量.

The idea how threads can be used to handle blink sequences is that you modify a global variable (required blinks count) and use threads which take care of blinking without any attention from your logic and any blocking calls. Threads also decrement the variable each time blink is performed.

以下是我使用线程处理闪烁的示例:

Here is a sample of what I use to handle blinks using threads:

#include <graham-pt.h>

#define STATUS_PIN           13
#define SENSING_PIN          2

#define STATUS_BLINK_UPDT_INTRVL 100
#define STATUS_BLINK_ON_DURATION_INTRVL 100
#define STATUS_BLINK_OFF_DURATION_INTRVL 10
#define STATUS_BLINK_SEQUENCE_PAUSE_INTRVL 30

int statusBlinksCnt = 0;
unsigned long nowTs, lastSenseTs = 0;

struct pt ptIoThd, ptStatusBlinkOnThd, ptStatusBlinkOffThd;

/* statusBlinkOnThd turns on status led and control status blinking sequences
 */
static int statusBlinkOnThd(struct pt *pt, unsigned long _now, unsigned long _interval){
  static unsigned long lastUpdtTs = 0;
  static unsigned int onIntrvlsCnt = 0;
  static int constantIntrvlsCnt = 0; 
  static int sequencePauseDuration = -1; 
  PT_BEGIN(pt);

  while(1){
    PT_WAIT_UNTIL(pt, abs(_now - lastUpdtTs) >= _interval);  // millis() will overflow after 59 days so abs val must be calculated; one inconsistent sleep between scans avary 2 months is negible
    lastUpdtTs = _now;
    if (statusBlinksCnt == 0){
      digitalWrite(STATUS_PIN, LOW);
    }
    else{
      if (digitalRead(STATUS_PIN) == HIGH)
        onIntrvlsCnt++;
      if (statusBlinksCnt < constantIntrvlsCnt){
        constantIntrvlsCnt = statusBlinksCnt;   
      } 
    }

    if (onIntrvlsCnt >= STATUS_BLINK_ON_DURATION_INTRVL){
      digitalWrite(STATUS_PIN, LOW);
      onIntrvlsCnt = 0;
      if(statusBlinksCnt>0){
        statusBlinksCnt--;
      }
      else if (statusBlinksCnt<0)
        statusBlinksCnt++;

      if (statusBlinksCnt == 0){ //end of blinking sequence
        if (constantIntrvlsCnt < 0){
          sequencePauseDuration = STATUS_BLINK_SEQUENCE_PAUSE_INTRVL;
        }
      }
    }

    if (sequencePauseDuration > 0){
      sequencePauseDuration--;
      if(sequencePauseDuration==0){
        sequencePauseDuration = -1;
        statusBlinksCnt = constantIntrvlsCnt;
      }
    }


  }

  PT_END(pt);
}

/* statusBlinkOffThd turns off status led when blinking takes place
 */
static int statusBlinkOffThd(struct pt *pt, unsigned long _now, unsigned long _interval){
  static unsigned long lastUpdtTs = 0;
  static unsigned int offIntrvlsCnt = 0; 
  PT_BEGIN(pt);

  while(1){
    PT_WAIT_UNTIL(pt, abs(_now - lastUpdtTs) >= _interval);  // millis() will overflow after 59 days so abs val must be calculated; one inconsistent sleep between scans avary 2 months is negible
    lastUpdtTs = _now;
    if (statusBlinksCnt == 0){
      digitalWrite(STATUS_PIN, LOW);
    }
    else{
      if (digitalRead(STATUS_PIN) == LOW)
        offIntrvlsCnt++;
    }

    if (offIntrvlsCnt >= STATUS_BLINK_OFF_DURATION_INTRVL){
      digitalWrite(STATUS_PIN, HIGH);
      offIntrvlsCnt = 0;
    }
  }
  PT_END(pt);
}

void setup(){
  pinMode(SENSING_PIN, INPUT_PULLUP);
  pinMode(STATUS_PIN, OUTPUT);
  PT_INIT( &ptStatusBlinkOnThd );
  PT_INIT( &ptStatusBlinkOffThd );
  statusBlinksCnt = 2;
}

void loop(){
  nowTs = millis();

  // updating threads
  statusBlinkOnThd(&ptStatusBlinkOnThd, nowTs, STATUS_BLINK_UPDT_INTRVL);
  statusBlinkOffThd(&ptStatusBlinkOffThd, nowTs, STATUS_BLINK_UPDT_INTRVL);

  // debounce digital read by setting statusBlinkCnt indirectly - after certain delay after switch is pressed and hold
  if (digitalRead(SENSING_PIN) == LOW){
    if (lastSenseTs == 0){
     lastSenseTs = nowTs;
    }
  }
  else{
    lastSenseTs = 0;
  }

 //simple bouncing; may not work on millis counter overflow every ~59 days
  if(lastSenseTs > 0)
     if(nowTs - lastSenseTs > 50){
       statusBlinksCnt = 1; 
       lastSenseTs = 0;             // should be removed if blinking should be continuous when input is kept at LOW 
     }
}

上面的代码在启动时闪烁两次 10 秒,中间有 1 秒的暂停.如果您将 statusBlinksCnt 设置为正值,则闪烁线程将执行多次闪烁.如果您将 statusBlinksCnt 设置为负值,您的 arduino 将持续闪烁定义的闪烁序列,并在 STATUS_BLINK_SEQUENCE_PAUSE_INTRVL 中定义的序列之间暂停.关闭、开启和暂停持续时间可以通过将定义乘以以毫秒表示的 STATUS_BLINK_UPDT_INTRVL 来计算.

The code above makes two 10 second blinks on start up with 1 second pause in between. If you set statusBlinksCnt to a positive value that many blinks will be performed by the blinking threads. If you set statusBlinksCnt to a negative value your arduino will keep blinking defined sequence of blinks continuously with pause between sequences defined in STATUS_BLINK_SEQUENCE_PAUSE_INTRVL. Off, on and pause durations can be calculated by multiplying defines by STATUS_BLINK_UPDT_INTRVL expressed in milliseconds.

我没有时间(和附近的面包板..)来测试输入引脚读数和琐碎的谴责,但它应该可以工作,但是我只是注意到你想检测高状态,而我的代码在输入上使用上拉并闪烁在低输入状态.

I didn't have time (and breadboard nearby..) to test the input pin reading and trivial denouncing but it should work however I just noticed you want to sense HIGH state whereas my code uses pull-up on input and blinks on the LOW input state.

这篇关于如何在arduino中背景睡眠?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆