PIR Sensor for Energy-Saving HVAC Control

Project Overview

This project creates an energy-saving HVAC control system that automatically adjusts temperature settings based on room occupancy. When a room is occupied, the system maintains normal temperature; when the room is empty for a set period, it enters an energy-saving mode with a temperature setback. This can reduce heating and cooling costs by 10-20% annually.

Difficulty: Intermediate
Estimated time: 3-4 hours
Estimated cost: $30-50

How It Works

PIR sensors placed in key rooms detect occupancy. When no motion is detected for a set period (e.g., 30 minutes), the system sends a signal to the HVAC system to adjust the temperature setpoint (higher for cooling, lower for heating). When occupancy is detected again, the system returns to the normal setpoint. Multiple sensors can be networked for whole-home occupancy tracking.

This project assumes you have a smart thermostat with API access (Nest, Ecobee) or an HVAC system with remote control capability.

Materials Needed

  • ESP32 or ESP8266 (1)
  • HC-SR501 PIR sensors (1-5, depending on rooms)
  • Jumper wires
  • Power supply (5V 2A)
  • Project enclosure
  • Smart thermostat with API (Nest, Ecobee, or Home Assistant)

Thermostat Compatibility

This project can integrate with various smart thermostats:

  • Nest Thermostat: Use Google Nest API or Home Assistant integration.
  • Ecobee: Use Ecobee API.
  • Home Assistant: If you have a local Home Assistant instance, use its API to control any connected thermostat.
  • IR-controlled AC units: Add an IR LED to control mini-split AC systems.

This tutorial uses Home Assistant as the central controller for simplicity.

Home Assistant Setup

  1. Install Home Assistant on a Raspberry Pi or server.
  2. Add your thermostat integration (Nest, Ecobee, etc.).
  3. Note the entity ID for your thermostat (e.g., climate.living_room).
  4. Enable the ESPHome integration for the PIR sensors.

ESPHome Configuration for PIR Sensors

# ESPHome configuration for multiple PIR sensors
esphome:
  name: occupancy_sensors

esp32:
  board: esp32dev

# Wi-Fi configuration
wifi:
  ssid: "YourWiFiSSID"
  password: "YourWiFiPassword"
  fast_connect: true

# API for Home Assistant
api:
  password: "YourAPIPassword"

ota:
  password: "YourOTAPassword"

# Binary sensors for each PIR
binary_sensor:
  - platform: gpio
    pin: GPIO4
    name: "Living Room Motion"
    device_class: motion
    filters:
      - delayed_on: 100ms
      - delayed_off: 60000ms  # Stay on for 1 minute after last motion
    
  - platform: gpio
    pin: GPIO5
    name: "Bedroom Motion"
    device_class: motion
    filters:
      - delayed_on: 100ms
      - delayed_off: 60000ms
    
  - platform: gpio
    pin: GPIO6
    name: "Kitchen Motion"
    device_class: motion
    filters:
      - delayed_on: 100ms
      - delayed_off: 60000ms

Home Assistant Automations

Create the following automations in Home Assistant:

Automation 1: Enter Away Mode When No Motion

# configuration.yaml or via UI
automation:
  - alias: "HVAC - Enter Away Mode"
    trigger:
      - platform: state
        entity_id: 
          - binary_sensor.living_room_motion
          - binary_sensor.bedroom_motion
          - binary_sensor.kitchen_motion
        to: "off"
        for: "00:30:00"  # 30 minutes of no motion
    condition:
      - condition: state
        entity_id: binary_sensor.house_occupied
        state: "on"
    action:
      - service: climate.set_temperature
        target:
          entity_id: climate.main_thermostat
        data:
          temperature: 62  # Heating setback
          hvac_mode: heat
      - service: input_boolean.turn_off
        target:
          entity_id: input_boolean.house_occupied

Automation 2: Return to Normal Mode When Motion Detected

automation:
  - alias: "HVAC - Return to Normal"
    trigger:
      - platform: state
        entity_id: 
          - binary_sensor.living_room_motion
          - binary_sensor.bedroom_motion
          - binary_sensor.kitchen_motion
        to: "on"
    condition:
      - condition: state
        entity_id: binary_sensor.house_occupied
        state: "off"
    action:
      - service: climate.set_temperature
        target:
          entity_id: climate.main_thermostat
        data:
          temperature: 68  # Normal heating temperature
      - service: input_boolean.turn_on
        target:
          entity_id: input_boolean.house_occupied

Input Boolean for Occupancy Status

input_boolean:
  house_occupied:
    name: House Occupied
    initial: true
    icon: mdi:home

Arduino Code (Standalone Version without Home Assistant)

If you don’t have Home Assistant, you can use an ESP32 to control a relay that directly interfaces with a simple thermostat:

// Standalone HVAC Controller with PIR
#include <WiFi.h>

const int pirPin = 4;
const int relayPin = 5;  // Controls setback circuit

// Wi-Fi for logging (optional)
const char* ssid = "YourWiFiSSID";
const char* password = "YourWiFiPassword";

unsigned long lastMotionTime = 0;
const unsigned long setbackDelay = 1800000; // 30 minutes
bool inSetback = false;

void setup() {
  Serial.begin(115200);
  pinMode(pirPin, INPUT);
  pinMode(relayPin, OUTPUT);
  digitalWrite(relayPin, LOW);  // Normal mode (relay off)
  
  WiFi.begin(ssid, password);
  delay(60000); // PIR warm-up
}

void loop() {
  bool motion = digitalRead(pirPin) == HIGH;
  
  if (motion) {
    lastMotionTime = millis();
    if (inSetback) {
      // Return to normal mode
      digitalWrite(relayPin, LOW);
      inSetback = false;
      Serial.println("Motion detected - returning to normal mode");
    }
  }
  
  if (!inSetback && (millis() - lastMotionTime > setbackDelay)) {
    // Enter setback mode
    digitalWrite(relayPin, HIGH);
    inSetback = true;
    Serial.println("No motion - entering setback mode");
  }
  
  delay(100);
}

Multiple Room Occupancy Tracking

For whole-house control, create a template sensor that aggregates all PIR sensors:

# template.yaml
template:
  - binary_sensor:
      - name: "Any Motion"
        state: >
          {{ is_state('binary_sensor.living_room_motion', 'on') or
             is_state('binary_sensor.bedroom_motion', 'on') or
             is_state('binary_sensor.kitchen_motion', 'on') }}
        delay_off:
          minutes: 30

Installation Steps

  1. Place PIR sensors: Position sensors in key rooms (living room, bedrooms, kitchen) at 2m height, covering main activity areas.
  2. Connect sensors to ESP32: Wire sensors with long cables if needed.
  3. Configure Home Assistant: Add ESPHome integration and thermostat.
  4. Create automations: Add occupancy-based setback rules.
  5. Test: Verify system enters setback after no motion and returns when motion detected.
  6. Adjust timing: Set setback delay to avoid short cycling (30 minutes is typical).

Energy Savings Calculation

According to DOE, setting thermostats back 7-10°F for 8 hours per day can save 10% on heating and cooling costs. This system can achieve similar savings by automatically managing setbacks based on actual occupancy.

Project Extensions

  • Room-level zoning: Use motorized dampers to heat/cool only occupied rooms.
  • Geofencing integration: Combine with phone location for even better occupancy detection.
  • Window sensors: Add window contact sensors to disable HVAC when windows are open.
  • Energy monitoring: Track energy usage and savings over time.
  • Voice control: Use Alexa/Google to check occupancy status and adjust temperature.

Troubleshooting

  • System enters setback while occupied: Increase motion detection range. Ensure sensors cover all activity areas. Increase setback delay time.
  • System doesn’t return from setback: Check PIR sensors are detecting motion. Verify wiring.
  • Too frequent cycling: Increase setback delay. Add delay_off filter in ESPHome.
  • No connection to thermostat: Check Home Assistant integration and API credentials.

Conclusion

This occupancy-based HVAC control system automatically reduces energy waste when rooms are empty, lowering utility bills without sacrificing comfort. With proper installation, it can pay for itself within one heating or cooling season.

Leave a Reply

Your email address will not be published. Required fields are marked *