I'm quit new into arduino, but it looks like a lot of fun.
What I want to do:
If it gets dark (LDR sensor) AND there is someone in the room (PIR sensor) the light (LED) will switch on.
So far so good.
I would like to add the conditions (and I don't know how ):
If someone is in the room, he can overrule condition nr. 1 and forge the light to go OFF or ON with a button --> if someone is in the room AND button is pressed the light will be forged to the opposite of the current status.
If the light is forged ON by hand (button) AND there is no one in the room for one hour, the light will switch off.
If a shadow passes in front of the LDR sensor (for example a cloud in front of the sun), the light shouldn't switch OFF and ON all the time. There should be some delay or smoothing on it.
My current code.
// constants won't change. They're used here to
// set pin numbers:
const int buttonPin = 7;Â Â // the number of the pushbutton pin
const int ledGreenPin = 12;Â Â Â // the number of the LED pin
const int LDRPin = A0;Â // select the analog input pin for light sensor
const int PIRPin = 6;Â Â // the number of the pessence sensor pin
// Variables will change:
int ledState = HIGH;Â Â Â Â // the current state of the output pin
int buttonState;Â Â Â Â Â Â // the current reading from the input pin
int lastButtonState = LOW;Â // the previous reading from the input pin
int LDRValue = 0;Â Â Â Â // variable to store the value coming from the sensor
int PIRValue;Â Â Â // the cuttent reading from the input pin
void setup() {
 pinMode(buttonPin, INPUT);
 pinMode(PIRPin, INPUT);    //initialize the PIR pin as an input
 pinMode(ledGreenPin, OUTPUT);
 Serial.begin(9600);  //sets serial port for communication
}
void loop() {
 LDRValue = analogRead(LDRPin); // read the value from the sensor
 Serial.println(LDRValue); //prints the values coming from the sensor on the screen
// read the state of the presence sensor value:
 PIRValue = digitalRead(PIRPin);
// read the state of the switch into a local variable:
 int reading = digitalRead(buttonPin);
Â
Â
 if(LDRValue < 750 && PIRValue == HIGH) { //setting a threshold value
  // turn LED on:
  digitalWrite(ledGreenPin, HIGH);
 } else if (LDRValue > 850 || PIRValue ==LOW){
  // turn LED off:
  digitalWrite(ledGreenPin, LOW);
 }
}
unsigned long currentMillis = millis();
Â
 if(PIRValue == HIGH){
  previousMillis=currentMillis; // reset the counter during absence
  if(LDRValue < 750 && PIRValue == HIGH) { //setting a threshold value
   // turn LED on:
   digitalWrite(ledGreenPin, HIGH);
  } else if (LDRValue > 850 || PIRValue ==LOW){
   // turn LED off:
   digitalWrite(ledGreenPin, LOW);
  }
 } else{
  Serial.println(currentMillis-previousMillis);
  if(currentMillis-previousMillis > 10000){ //if there is no one in the room for a certain time
   digitalWrite(ledGreenPin, LOW); // the light turns off
   previousMillis=currentMillis; // reset the counter
  }
 }
Does your PIR have an in-built timer. That is, if it is triggered, it remains in a triggered state for some time, even if the cause of the trigger is no longer present ?
If the person in the room overrides the PIR and switches the light off, how long should the override last. Also 1 hour as in case #3 ?
If the person overrides the PIR and switches the light off, the light stays off ass long as the person is in the room.
If the person overrides the PIR and switches the light on, the light stays on ass long as the person is in the room AND stays on for an additional time (for example 1 hour) when he leaves the room.
If it gets dark (LDR sensor) AND there is someone in the room (PIR sensor) the light (LED) will switch on.
If someone is in the room, he can overrule condition nr. 1 and forge the light to go OFF or ON with a button --> if someone is in the room AND button is pressed the light will be forged to the opposite of the current status.
If the light is forged ON by hand (button) AND there is no one in the room for one hour, the light will switch off.
Wherein I didn't succeed:
If a shadow passes in front of the LDR sensor (for example a cloud in front of the sun), the light shouldn't switch OFF and ON all the time. There should be some delay or smoothing on it.
I tried to solve condition 4 with a for loop. Problem is, I want to make a buffer of 10 minutes and when the code is in the for loop... It is stuck for 10 minutes to receive any code
Has someone an idea to solve this problem?
// constants those won't change. They're used here to set pin numbers:
const int PIRPin = 6;Â Â Â // the number of the pessence sensor pin
const int buttonPin = 7;Â Â // the number of the pushbutton pin
const int LDRPin = A0;Â Â Â // select the analog input pin for ldr
const int ledPin1 = 13;Â Â Â // the number of the Blue LED pin
const int ledPin2 = 12;Â Â Â // the number of the Green LED pin
const int ledPin3 = 11;Â Â Â // the number of the Red LED pin
const int ledPin4 = 10;Â Â Â // the number of the X LED pin*/
//Variables will change
boolean ledVal1 = false; // state of LED 1
boolean ledVal2 = false; // state of LED 2
boolean ledVal3 = false; // state of LED 3
boolean ledVal4 = false; // state of LED 4
boolean OverRule = false; // has automation been overruled by user?
unsigned long previousMillis = 0;Â Â Â Â // will store last time LED was updated
int LDRValue = digitalRead(LDRPin);Â Â Â Â // will store LDR value (analog)
int b;
//=================================================
void setup()
{
 // Set input pins
 pinMode(buttonPin, INPUT);
 digitalWrite(buttonPin, HIGH );
 pinMode(PIRPin, INPUT);
 // Set output pins
 pinMode(ledPin1, OUTPUT);
 digitalWrite(ledPin1, ledVal1);
 pinMode(ledPin2, OUTPUT);
 digitalWrite(ledPin2, ledVal2);
 pinMode(ledPin3, OUTPUT);
 digitalWrite(ledPin3, ledVal3);
 pinMode(ledPin4, OUTPUT);
 digitalWrite(ledPin4, ledVal4);
 Serial.begin(9600);  //sets serial port for communication
}
void loop()
{
 unsigned long currentMillis = millis();
 // Get button event and act accordingly
 b = checkButton();
 if (b == 1) {
  OverRule = !OverRule;
  //Serial.println(OverRule);
  clickEvent();
  previousMillis = currentMillis; // reset the counter during absence
 }
 if (b == 2) {
  OverRule = !OverRule;
  //Serial.println(OverRule);
  doubleClickEvent();
  previousMillis = currentMillis; // reset the counter during absence
 }
 if (b == 3) {
  OverRule = !OverRule;
  //Serial.println(OverRule);
  holdEvent();
  previousMillis = currentMillis; // reset the counter during absence
 }
 //if (b == 4) {OverRule != OverRule; longHoldEvent();} //event 3 is always triggerd along when triggering event 4
 //home automation depending on light level and pressence of people
 Serial.println(LDRValue);
 if (OverRule == false) {
  if (digitalRead(PIRPin) == HIGH) {
   previousMillis = currentMillis; // reset the counter during absence
   if (LDRValue < 750) { //setting a threshold value
    // turn LED on:
    digitalWrite(ledPin1, HIGH);
   } else if (LDRValue > 850) {
    // turn LED off:
    digitalWrite(ledPin1, LOW);
   }
  } else {
   //Serial.println(currentMillis - previousMillis);
   if (currentMillis - previousMillis > 10000) { //if there is no one in the room for a certain time
    digitalWrite(ledPin1, LOW); // the light turns off
    previousMillis = currentMillis; // reset the counter
   }
  }
 }
 //LDRValue = getLight(10,60000); // read the value from the sensor
 LDRValue = digitalRead(LDRPin);
 if (OverRule == true && digitalRead(PIRPin) == HIGH) {
  previousMillis = currentMillis; // reset the counter during absence
 } else if (OverRule == true && digitalRead(PIRPin) == LOW) {
  //Serial.println(currentMillis - previousMillis);
  if (currentMillis - previousMillis > 10000) { //if there is no one in the room for a certain time
   digitalWrite(ledPin1, LOW); // the light turns off
   OverRule = false;
   previousMillis = currentMillis; // reset the counter
  }
 }
}
//=================================================
// Events to trigger by click and press+hold
void clickEvent() {
 ledVal1 = digitalRead(ledPin1);
 ledVal1 = !ledVal1;
 digitalWrite(ledPin1, ledVal1);
}
void doubleClickEvent() {
 ledVal2 = !ledVal2;
 digitalWrite(ledPin2, ledVal2);
}
void holdEvent() {
 ledVal3 = !ledVal3;
 digitalWrite(ledPin3, ledVal3);
}
void longHoldEvent() {
 ledVal4 = !ledVal4;
 digitalWrite(ledPin4, ledVal4);
}
/*
 MULTI-CLICK: One Button, Multiple Events
 Oct 12, 2009
 Run checkButton() to retrieve a button event:
 Click
 Double-Click
 Hold
 Long Hold
*/
// Button timing variables
int debounce = 20; // ms debounce period to prevent flickering when pressing or releasing the button
int DCgap = 250; // max ms between clicks for a double click event
int holdTime = 2000; // ms hold period: how long to wait for press+hold event
int longHoldTime = 5000; // ms long hold period: how long to wait for press+hold event
// Other button variables
boolean buttonVal = LOW; // value read from button
boolean buttonLast = LOW; // buffered value of the button's previous state
boolean DCwaiting = false; // whether we're waiting for a double click (down)
boolean DConUp = false; // whether to register a double click on next release, or whether to wait and click
boolean singleOK = true; // whether it's OK to do a single click
long downTime = -1; // time the button was pressed down
long upTime = -1; // time the button was released
boolean ignoreUp = false; // whether to ignore the button release because the click+hold was triggered
boolean waitForUp = false; // when held, whether to wait for the up event
boolean holdEventPast = false; // whether or not the hold event happened already
boolean longHoldEventPast = false;// whether or not the long hold event happened already
int checkButton() {
 int event = 0;
 // Read the state of the button
 buttonVal = digitalRead(buttonPin);
 // Button pressed down
 if (buttonVal == HIGH && buttonLast == LOW && (millis() - upTime) > debounce) {
  downTime = millis();
  ignoreUp = false;
  waitForUp = false;
  singleOK = true;
  holdEventPast = false;
  longHoldEventPast = false;
  if ((millis() - upTime) < DCgap && DConUp == false && DCwaiting == true) DConUp = true;
  else DConUp = false;
  DCwaiting = false;
 }
 // Button released
 else if (buttonVal == LOW && buttonLast == HIGH && (millis() - downTime) > debounce) {
  if (not ignoreUp) {
   upTime = millis();
   if (DConUp == false) DCwaiting = true;
   else {
    event = 2;
    DConUp = false;
    DCwaiting = false;
    singleOK = false;
   }
  }
 }
 // Test for normal click event: DCgap expired
 if ( buttonVal == LOW && (millis() - upTime) >= DCgap && DCwaiting == true && DConUp == false && singleOK == true) {
  event = 1;
  DCwaiting = false;
 }
 // Test for hold
 if (buttonVal == HIGH && (millis() - downTime) >= holdTime) {
  // Trigger "normal" hold
  if (not holdEventPast) {
   event = 3;
   waitForUp = true;
   ignoreUp = true;
   DConUp = false;
   DCwaiting = false;
   //downTime = millis();
   holdEventPast = true;
  }
  // Trigger "long" hold
  if ((millis() - downTime) >= longHoldTime) {
   if (not longHoldEventPast) {
    event = 4;
    longHoldEventPast = true;
   }
  }
 }
 buttonLast = buttonVal;
 return event;
}
//
int getLight(int samples, int sampleInterval) {
 //int samples = 8;
 //int sampleInterval = 50;
 unsigned long Vorig = 0;
 int sampleData[samples];
 int light = 0;
 /*for (int i = 0; i < samples; i++) {
   sampleData[i] = analogRead(LDRPin);
   light = light + sampleData[i];
   delay(sampleInterval);
  }*/
 int i = 0;
 while (i < samples) {
  if (millis() - Vorig >= sampleInterval) {
   Vorig = millis();
   sampleData[i] = analogRead(LDRPin);
   light = light + sampleData[i];
   i++;
  }
 }
 light = (light / samples);
 //light = map(light, 0, 1023, 100, 0);
 return light;
}
I tried to solve condition 4 with a for loop. Problem is, I want to make a buffer of 10 minutes and when the code is in the for loop... It is stuck for 10 minutes to receive any code
Don't do that.
On every pass through loop(), see if it is time to take another reading. Once a minute is often enough.
If it is, take a reading, and store it in the next position in the array. Average the readings. Deal with the average reading, not any instantaneous readings.
You'll need two indexes into the array - one to define where to write and one to define the last used position in the array. Both index values start at 0. The first one increments to the length of the array minus 1, and then resets to 0. The second one increments to the length of the array minus 1, and then stays there.
The first index defines where to write. The second defines how many values are in the array. The average is based on the number of elements in the array, NOT the length of the array.