Search This Blog

Showing posts with label Sleep. Show all posts
Showing posts with label Sleep. Show all posts

Saturday, October 2, 2010

Arduino IR remote TV sleep timer setter

Now that this project is finally up and running in field trials, I'm finally going to write it up.

The purpose of this project is automatically turn on the sleep timer of the television.

Story: My wife is an insomniac and stays up late every night watching TV.  She eventually falls asleep and leaves the TV on.  She NEVER remembers to set the sleep timer, plus the TiVo remote doesn't allow setting the TV sleep timer, and who knows where the original TV remote is most of the time.   We have DirecTV, and about 3 or 4 in the morning they do a download.  The TV goes black and quiet for a while, then comes back to life when the download is done.  This wakes me up every night and i have to get out of bed and turn off the TV because my wife as fallen asleep and lost the remote in the bed somewhere.   Arrrgh!

How it works:  Based on an Arduino board, it has an IR receiver ripped from an old broken TV, and an IR diode from a remote from a TV we don't have anymore.  The device sits on the TV stand, directly in front of the TV. When it detects IR traffic from the remote, it keeps resetting a timer.  If the timer expires, it assumes that the user has fallen asleep and is no longer controlling the TV.  The device then sends a remote control to the TV to set the sleep timer.   If the user doesn't notice (they are likely asleep), the sleep timer counts down and shuts off the TV.  You might ask why don't I just send a power command?  Problem is I can't really be sure the TV is on or off.  What if she actually turned the TV off before falling asleep.  It would be a disaster to have the device turn ON the TV.  Using the sleep timer is the perfect fail safe.  If the TV is off, the sleep command does nothing .  If the TV is on, it will count down and turn off.  Just takes a little longer than turning it off directly.

We have a SONY Bravia TV and use a DirecTV TiVo box primarily.  This works for those devices.  You will have to modify for your devices.

Arduino TV IR sleeper

The project is constructed of:
Connections:
The IR receivers have three pins.  Signal, Gnd, 5V.  I attached it to pin 9
int RECV_PIN = 9;                //IR detector module attached here
int led_green = 11; //led to indicate TV on & IR activity flickers green.  Connect the same way as the IR diode, but use a 2.2K resistor in series instead
int led_yellow = 13;          //led to indicated TV user is drowsy.  Same as led_green.

IR wiring
thanks to http://www.arcfn.com/2009/08/multi-protocol-infrared-remote-library.html for this drawing

I used the prototype shield, which is probably overkill but made a nice compact unit.  I bent the receiver and yellow/green LEDs so they pointed towards the user.  The IR tx diode is mounted on the back edge and points towards the TV.  I put on a reset switch because it is always nice to have a wave to recover.

This project proved way more difficult than i expected.  The device is both a reciever and a transmitter, and needed to detect IR transmission as an interrupt because I was running a timer from last activity.  Combining these three functions was tricky.  There was an IR library on Arduino playground http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1176098434 ,  that was based on delay(),.  The receiver worked just fine, but the transmitter failed to control the TV.  I experimented for hours and finally discovered that the timing of the bits in the Arduino were off.  I had to set the times much shorter than the spec, because the Arduino was timer and interrupts were slowing things down.  In the process of debugging and googling help, the http://www.arcfn.com/2009/08/multi-protocol-infrared-remote-library.html library bubbled up through google and i downloaded it.  This is much more solid and uses the PWM as the timing reference for transmit, so the TV liked it.  Luckily it supports the same devices that I had in my home, so I used it almost unmodified.   I had further troubles with the sending routine stopping the receiving routine, which the author admits to in his blog comments.  All you have to do is restart the receiver after you have transmitted.  I had further troubles with ambient IR triggering the receiver, and had to add a code filter to ignore anything that doesn't match a valid IR code from either the TiVo (NEC codes) or Sony.

So here is the code I ended up with.  you need to download the IR library and put it in your libraries folder.
This code has debugging to the serial monitor included, which helps you understand what is happening.

Code follows....

Monday, September 27, 2010

Got the IR TV sleep timer setter code working!

Rewrote my code using the libraries from this blog:
http://www.arcfn.com/2009/08/multi-protocol-infrared-remote-library.html

After a little stumble with a == instead of a =, i got the first version running.  Now the IR
receiver doesn't block the code execution and I can run a timer marking when the last IR event
happened.  Also this code seems to see just about any IR activity, not just the Sony.

Feel bad that i haven't taken the time to understand what he did, just borrowed it.

This guy has also a bunch of stuff on IR remotes and interrupts too, didn't use it but wanted to note it.
http://minkbot.blogspot.com/2009/08/arduino-ir-receiver-with-interrupts.html

I wrote the code as a simple state machine (my background as a RTL designer is showing).  There are three states.  TV_OFF, TV_ON, DROWSY.    It stays in TV_OFF unless the IR activity sends it to TV_ON.  It starts a timer and kicks back to TV_ON every time the IR remote is detected.  If the timer times out without any IR activity, it moves to DROWSY.  DROWSY sends the sleep command to the TV and starts a timer.  If the timer expires, it assumes the TV sleep timer turned off the TV and goes to TV_OFF.  Any IR activity moves you back to TV_ON.  DROWSY state isn't absolutely necessary, but it prevents sending sleep again too soon and extending the sleep timer time.

Now to clean up the hardware in a more permanent form and write it up for the next post!

Sunday, September 26, 2010

Back working on the Arduino IR TV sleep timer setter

Now that the GPS is working, i'm back working on a project that stalled.

This project has an IR receiver that looks for any traffic, from multiple remotes.  Point is not to decode them, just to detect them.   A timer runs and if no traffic has been seen for a set time (say 1/2 hour) it sends via an IR diode a sleep timer set code for the TV.  The device is placed in front of the TV where it will see the IR remote and be able to send a code to the TV out the back.   The point is that when someone is watching, they skip commercials, change volume, channel, etc.  When they fall asleep they stop using the remote.  If we mess up and accidentally set the sleep timer on an awake user, so what.  They will notice.

I had been using code from the Arduino playground and successfully detected Sony remote codes at just bout 100% accuracy.
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1176098434
I had some trouble sending the same codes to the TV.  There were two problems.  First the bit order was opposite what i thought, and I think the code on the website was not symmetrical.  After printing the codes out I figured that out.  More vexing however was that the TV ignored the codes I sent.  I tried several Sony TVs.  Luckily the TV I want to use is a Sony, which has easier codes.   I discovered after playing a long while, and looking at the time measurements of the real IR remote versus what I was sending (this took two Arduinos with the same hardware) that my pulses were longer than the real remote.  The real remote times were much less than the spec times of 600us and 1200us .  I think the clock in the Arduinos are off.  By changing the bit transmit times in the code to what i measured, I got the TV to respond.  That took a while to sort out.  However this varies Arduino to Arduino, so you have to tweak the times to the specific Arduino.  Disappointing but I'll live.

The problem that finally stalled me, was that the Arduino IR remote code is using a pulse measurement command and a while loop. 



while(pulseIn(ir_pin, LOW) < 2200) { //Wait for a start bit

} data[0] = pulseIn(ir_pin, LOW);


Problem is that I want a timer to increment, and this command uses up the whole of the Arduino's attention.  Additionally it is reliable with only Sony remotes, but remember i want to notice codes from a variety of remotes.   The 2000us pulse width doesn't apply to the other protocols and doesn't work reliably.

Whoa! ... a google search just turned up this blog, which is much more professional than mine, and has a lot of useful information.   Early posts point to the code i had been using.

http://www.arcfn.com/2009/08/multi-protocol-infrared-remote-library.html
http://www.arduino.cc/playground/Code/InfraredReceivers

Alright.  Off to lick this problem with some new code!!