动作控制灯

Motion controlled light

我正在尝试创建一个只有在天黑时才会打开的运动控制灯。

我想让灯在检测到运动时用 pwm 缓慢打开和关闭。现在我的代码可以正常工作并且几乎可以完成我想要的一切。

问题是我正在使用延迟功能在达到全亮度后保持灯亮。因此,如果在灯亮起时检测到运动,它不会重置计时器。一旦延迟计时器用完并且检测到运动,亮度将下降然后恢复。

我想让运动检测器重置使 LED 保持点亮的定时器,但无法使其正常工作。

我看过这些:

http://playground.arduino.cc/Code/AvoidDelay

https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay

但由于我对 arduino 代码的理解有限,我无法让它工作。我真的很感激任何帮助。

已解决

下面的工作代码:

const byte MotionPin = 4; // Motionsensor
int LightSensorPin = 2; // Lightsensor
const byte LedPin = 11; // LED

unsigned long MotionDetectedMillis; // When motion was detected
unsigned long ledTurnedOnAt; // when led was turned on
unsigned long turnOnDelay = 50; // wait to turn on LED
unsigned long turnOffDelay = 5000; // turn off LED after this time
bool ledReady = false; // Has motion been detected
bool ledState = false; // Led on or off
int LightSensorState = 0;

int fadeAmount = 5;   // How much to fade in a loop 
byte brightness = 0; 

void setup() {
 pinMode(MotionPin, INPUT);
 pinMode(LightSensorPin, INPUT);
 pinMode(LedPin, OUTPUT);

 digitalWrite(LedPin, LOW);
}

void loop() {
 // get the time at the start of this loop()
 unsigned long currentMillis = millis(); 

 if (digitalRead(MotionPin) == HIGH && digitalRead(LightSensorPin)== HIGH) 
 {
  MotionDetectedMillis = millis();
  ledReady = true;
 }

 if (ledReady) 
 {
   if ((unsigned long)(currentMillis - MotionDetectedMillis) >= turnOnDelay) 
   {
      while (brightness < 255)
      {
        brightness = brightness + fadeAmount;
        analogWrite(LedPin, brightness);
        delay(30); 
      }

     // setup our next "state"
     ledState = true;
     // save when the LED turned on
     ledTurnedOnAt = currentMillis;
     ledReady = false;
   }
 }

 // see if we are watching for the time to turn off LED
 if (ledState) 
 {
   if ((unsigned long)(currentMillis - ledTurnedOnAt) >= turnOffDelay) 
   {    
     while (brightness >0)
      {
        brightness = brightness - fadeAmount;
        analogWrite(LedPin, brightness);
        delay(30); 
      }
     ledState = false;
   }
 }
}

你要的是状态机;你必须在循环中跟踪你当前处于哪个状态以及触发下一个状态的条件是什么;因为只有当某些事情触发新状态时你的循环才会执行一个动作,而不是使用 delay() 你将使用 'waiting for timeout' 状态(记住要知道下一个状态是什么)。

如果这让您感到困惑,请将每个状态想象成说明手册中的步骤; 打开 led 1,等待 x,再打开 led 1,等待 y,等等。 因为你没有更多的延迟,在管理状态的 "normal flow" 之前或之后,你可以添加一些特殊情况,比如 "if input 2 is high and current state is X or Y then set current state to Z".

因此,您可以通过中断轻松存档您想要的内容,但对于像这样的简单项目,您只需删除 delay(OnTime) 功能即可获得相同的结果。 如果您想了解更多关于 Arduino UNO 使用的 atmega328 的中断,请转到 here