Occupancy Based Energy Saving Device using PIR Motion Sensor

SUMMARY

This project uses the HC-SR504 PIR Motion sensor to detect the presence of people in a room and automatically switches a connected load on or off. You can connect any load to it, for instance, an Air conditioner.

ABOUT

Category:  Arduino

Difficulty:  Intermediate

Submitted by: Isaac

Date: 4th February, 2018

STORY

A lot of energy is lost due to people leaving devices and appliances on when they shouldn’t be. In homes and offices, we sometimes forget to turn off our lights, fans and air conditioners when we leave a room, leading to wastage of energy. This project helps you save energy by automatically turning connected devices on or off depending on the occupancy of the room.

For example, if you connect this device to your AC, if you forget to turn your AC off and leave the room, it will automatically turn the AC off after a while. When you come back to your room and your presence is detected, the AC will automatically turn back on.

OVERVIEW

This project uses the HC-SR504 PIR Motion sensor to detect the presence of people in a room and automatically switches a connected load on or off. You can connect any load to it, for instance, an Air conditioner.

When the motion sensor detects that there is someone in the room, it first checks if the connected load is on. If the load is on, it takes no action. If the load is off, it triggers a countdown timer. After the countdown timer finishes counting, it turns the load on.

Alternatively, when the motion sensor detects that there is no one in the room, it first checks to see if the connected load is off. IF the load is off, the device takes no action. However, if the device is on, it triggers a countdown timer which counts down from 5 minutes. After the countdown has elapsed, if no occupant is detected, the device turns off the load.

DETAILS

Components Used

  • Arduino Pro Mini Microcontroller
  • HC-SR504 PIR Motion Sensor
  • 5V Relay
  • Active Buzzer
  • Perforated Circuit Board
  • RGB Light Emitting Diode
  • Green Light Emitting Diode
  • Digital Energy Meter
  • On/Off Rocker Switch
  • Terminal Blocks
  • Resistors (100ohms – 1, 1kohms – 1)
  • Connecting wires
  • Override switch
  • 12V Power supply
  • Female power port
  • Screws

Tools and Materials Used

  1. Soldering Iron
  2. Soldering Lead

Block Diagram

How It Works

The same signal pin of PIR motion sensor is connected to the two interrupt pins (pin 2 and pin 3) on the Arduino microcontroller. One of the interrupt pins is set to trigger on the RISING signal edge (LOW to HIGH) . This means the interrupt is triggered when the sensor detects motion while previously in a LOW state.

The other interrupt pin is set to trigger on the FALLING signal edge (HIGH to LOW) . This means the interrupt is triggered when the sensor stops detecting motion while previously in a HIGH state.

The PIR motion sensor is in a HIGH state when it has detected motion and a LOW state when it stops detecting motion. Using interrupts means that we don’t have to keep polling the signal pin of the PIR motion sensor to see whether motion has been detected or not.

Read about interrupts here.

Depending on which interrupt is triggered, one of two functions are called; the checkRelayStatusOFF() function or the checkRelayStatusON() function.

Let’s take a few scenarios.

SCENARIO 1. Someone enters a room which previously had no occupants.

The PIR sensor data out pin goes from LOW to HIGH, triggering the RISING edge interrupt. This, in turn, calls the checkRelayStatusON() function which checks if the relay which switches on the load is already on. If it is already on, the device does nothing. However, if it is off, the startOnDelayTimer() function is called.

This starts an on-delay countdown timer which counts down to zero. Once the timer reaches zero, the switchRelayON() function is called which switches on the relay and the connected load comes on.

If the sensor stops detecting motion while the timer is counting down, if the sensor stops detecting motion after a number of seconds (which can be set from the potentiometer on the motion sensor) it resets the timer and everything goes back to normal.

SCENARIO 2. The last person leaves the room and forgets to turn off the connected appliance (Load).

The PIR sensor data out pin goes from HIGH to LOW, triggering the FALLING edge interrupt. This, in turn, calls the checkRelayStatusOFF() function which checks if the relay which switches off the load is already off. If it is already off, the device does nothing. However, if it is on, the startOffDelayTimer() function is called.

This starts a 5 minute off-delay countdown timer which counts down to zero. Once the timer reaches zero, the switchRelayOFF() function is called which switches on the relay and the connected load goes off.

While counting down, the buzzer will beep every 30 seconds.

The RGB LED has 3 status indicators.

When the system is loading, the LED will turn blue. When motion is detected, it will turn red and when no motion is detected, it will turn green.

If the sensor detects motion, while the timer is counting down, the system resets and the and everything goes back to normal. The

Logic/Flow Chart

Fritzing Circuit

Arduino Code

 

 

/*
 * HERE IS HOW THE CODE WORKS/IS SUPPOSED TO WORK.
 * When the PIR sensor goes from Low to High or High to low, it triggers one of two interrupts
 * meant to detected a rising (low to high) or falling (high to low) edge.
 * 
 * When low to high interrupt is triggered, it calls the calls the checkRelayStatusON function which checks if the relay is off. 
 * If relay is off, it starts the onDelay countdown timer. If it is on, it does nothing.
 * 
 * Why calls the calls the checkRelayStatusOFF function which checks if the relay is on. 
 * If relay is off, it starts the oFFDelay countdown timer. If it is off, it does nothing.
 * 
 * After the respective timers finish counting down, they call a function which either switches off the relay (offDelayTImer) 
 * or switches on the relay(onDelayTimer)
  */

#include "Countimer.h" //Countdown timer library

//VARIABLE DECLARATIONS
const byte buzzer =  7;
const byte relay = 8;
const byte bootingLed = 4;
const byte  detectedLed = 6;
const byte  notDetectedLed = 5;

//TIMER FOR BUZZER INTERVALS
unsigned long previousMillis = 0; 

const byte interruptPIRLow = 2; // Interrupt pin to trigger when motion sensor goes low
const byte interruptPIRHigh = 3; // Interrupt pin to trigger when motion sensor goes high

//TIMER BUZZES EVERY 30 SECONDS
const long INTERVAL = 30000;

Countimer onDelayTimer;  //Initialialize a new instance of the Countimer object for on-delay (delay before relay is turned on)
Countimer offDelayTimer; //Initialialize a new instance of the Countimer object for off-delay (delay before relay is turned off)

void counter();  
void bootSystem();   //Allows the PIR sensor sometime to boot up and start giving stable reading
void displayTimerCount();  //Displays current time left in the count down timer in serial monitor
void checkRelayStatus(); //Checks if relay is already on or off
void beepbuzzer(); //Beeps the buzzer
void switchRelayON();
void switchRelayOFF();

void setup(){
 
  Serial.begin(9600);
  pinMode(relay, OUTPUT);
  pinMode(bootingLed, OUTPUT);
  pinMode(detectedLed, OUTPUT);
  pinMode(notDetectedLed, OUTPUT);
  pinMode(buzzer, OUTPUT);
  pinMode(interruptPIRLow, INPUT_PULLUP);
  pinMode(interruptPIRHigh, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPIRLow), checkRelayStatusOFF, FALLING);  //Set an interrupt which is triggered when PIR sensor goes from High to low
  attachInterrupt(digitalPinToInterrupt(interruptPIRHigh), checkRelayStatusON, RISING); //Set an interrupt which is triggered when when PIR sensor goes from low to high

  onDelayTimer.setCounter(0, 0, 30, onDelayTimer.COUNT_DOWN, switchRelayON); //Set a 30 second countdown timer as a delay before switching on relay when motion is detected
  onDelayTimer.setInterval(displayOnDelayTimerCount, 1000);  //Display the time left in the countdown every 1 second

  offDelayTimer.setCounter(0, 5, 00, offDelayTimer.COUNT_DOWN, switchRelayOFF); //Set a 30 second countdown timer as a delay before switching off relay when no motion is detected
  offDelayTimer.setInterval(displayOffDelayTimerCount, 1000); //Display the time left in the countdown every 1 second
  
 bootSystem();  //Delay for 60 seconds to allow PIR sensor to start giving stable values
}

void loop(){
    unsigned long currentMillis = millis();
    onDelayTimer.run();  //Initialize the onDelayTimer function
  offDelayTimer.run(); //Initialize the offDelayTimer function

  if( !offDelayTimer.isCounterCompleted()){ 

    if (currentMillis - previousMillis >= INTERVAL) {
    previousMillis = currentMillis;
    digitalWrite(buzzer, HIGH);
    delay(500);
    digitalWrite(buzzer, LOW);
  }

  }
}

//BOOT THE SYSTEM
void bootSystem(){
  Serial.println("System is booting...Wait for 1 minute");
  digitalWrite(bootingLed, HIGH);  //Turn booting LED (blue LED) on while system is booting
  delay(10000);
  digitalWrite(bootingLed, LOW);
    digitalWrite(notDetectedLed, HIGH);   //Turn NOT Dected LED on (red led) after system finished booting
    Serial.println("Booting Complete...");

}

/* =====================================================================
 CHECK IF THE RELAY IS ON AND START ON-DELAY COUNTDOWN TIMER IF IT ISNT.
 ======================================================================*/
void checkRelayStatusON(){
  Serial.println("Motion Detected. Low To High Interrupt Triggered");
  digitalWrite(notDetectedLed, LOW);
  digitalWrite(detectedLed, HIGH);

  //CHECK IF OFF-DELAY COUNTDOWN TIMER WAS RUNNING WHILE MOTION WAS DETECTED AND STOP IT 
  if(!offDelayTimer.isCounterCompleted()){ 
    Serial.println("Stopping OFF Delay Timer now...");
    offDelayTimer.stop();  //STOP THE OFF DELAY TIMER
    if(offDelayTimer.isStopped()){
      Serial.println("Successfully Stopped OFF delay Timer");
    }
    else{
      Serial.println("Error Stopping Off-Delay Timer");
    }
  }

  //CHECK IF THE RELAY IS OFF AND TURN IT ON IF IT ISNT
  if(digitalRead(relay)==LOW){
     Serial.println("checkRelayStatusON Results: Relay is OFF...");
    startOnDelayTimer();
  }
  else{
      Serial.println("checkRelayStatusON Results: Relay is on ON... No further action");
  }
}

//CHECK IF THE RELAY IS OFF AND START OFF DELAY COUNTDOWN TIMER IF IT ISNT.
void checkRelayStatusOFF(){
  Serial.println("Motion Not Detected Anymore. High to low Interrupt Triggered");
  digitalWrite(detectedLed, LOW);
  digitalWrite(notDetectedLed, HIGH);

    //CHECK IF ON-DELAY COUNTDOWN TIMER WAS RUNNING WHILE MOTION WAS NOT DETECTED ANYMORE AND STOP IT 
  if(!onDelayTimer.isCounterCompleted()){ 
    Serial.println("Stopping ON Delay Timer now...");
    onDelayTimer.stop();  //STOP THE OFF DELAY TIMER
    if(onDelayTimer.isStopped()){
      Serial.println("Successfully Stopped ON delay Timer");
    }
    else{
      Serial.println("Error Stopping ON-Delay Timer");
    }
  }

  if(digitalRead(relay)==HIGH){
    Serial.println("checkRelayStatusOff Results: ON...");
    startOffDelayTimer();
  }
  else{
    Serial.println("checkRelayStatusOff Results: OFF...No further action");
  }
}

//START 15 SECOND ON DELAY COUNTDOWN TIMER AND TURN ON RELAY AFTER COUNTDOWN GOES TO ZERO
void startOnDelayTimer(){
  Serial.println("Starting OnDelay Timer...");
  digitalWrite(notDetectedLed, LOW); //Change LED statuses
  digitalWrite(detectedLed, HIGH);
  offDelayTimer.stop();
  onDelayTimer.start();
}

//START 30 SECOND OFF DELAY COUNTDOWN TIMER AND TURN OFF RELAY AFTER COUNTDOWN GOES TO ZERO
void startOffDelayTimer(){
  Serial.println("Starting OffDelay Timer...");
  digitalWrite(notDetectedLed, HIGH); //Change LED statuses
  digitalWrite(detectedLed, LOW);
  onDelayTimer.stop();
  offDelayTimer.start();
}

//SWITCH ON RELAY AFTER COUNTDOWN
void switchRelayON(){
  Serial.println("Turning relay on...");
  digitalWrite(relay, HIGH);
  if(digitalRead(relay)==HIGH){
    Serial.println("Relay successfully turned ON");
  }
  else{
     Serial.println("Switching ON relay FAILED...");
  }
}

//SWITCH OFF RELAY AFTER COUNTDOWN
void switchRelayOFF(){
  Serial.println("Turning relay off...");
  digitalWrite(relay, LOW);
    if(digitalRead(relay)==LOW){
    Serial.println("Relay successfully turned OFF");
  }
  else{
     Serial.println("Switching OFF relay FAILED...");
  }
}

//DISPLAY COUNTDOWN TIMER
void displayOnDelayTimerCount()
{
  Serial.print("Time To Switch On: ");
  Serial.println(onDelayTimer.getCurrentTime());
}

void displayOffDelayTimerCount()
{
  Serial.print("Time To Switch Off: ");
  Serial.println(offDelayTimer.getCurrentTime());
}

COMMENTS

This is the tutorials website for Invent Electronics. We are a top online retailer of electronics components, microcontrollers and sensors in Ghana. Besides providing customers with good quality electronic components we want to help them build great projects with the components they buy for us so we’ve put together a ton electronics resources, projects and tutorials on this site just for you!

Looking for electronic components to buy in Ghana?

Get all your sensors, electronic components, Arduinos, Raspberry Pi and other parts for your project at great prices from our online store.

Join Our Community

We’re more than just an electronics store. We are also a community of makers, engineers, enthusiasts and more. Join our community today, meet and learn from other people like you.