Simple run on timer sketch (delay causing me headaches!)

Hi Guys, I'm trying to make a real simple sketch as a simple run on timer to keep power on my raspberry pi as it shuts down, the input comes from a 5v relay on the TVs USB port and the output is a 5v relay interrupting the Pi's USB power from a PSU. My TV turns itself off when the pi shuts down but I want to be sure the pi has a clean shutdown before it looses power therefore am not sure just putting a relay inline would be a great idea!

the correct sketch plan; when pin 10 reads high pin 12 goes low when pin 10 reads low there is a delay then pin 12 goes high

I've written the code below and it kind of works BUT the delay occurs before the power up and after so currently it does this; when pin 10 reads high there is a delay then pin 12 goes low when pin 10 reads low there is a delay then pin 12 goes high

How can I remove the delay before pin 12 goes low?

/*
Pi Power Sketch

TMS 2/12/2013

*/

//variables
const int tvPin = 10;     // 0v from Voltage detection relay
const int outPin =  12;      // 0v output to relay 2
int tvPowerState = 0;         // variable for reading the TV power status

//Setup
void setup() {
  // initialise the TV pin as an input:
  pinMode(tvPin, INPUT);      
  // initialise the Relay output pin as an output:
  pinMode(outPin, OUTPUT);   
 // initialise relay start as HIGH (off)
  digitalWrite(outPin, HIGH);
}

//Loop
void loop(){
  // read the state of the input relay:
  tvPowerState = digitalRead(tvPin);

  // check if the voltage is detected.
  // if it is, the outpin is LOW:
  if (tvPowerState == HIGH) {     
    // turn relay 2 on (LOW):    
    digitalWrite(outPin, LOW);  
  } 
  else {
    // Pause for 1 minute.
    // turn relay 2 off (HIGH).
    delay(3000);
    digitalWrite(outPin, HIGH); 
  }
}

Thanks so much for your time!

I'm sorry to bump this but can anyone help, I'm sure its something simple!

I'm no longer interrupting the USB to switch the pi instead I'll send the output to the GPIO on the pi!

I’ve written the code below and it kind of works BUT the delay occurs before the power up and after so currently it does this;
when pin 10 reads high there is a delay then pin 12 goes low
when pin 10 reads low there is a delay then pin 12 goes high

No, this is not what happens.

When pin 10 does not read HIGH, there is a 3 second delay before you read the pin again.

oh ok thanks, how can I stop this?

I suspect that you need to look at the state change detection example. It is not the state of the tvPin that is of explicit interest. It is a change in the state of the pin that is of interest.

This lends itself to a state machine. A state diagram is attached.
Once the state diagram is verified the code almost writes itself when using my state machine library found here:
http://playground.arduino.cc/Code/SMlib
instructions for installing libraries are here: http://arduino.cc/en/Guide/Libraries

#include <SM.h>

SM piCtrl (powerSave);
const int tvPin = 10;// 0v from Voltage detection relay
const int outPin =  12;// 0v output to relay 2
const unsigned long offDelay = 60*1000;//1 min

void setup(){
  pinMode(tvPin, INPUT); // initialise the TV pin as an input     
  pinMode(outPin, OUTPUT);// initialise the Relay output pin as an output
  digitalWrite(outPin, HIGH);// initialise relay start as HIGH (off)
}//()

void loop(){
  EXEC(piCtrl);
}//()

State powerSave(){
  digitalWrite(outPin, HIGH);// initialise relay start as HIGH (off)
  if(digitalRead(tvPin)) piCtrl.Set(powerOn);
}//powerSave()

State powerOn(){
  digitalWrite(outPin, 0);//low level means power on
  if(!digitalRead(tvPin)) piCtrl.Set(Wait);
}//powerOn()

State Wait(){
  if(piCtrl.Timeout(offDelay)) piCtrl.Set(powerSave);
}//Wait()

tv power save state diagram.png

That is bloody excellent, Thank you so much it works a treat!

I am planning on doing some C++ training so I can get much better at this and although I understand what is going on in your sketch I cannot add an extra element in the correct place which is a shame!

If you don't mind helping me further what I'd love would be able to add a step to the power off sequence where at the beginning of the delay time pin 8 goes high for a second before going low again, I will run a python script on the Pi to monitor this and shut itself down when that pin goes high!

Tim

Ok. In return you do some reading on state machines. ok?

#include <SM.h>

SM piCtrl (powerSave);
const int signalPin = 8;
const int tvPin = 10;// 0v from Voltage detection relay
const int outPin =  12;// 0v output to relay 2
const unsigned long offDelay = 60*1000;//1 min
const unsigned long signalDelay = 1000;//1s

void setup(){
  pinMode(signalPin, OUTPUT);
  pinMode(tvPin, INPUT); // initialise the TV pin as an input     
  pinMode(outPin, OUTPUT);// initialise the Relay output pin as an output
  digitalWrite(outPin, HIGH);// initialise relay start as HIGH (off)
}//()

void loop(){
  EXEC(piCtrl);
}//()

State powerSave(){
  digitalWrite(outPin, HIGH);// initialise relay start as HIGH (off)
  if(digitalRead(tvPin)) piCtrl.Set(powerOn);
}//powerSave()

State powerOn(){
  digitalWrite(outPin, 0);//low level means power on
  if(!digitalRead(tvPin)) piCtrl.Set(signal);
}//powerOn()

State signal(){
  digitalWrite(signalPin, 1);
  if(piCtrl.Timeout(signalDelay)) piCtrl.Set(Wait);
}

State Wait(){
  digitalWrite(signalPin, 0);
  if(piCtrl.Timeout(offDelay)) piCtrl.Set(powerSave);
}//Wait()

Another cool thing would be using a gpio pin on the raspberry to signal to the arduino thats it is finished powering down and replace the 1 min wait with that signal

tv power save signal state diagram.png