arduino - 在arduino中,如何背景睡眠?

  显示原文与译文双语对照的内容
146 0

我刚从arduino开始,我已经喜欢它了。我想尝试处理以下伪代码流的一个项目:

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秒。换句话说,函数可以是 backgrounded,还是有一个类似于中的比如 after()的机制

我发现是一个聪明的解决方案,其中一个"手工"检查时间间隔,但希望有一个更高的的解决方案。

时间:原作者:0个回答

82 5

也许你可以尝试另一种方式。你可以使用时分复用或者其他方式,而不是遵循"非阻塞睡眠"概念。线程处理。

在blinking的时候使用线程可能会发出声音,但在处理非时间关键任务时, protothreads work 。快速介绍和arduino端口可以在以下位置找到:http://waynemay.com/threading-in-arduino/by来自这个链接显示了如何实现连续的闪烁,但是你的问题可以以解决。

线程可以以用来处理闪烁序列的方法是修改全局变量( 需要闪烁计数),并使用不受任何关注的线程。每次执行闪烁时线程也会减少变量。

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

#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秒的秒闪烁,在两秒之间的。如果将 statusBlinksCnt 设置为一个正值,则闪烁线程将执行许多闪烁。如果将 statusBlinksCnt 设置为负值,arduino将持续闪烁定义的闪烁序列,并在 STATUS_BLINK_SEQUENCE_PAUSE_INTRVL 中定义的序列之间持续闪烁。关闭。打开和暂停持续时间可以通过 STATUS_BLINK_UPDT_INTRVL 用毫秒表示的乘法来计算。

在输入引脚读和小denouncing时我没有时间测试,但是我只是注意到了,但是我只是注意到你想要sense状态,而我的代码uses输入,并在低输入状态闪烁。

原作者:
...