CountDown Timer When PIR detects Movement (Auto TV shutoff Movement Sensor)

Hello Everyone :slight_smile:

I'm trying to put together a sketch for an Auto TV shutoff Movement Sensor. Got 4 boys and they are ALWAYS LEAVING THEIR TVs ON :0
Ive had no trouble coding a few of my other projects but i cant for the life of me figure this one out.
I'm great with electronic engineering but a terrible coder.

Id even offer $10us through paypal for a perfectly working sketch! (no joke)

Parts
Atmega328
PIR Sensor (INPUT) (unit automatically gives out HIGH for 5sec when it detects movement, then goes back LOW)
LED (OUTPUT)
Piezo Buzzer (OUTPUT)
IR Emitter (OUTPUT) i already have this all figured out using IRremote Library
plus Components to put it all together (id be glad to show the schematic once i get the code working)

How To Use

Device powered directly from USB behind TV
After a set time(I'm thinking 30min) of no movement in the room.
Triggers IR Emitter to send Off Command to TV (As to shut it down Properly, not just trigger a relay killing the power)
Everytime there's movement, simply restarts the timer.
Once TV is off, it also powers off the Device.

Ive done many tests with the PIR sensor and it works very well detecting minute movement. (like scratching your nose or moving an arm on the couch)

How id like the code to work

Unit powers on with TV
Everytime PIR (input) senses movement it restarts a timer. Lets Say 30min (this will happen over and over until everyone leaves the room)
When timer reaches 5min, Blink LED (don't stop until timer reaches zero)
When timer Reaches 1min, ring for 500ms off and on 5 times.

When timer reaches zero, Let me use my code to initiate IR off Command.

Would be great if code DIDNT USE "delay" as to tie up any other code id like to add on.
Also, if this is even possible, not have it tie up TIMER 2

Looking forward to some of your thoughts and (hoping) help!

Thanks you
Eric

This seems like an incredibly easy program to write. The power up part is handled by the TV's USB supplying, or not, power.

You seem to already know how to read the PIS sensor. Adding a variable, of type unsigned long, called then, valued by a call to millis() when the sensor detects motion is trivial.

On every pass through loop, value another unsigned long variable called now. In a if statement if(now - then > interval), where interval is 25 minutes, have some more code that determines if it is time to toggle the LED state.

Another if statement, where interval is 30 minutes, contains code to turn the TV off, resulting in loss of power to the Arduino, shutting it down.

Thanks for the reply
I just cant wrap my head around how to code resetting the clock every time there is movement

I just cant wrap my head around how to code resetting the clock every time there is movement

if (movement) { 
  lastTime = millis();
}

Here's what i have so far for testing

Problem is with

  if(now - start > warning) 
  {
    digitalWrite(ledPin, HIGH);
  }

warning = 5sec

as soon as the device turns on the LED turn on with it
now if i reverse with (start - now > warning)
The LED comes up after 5 sec the way i want it to

it seems backwards to me. Can someone explain why?

Thanks for the tip AWOL.
I may be doing it wrong as when movement happens it doesn't reset the LED (maybe because the LED isisnt working right to begin with)

Here's the code

int ledPin=12;
int pir=2;
unsigned long start;
unsigned long now;
int movement=0;

long warning = 5000;        // Warning...5second test
long kill = 10000;          // Time To Kill 10second test


void setup() {
  Serial.begin(9600);
  pinMode(pir, INPUT);
  pinMode(ledPin, OUTPUT);
}

void loop() {
  Serial.print("start: ");
  movement=digitalRead(pir);
  start = millis();


  if(now - start > warning) 
  {
    digitalWrite(ledPin, HIGH);
  }

  if(movement)
  {
    start = millis();
  }

}
  start = millis();


  if(now - start > warning) 
  {
    digitalWrite(ledPin, HIGH);
  }

start should only be assigned a new value when there is movement, so the first line needs to go. The rest of this snippet needs to be moved after the if statement that followed it.

And, now needs to be assigned a value on every pass through loop().

Guys,
I cant thank you enough on pointing me in the right directions. You were very courteous and fast on giving help. (how do i give you karma?!)
Great learning experience for me.
Initial test sketch is now running beautifully. :slight_smile:

Any tips on how well the code is written?
I cant yet differentiate between long unnecessary "Frankenstein" code or clean code.

Here's the working test script if interested.

int ledPin=12;
int pir=2;
unsigned long start;
unsigned long now;
int movement=0;

long warning = 8000;        // Warning...8second test
long kill = 10000;          // Time To Kill 10second test


void setup() {
  Serial.begin(9600);
  pinMode(pir, INPUT);
  pinMode(ledPin, OUTPUT);
}

void loop() {
  
  movement=digitalRead(pir);

  if(movement)
  {
    Serial.print("Movement!!");
    digitalWrite(ledPin, LOW);
    start = millis();
  } 
  now=millis();
  if(now - start > warning) 
  {
    digitalWrite(ledPin, HIGH);
    Serial.print("WARNING");
  }



}

Any tips on how well the code is written?

void loop() {
  
  movement=digitalRead(pir);

  if(movement)
  {
    Serial.print("Movement!!");
    digitalWrite(ledPin, LOW);
    start = millis();
  } 
  now=millis();
  if(now - start > warning) 
  {

You are using two different conventions for where the { goes. Pick one (where the { goes on a new line) and stick with it.

The blank line at the start of loop() is distracting.

The if(movement) block expresses a thought. If should follow immediately after movement is valued. There should be a blank line between that if block and the code that follows it.

Blank lines between ending one block and ending another are like blank pages in a book. You wonder why the publisher put them there. Trying to increase page count is all I can figure. Don't do that.

On the other hand, the choice of variable names is pretty good. The code is logically arranged. And, best of all, it does what you want (so far). It is a good foundation on which to build.

The only variable name that could be improved is start. What is that the start of? lastMovement might be a better choice. Keep in mind that you are going to have another start time - the time the LED started flashing. Giving start a better name now will encourage you to give the other start variable a name that is better than start2.

I really got some very useful hints for my project too from this discussion

Thanks a lot..