Now for the code controlling the whole thing:
/**
* Add a remote control to an ASUS Monitor
* Uses Power & Volume buttons from a standard Sony TV remote
*/
#include <EEPROM.h>
//CONSTANTS
#define btnPower 149
#define btnMute 148
#define btnDown 147
#define btnUp 146
#define rate 4
#define start_bit 2000 //Start bit threshold (Microseconds)
#define bin_1 1000 //Binary 1 threshold (Microseconds)
#define bin_0 400 //Binary 0 threshold (Microseconds)
#define ir_pin 2 //Sensor pin 1 wired through a 220 ohm resistor
#define led_pin 13 //"Ready to Recieve" flag, not needed but nice
#define debug 0 //Serial connection must be started to debug
//VARIABLES
long timer = -5000;
int i = 0; //general purpose counter
int wait = 20;
void setup() {
pinMode(6, OUTPUT); //Push button when Volume-down detected
pinMode(7, OUTPUT); //Push button when Volume-up detected
pinMode(8, OUTPUT); //Push when Power detected
pinMode(led_pin, OUTPUT); //This shows when we're ready to recieve
pinMode(ir_pin, INPUT);
digitalWrite(led_pin, LOW); //not ready yet
timer = -5000; // used for volume up command
}
void loop() {
//Fetch the key
int key = getIRKey();
switch (key) {
case btnPower:
digitalWrite(8, HIGH);
delay (500); //Debounce switch
digitalWrite(8, LOW);
timer = -5000;
break;
case btnDown:
digitalWrite(6, HIGH);
delay(wait);
digitalWrite(6, LOW);
timer = millis(); //reset timer to now
break;
case btnUp:
if ((millis() - timer) >= 3500){ // activate volume instead of default brightness setting for vol + button.
digitalWrite(6, HIGH);
delay(wait);
digitalWrite(6, LOW);
delay(wait);
}
digitalWrite(7, HIGH);
delay(wait);
digitalWrite(7, LOW);
timer = millis(); //reset timer to now
break;
default:
digitalWrite(8, LOW);
digitalWrite(6, LOW);
digitalWrite(7, LOW);
}
}
int getIRKey() {
int data[12];
digitalWrite(led_pin, HIGH); //Ok, i'm ready to recieve
while(pulseIn(ir_pin, LOW) < 2200) {
//Wait for a start bit
return -1; //clear out old codes
}
for(i=0;i<11;i++){
data[i] = pulseIn(ir_pin, LOW); //Start measuring bits, I only want low pulses
}
digitalWrite(led_pin, LOW);
if(debug == 1) {
//Serial.println("-----");
}
for(int i=0;i<11;i++) { //Parse them
if (debug == 1) {
//Serial.println(data[i]);
}
if(data[i] > bin_1) { //is it a 1?
data[i] = 1;
} else {
if(data[i] > bin_0) { //is it a 0?
data[i] = 0;
} else {
data[i] = 2; //Flag the data as invalid; I don't know what it is!
}
}
}
for(i=0;i<11;i++) { //Pre-check data for errors
if(data[i] > 1) {
return -1; //Return -1 on invalid data
}
}
int result = 0;
int seed = 1;
for(int i=0;i<11;i++) { //Convert bits to integer
if(data[i] == 1) {
result += seed;
}
seed = seed * 2;
}
return result; //Return key number
}
One tricky part for this code is that the monitor uses the same buttons for both volume and brightness. If you press the Vol (+) button first, it will do brightness, not volume (goofy design if you ask me). What I did to counter this, is if more than a few seconds have gone by, and you press the Vol (+) button on the remote, the Arduino will send one Vol (-) command before sending the Vol (+) commands - this is enough to get the monitor into volume mode first before increasing volume.
This code was modified from the link referenced in the first post. Thanks to all of the resources listed on top - they were all very helpful.
The monitor now works just as if it were a Sony TV (well at least for Power, Volume Up, and Volume Down). The wife is very happy.