首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于millis的PIR连续运动检测

基于millis的PIR连续运动检测
EN

Stack Overflow用户
提问于 2019-09-18 01:27:22
回答 1查看 672关注 0票数 0

我正在尝试检测何时连续的运动已经被触发从PIR传感器超过8秒。这是我所拥有的。当感应器很低时“没有动作.”显示,然后短动触发第一个'< 8秒‘IF语句。当传感器恢复到低端时-没有显示它应该显示的运动,但是当第二次检测到运动时,代码似乎冻结了,什么也没有发生。

代码语言:javascript
复制
unsigned long startMillis;
boolean timingFlag  = false;
const int buttonPin = 2;
int buttonState = 0;

void setup() {
   pinMode(buttonPin, INPUT);
   Serial.begin(19200);
   delay(500);
}

void loop() {
  buttonState = digitalRead(buttonPin);
  if (buttonState == HIGH && millis() - startMillis <= 8000UL)
  {
    Serial.println("Motion Detected but less than 8");
    delay(1000);
    //the PIR timed out with in the three seconds so cancel timing
    timingFlag = false;    //disable timing 
  }

  if (buttonState == LOW)
  {   
    Serial.println("No Motion...");   
    delay(1000);
    timingFlag = true;     //enable timing       
  }
  //when nine seconds have gone by with consistant detection do something
  if (timingFlag == false && millis() - startMillis >= 9000UL)
  {
    //There has now been nine seconds of constant PIR detection
    Serial.println("Motion Detected and greater than 9 sec");
    delay(1000);
    //Do Something   
  }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-09-18 12:04:59

正如Scheff在注释中提到的,当前代码有一个非常明显的问题:您从未实际将startMillis设置为任何东西,因此它们可能(但不一定)总是0。

这意味着,在8000 ms之后,if (buttonState == HIGH && millis() - startMillis <= 8000UL)语句将永远是false (直到millis()结束,大约50天后* ),因此在此之后timingFlag将永远不会被重置为false。这最终会导致你的“冰冻”状况。

我试图在代码中找到一个设置startMillis的好地方,但老实说,我觉得这有点让人费解,所以我允许自己重写您的逻辑,希望您不介意。(请注意,我还将变量名从按钮改为检测器,因为这似乎更适合我):

(此版本在从高到低的转换中触发)

代码语言:javascript
复制
// define the threshold, after which an action shall be triggered
const int detectionThreshold = 8000;
const int detectorPin = 2;

unsigned long startTime = 0;
int lastDetectorState = LOW;

void setup() {
   pinMode(detectorPin, INPUT);
   Serial.begin(19200);
   delay(500);
}

void triggerDetectionAction(){
    // do whatever needs to be done after 8 seconds of motion in here
}

void loop() {

    int currentDetectorState = digitalRead(detectorPin);

    // if detector is low, no motion is detected
    if( currentDetectorState == LOW ){
        // when the detector is LOW, we want to check if the last state was HIGH
        // because then we just arrived at the transition from HIGH to LOW =>
        // "something was detected" to "there is no longer something detected"
        if( lastDetectorState == HIGH ){
            // then, we can get the total duration, the detection lasted
            unsigned long detectionDuration = millis() - startTime;
            // and print it for easier debugging
            Serial.print("Detection ended after ");
            Serial.print(detectionDuration);
            Serial.println(" milliseconds");

           // finally, we check if the durations was more than
           // or equal to our threshold
           if( detectionDuration >= detectionThreshold ){
               // and trigger stuff if necessary
               triggerDetectionAction();
           }
        }

        // if last detector state was LOW too, 
        // we don't want to do anything

    }else{

        // here we wan't to check for the transition of LOW to HIGH, 
        // so we check our last detector state
        if( lastDetectorState == LOW ){
            // if we caught the transition, 
            // set the start time to the current millis
            startTime = millis();

            // we could also set an indicator LED
            // or Serial.print something here
            Serial.println("Detection started");
        }

        // otherwise, we don't wan't to do anything

    }

    // finally, we save our current state into the last state, 
    // so we have it available in the next loop
    lastDetectorState = currentDetectorState;

    // do your other loop stuff here

}

请注意,在编写代码时我无法测试代码,因此可能会出现(语法)错误。

*更多关于millis和overflow的信息:https://www.arduino.cc/reference/en/language/functions/time/millis/

更新:此版本将在达到阈值时立即触发。它还包括一个示例,说明如何在达到阈值后触发一次和每一次循环。

代码语言:javascript
复制
// define the threshold, after which an action shall be triggered
const int detectionThreshold = 8000;
const int detectorPin = 2;

unsigned long startTime = 0;
int lastDetectorState = LOW;
bool actionTriggered = false;

void setup() {
   pinMode(detectorPin, INPUT);
   Serial.begin(19200);
   delay(500);
}

void triggerOnce(){
    // this will be called once, when the threshold is reached
}

void triggerEveryLoop(){
    // this will be called every loop, after the threshold was reached
    // for as long as the detector stays high
}

void loop() {

    int currentDetectorState = digitalRead(detectorPin);

    if( currentDetectorState == LOW ){

        if( lastDetectorState == HIGH ){
            // since we want to trigger immediately when the threshold is reached,
            // we actually don't need this transition any longer.
            // We can still keep it for debugging reasons thought.
            // If you don't need this, you can simply remove the entire block
            unsigned long detectionDuration = millis() - startTime;
            Serial.print("Detection ended after ");
            Serial.print(detectionDuration);
            Serial.println(" milliseconds");
        }

    }else{

        // Check for LOW => HIGH transition change
        if( lastDetectorState == LOW ){
            // if we caught the transition, 
            // set the start time to the current millis
            startTime = millis();

            // and reset the flag
            actionTriggered = false;

            // we could also set an indicator LED
            // or Serial.print something here
            Serial.println("Detection started");

        }else{

            // otherwise we want to check the duration
            unsigned long detectionDuration = millis() - startTime;

            // and trigger immediatley when the threshold is reached
            if( detectionDuration >= detectionThreshold ){

               // as long as it wasn't already triggered before
               if( !actionTriggered ){

                   Serial.println("Threshold reached, triggering");

                   // now we also need to set a flag, so we know we already triggerd this action once
                   actionTriggered = true;

                   triggerOnce();
               }

               // we can also do something every loop
               // this can be handy for e.g. blinking a light or playing a sound or something
               triggerEveryLoop();

           }

        }

    }

    // finally, we save our current state into the last state, 
    // so we have it available in the next loop
    lastDetectorState = currentDetectorState;

    // do your other loop stuff here

}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57983828

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档