Wifi connected Motion Sensor

Hi all,

Received my Spark Core yesterday with the intention of creating a motion sensor that I can use along side my Philips Hue Lighting Setup to turn off the lights in my room after it has been empty for a short amount of time.

Hardware:
Using 2 Parallax PIR sensors + a spark core.

Software:
Using a PHP library for my Philips Hue that I am in the process of creating.
https://github.com/markp1989/HuePhpLibrary

Code that is running on the Spark.

/*
Using Parallax PIR sensor 
*/


int interval = 600000;  //600 seconds

//both these vars are set to volatile because they will be changed when there is an interupt  
volatile boolean motion = false; 
volatile unsigned long lastmotiontime = 0; 



boolean currentMotion = false; //variable that is going to be available through the spark api a nonvolatile var is required


void setup(){
  Serial.begin(9600); 
    Spark.variable("motion", &currentMotion , BOOLEAN);
    //pinMode(pirPin, INPUT);
    delay(30000); 
    Serial.println("setup has completed"); 
  
  
  //attaching interrupt pins for both my motion sensors. 
  attachInterrupt(A0, motionInterupt, RISING);
  attachInterrupt(A1, motionInterupt, RISING);

}

void loop(){
  noInterrupts();
  unsigned long currentMillis = millis();
   //as I intend to have this on at all times adding in a catch for when the millis() function overflows.  
  if (currentMillis < lastmotiontime){ 
    lastmotiontime = 0 ; 
    motion = false; 
  } 
  
 
  //reseting motion variable if no motion has been detected in a while 
  if (motion & (currentMillis - lastmotiontime   > interval)){
    Serial.print("no motion since ");
    Serial.print(lastmotiontime);
    Serial.println(" resetting state..........");   
    motion = false; 
  }
  interrupts();
  
  
  currentMotion = motion;  //store the current state in a non volatile variable - for access from spark.variable 

  delay(10); 
}

void motionInterupt(){
  motion=true;  
  lastmotiontime = millis(); 
}

PHP Script Running on Home Server:
This script is called by Cron every 10minutes, does a few things:

    • Adjusts the colour temperature of light to mimic natural sunlight
    • Detects if the room is empty (using spark) and turns off the lights
    • Will only do this if there is no content being played on the HTPC

This is the important bit for this part of the project which uses the spark API to read the “currentMotion” variable from the core:

    $content = file_get_contents("https://api.spark.io/v1/devices/DEVID/motion?access_token=ACCESSTOKEN");
    if (empty($content)) {
        echo "catch if the motion sensor doesnt responde" . PHP_EOL;
    } else {
        $content = json_decode($content, true);
        $roomEmpty = $content["result"];
        if (!$roomEmpty) {
            echo "the room is currently empty turning lights off. " . PHP_EOL;
            $this->ph->on(false);
            $this->ph->sendCommands();
            return;
        }
    }

This is the full “Natural Light” Script

<?php

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 * Description of naturalLight
 * 
 * This is mainly written for my own personal use, for a natural light script 
 * see the  original "natural light" file. 
 *
 * Does everything that the original natural light file did, but adds a couple
 * of extra features:
 * 
 * Description of naturalLight
 * Sets a colour temperature to be similar to that of natural light
 * 2500k at sun rise, gradually getting up to 6500k at midday
 * then back to 2500k again at night. 
 *
 * to be ran like : 
 * $nl = new naturalLight();
 * $hour =  date('G');
 * $min = date('i');
 * $nl->setLights($hour,$min);
 * 
 * Currenly sun rise and sun set times need to be set manually  
 * Currently working: 
 *          Only change the light temperature if there is nothing playing on XBMC.  
 * 
 * Planned: 
 *          Turn the lights off if there is nobody in the room. 
 * 
 * @author Mark
 */
include_once "PhilipsHue.php";
include_once "xbmc.php";

class naturalLight {

  
    private $sunrise = 7;
    private $sunriseMin = 30;

    private $midDay = 18;
    private $midDayMin = 30;
    
    
    //10:30 pm 
    private $sunset = 22;
    private $sunsetMin = 30;
    
    
    // reference color temperatures. 
    private $SunRiseSet = 2500;
    private $Noon = 6500;
    private $xbmcSettings = array('host' => 'markhtpc.local', 'port' => '8080', 'user' => 'xbmc', 'pass' => 'xbmc');
    // -----------------------END OF configurable settings ----------------------------------------------------------


    private $ph;

    function __construct() {
        $this->sunrise = ($this->sunrise * 3600) + ($this->sunriseMin * 60);
        $this->sunset = ($this->sunset * 3600) + ($this->sunsetMin * 60 );
        $this->midDay = ($this->midDay * 3600) + ($this->midDayMin * 60 );


        $this->ph = new PhilipsHue();
        //$this->ph->setup();
        //$this->dayLength = $this->sunset - $this->sunrise;
        //$this->midDay = ($this->sunrise + $this->sunset) / 2;
        //  echo "mid day is $this->midDay" . PHP_EOL;
    }

    /* input time in 24 hour format and any lights that are currently on 
     * will be set to the colour temperature representing the time between sunset. 
     */

    function setLights($hours, $mins, $roomEmpty = false) {
        $this->ph->refreshLights(); //ensure that we have the latest state of the lights
        /* if none of the lights are on just exit the function. */
        if (!$this->ph->isOn()) {
            echo "no lights are on! " . PHP_EOL;
            return;
        }

        /* detect if any of the lights are in XY 
         * color mode and exit if they are
         */
        $this->ph->refreshLights(); //ensure that we have the latest state of the lights
        $modes = $this->ph->readModes();
        print_r($modes);
        if ($modes['XY'] > 0) {
            echo "Lights are in a unsupported mode! " . PHP_EOL;
            return;
        }

        /* Dont do anythign to the lights if there is something playing on the
         * xbmc box. 
         */
        try {
            $xbmcHost = new xbmcHost($this->xbmcSettings);
            $xbmcJSON = new xbmcJson($xbmcHost);
            $activePLayers = $xbmcJSON->Player->GetActivePlayers();
            //dont change the lights if the media center is playing!!
            if (!empty($activePLayers)) {
                echo "Something is playing on the HTPC" . PHP_EOL;
                return;
            }
        } catch (Exception $e) {
            echo 'Caught exception: ', $e->getMessage(), "\n";
        }
        $this->ph->refreshLights(); //ensure that we have the latest state of the lights

        /* turn of the lights if the room is empty
         * waiting for the Spark Core to be delivered 
         * so I can create a motion sensor. 
         */
        $content = file_get_contents("https://api.spark.io/v1/devices/DEVID/motion?access_token=ACCESSTOKEN");
        if (empty($content)) {
            echo "catch if the motion sensor doesnt responde" . PHP_EOL;
        } else {
            $content = json_decode($content, true);
            $roomEmpty = $content["result"];
            if (!$roomEmpty) {
                echo "the room is currently empty turning lights off. " . PHP_EOL;
                $this->ph->on(false);
                $this->ph->sendCommands();
                return;
            }
        }

        $this->ph->refreshLights(); //ensure that we have the latest state of the lights
        $birghtness = (int) $this->ph->getAvgBrightness();
        
        //convert time to sec Since midnight. 
        $time = ($hours * 60 * 60) + ($mins * 60);
        
        //if sun is not up yet. 
        if ($time < $this->sunrise) {
            echo "sun is not up yet" . PHP_EOL;
            $time = $this->sunrise;
        }

        //if sun has already set. 
        if ($time > $this->sunset) {
            echo "sun has already set" . PHP_EOL;
            $time = $this->sunset;
        }

        //if before mid day 
        if ($time < $this->midDay) {
            //NewValue = (((OldValue - OldMin) * (NewMax - NewMin)) / (OldMax - OldMin)) + NewMin
            $temperature = (int) ((($time - $this->sunrise) * ($this->Noon - $this->SunRiseSet)) / ($this->midDay - $this->sunrise)) + $this->SunRiseSet;
        } else {
            //NewValue = (((OldValue - OldMin) * (NewMax - NewMin)) / (OldMax - OldMin)) + NewMin
            $temperature = (int) ((( $time - $this->midDay) * ( $this->SunRiseSet - $this->Noon )) / ( $this->sunset - $this->midDay )) + $this->Noon;
            //  echo "temperature  is  $temperature , time is $time" . PHP_EOL;
        }

        $this->ph->alert("all", "none");
        $this->ph->setColorTemp("all", $temperature, $birghtness, 100);
        $this->ph->sendCommands();
    }

}

?>

So far performance is what I have expected from the project, after leaving the room I come back to find the room is dark :slight_smile: , A few things I want to improve are:

  1. get a decent project case for this setup.
  2. find a good placement for it to cover most of the room - yesterday when in bed on laptop the room went dark because i was not in front of asensor.
  3. make is so that both PIR sensors are facing in different directions as currently they are just stuck on a bread board.
  4. remove the blue-tack from the LED and dim it in software.

Photos

6 Likes

mark​p​1989, great project! Thanks for sharing it with us. :smile:

Just a note, the pictures at the bottom did not post properly.

I fixed the images… one of them wouldn’t load at all though… cool project!

1 Like

Thanks for fixing the photos for me, one of them wouldn’t load because i deleted the file from Dropbox because it was blurry.

since the post yesterday I have manually changed the RGB led so it doesn’t light up the complete room, and have connected the PIR sensors to 3.3v output instead of the VIN pin.

I may decided to power it from batteries in the future, currently I am using my kindle charger because of the long cable length, if I decide to power it from batteries I have to worry about putting the Spark to sleep and other power concerns, does anyone know how Spark.variables function with the device in sleep mode?

Im debating wether I should alter the PHP script so it turns on the lights when motion is detected, but I have a feeling that may be more annoying than convenient.

Glad I found your project. I just purchased my spark for a very similar project. I want to use motion sensors placed under my bed to turn on a Hue light when I get out of bed in the middle of the night. Then turn off once there is no motion.

Hopefully, I’ll get a soft glowing light that will be enough illumination to navigate the room but not so much that it disturbs my wife. I plan to mount the PIR sensors under bed so that they can sense movement at about calf height but not triggered if I’m just reading in bed.

I look forward to your progress.

How much current does this sort of thing draw?
I ask this as I am wondering if it can it be used as part of a home security system. I would want to be able to power it from say 3xAA’s but I would not want to be recharging them too often, say once a year tops.

@Gizmo take a look at @wgbartley’s post on battery life using deep sleep:

Hi @markp1989

In the code I can see you have called two functions noInterrupts() and interrupts() inside loop(). But I can’t find the definition for these two functions.

Thanks

@bijay, these functions are in the Core firmware: http://docs.spark.io/firmware/#interrupts-interrupts :smile:

2 Likes

Thanks @peekay123