/*

* Good Dog / Bad Dog

* © 2010 Rob Gonsalves

* http://www.robgon.com/Details.aspx?work=good_dog

*

* Arduino control code

* Released under Creative Commons Attribution-NonCommercial-ShareAlike 2.0 Generic License

* http://creativecommons.org/licenses/by-nc-sa/2.0/

*

** This uses PIRsense by: Kristian Gohlke

* http://www.arduino.cc/playground/Code/PIRsense

*o:p>

* And timing code by Handi

* http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1214336737

*

*/

 

#include <avr/interrupt.h >

#include <avr/io.h >

 

#define INIT_TIMER_COUNT 0

#define RESET_TIMER2 TCNT2 = INIT_TIMER_COUNT

 

#define DURATION 5

 

int int_counter = 0;

int show_halo = 0;

int show_horns = 0;

int count_down = 0;

int show_lights = 0;

 

//the time we give the sensor to calibrate (10-60 secs according to the datasheet)

int calibrationTime = 30;       

 

//the time when the sensor outputs a low impulse

long unsigned int lowIn;

 

int use_comm = 1;

 

int light1Pin = 2;

int light2Pin = 3;

int pirPin = 8;

int ledPin = 13;

 

//the amount of milliseconds the sensor has to be low

//before we assume all motion has stopped

long unsigned int pause = 5000; 

 

boolean lockLow = true;

boolean takeLowTime; 

 

// Arduino runs at 16 Mhz, so we have 61 Overflows per second...

// 1/ ((16000000 / 1024) / 256) = 1 / 61

ISR(TIMER2_OVF_vect)

{

    int_counter += 1;

    if (int_counter == 61)

    {

        int_counter = 0;

 

        doTimer();

    }

};

 

void setup()

{

    if (use_comm)

    {

        Serial.begin(9600);

        Serial.println("Initializing Haloween 2010");

    }

 

    randomSeed(analogRead(0));

 

    //Timer2 Settings:  Timer Prescaler /1024

    TCCR2B |= ((1 << CS22) | (1 << CS21) | (1 << CS20));

 

    //Timer2 Overflow Interrupt Enable

    TIMSK2 |= (1 << TOIE2);

 

    RESET_TIMER2;

 

    sei();

 

    pinMode(light1Pin, OUTPUT);

    pinMode(light2Pin, OUTPUT);

    pinMode(pirPin, INPUT);

    digitalWrite(pirPin, LOW);

    pinMode(ledPin, OUTPUT);

 

    //give the sensor some time to calibrate

    if (use_comm)

        Serial.print("calibrating sensor ");

       

    for(int i = 0; i < calibrationTime; i++)

    {

        if (use_comm)

            Serial.print(".");

        //delay(1000);

    }

   

    if (use_comm)

    {

        Serial.println(" done");

        Serial.println("SENSOR ACTIVE");

    }

    delay(50);

}

 

void turn_on_light()

{

    if (show_halo == 1)

    {

        show_horns = 0;

        digitalWrite(light1Pin, HIGH);

        digitalWrite(light2Pin, LOW);

        if (use_comm)

            Serial.println("horns on");

    }

    else

    {

        show_horns = 1;

        show_halo = 0;

        digitalWrite(light1Pin, LOW);

        digitalWrite(light2Pin, HIGH);

        if (use_comm)

            Serial.println("halo on");

    }

}

 

void doTimer()

{

    if (count_down > 0)

    {

        count_down--;

        if (use_comm)

            Serial.println(count_down);

 

        if (count_down == 0)

        {

            if (show_lights > 1)

            {

                show_lights = 1;

                count_down = DURATION;

 

                show_halo = !show_halo;

                show_horns = !show_horns;

 

                turn_on_light();

            }

            else

            {

                show_lights = 0;

                show_halo = 0;

                show_horns = 0;

                digitalWrite(2, LOW);

                digitalWrite(3, LOW);

                if (use_comm)

                    Serial.println("both off");

            }

        }

    }

}

 

void loop()

{

    //int val = digitalRead(4);

    //int light_sensor_1 = analogRead(0);

    int trigger = 0;

    //Serial.print("light level 1 = ");

    //Serial.println(light_sensor_1);

    //light_sensor_1 > 1015 to trigger

 

    if(digitalRead(pirPin) == HIGH)

    {

        digitalWrite(ledPin, HIGH);   //the led visualizes the sensors output pin state

        trigger = true;

           

        if(lockLow)

        { 

            //makes sure we wait for a transition to LOW before any further output is made:

            lockLow = false;   

           

            if (use_comm)

                {  

                Serial.println("---");

                Serial.print("motion detected at ");

                Serial.print(millis()/1000);

                Serial.println(" sec");

                }

               

            delay(50);

        }

 

        takeLowTime = true;

    }

 

    if(digitalRead(pirPin) == LOW)

    {      

        digitalWrite(ledPin, LOW);  //the led visualizes the sensors output pin state

 

        if(takeLowTime)

        {

            lowIn = millis();          //save the time of the transition from high to LOW

            takeLowTime = false;       //make sure this is only done at the start of a LOW phase

        }

        //if the sensor is low for more than the given pause,

        //we assume that no more motion is going to happen

        if(!lockLow && millis() - lowIn > pause)

        { 

            //makes sure this block of code is only executed again after

            //a new motion sequence has been detected

            lockLow = true;  

           

            if (use_comm)

                {    

                Serial.print("motion ended at ");      //output

                Serial.print((millis() - pause)/1000);

                Serial.println(" sec");

                }

                

            delay(50);

        }

    }

 

    if (trigger && count_down != DURATION)

    {

        trigger = false;

        if (show_lights == 0)

        {

            if (use_comm)

                Serial.println("first trigger");

               

            show_lights = 1;

            count_down = DURATION;

            show_halo = random(2);

 

            turn_on_light();

        }

        else if (show_lights == 1)

        {

            if (use_comm)

                Serial.println("second trigger");

               

            show_lights = 2;

        }

    }

}