NEC infrared remote

I see jmknapp has posted his setup for controlling RC5 compliant IR devices…
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1209565937
…so I just had to post my very similar setup for controlling NEC-compliant equipment.

I won’t bother uploading a picture because my setup is basically exactly the same as jmknapps; one single IR-led to send the signal.

The code is where the magic is done:

int irPin = 13;
int data[32];
int val;
int timeout = 0;

void setup()
{
  pinMode(irPin, OUTPUT);
  Serial.begin(115200);
  Serial.println("System ready!");
}

void loop()
{

  if(Serial.available())
  {
    //get and decode first byte
    val = Serial.read();
    Serial.print("Byte1: ");
    Serial.println(val);
    makedata(val, 0);
  
    //get and decode second byte
    timeout = millis();
    while(!Serial.available() && millis() < timeout + 100) {}
    if(Serial.available())
    {
      val = Serial.read();
      Serial.print("Byte2: ");
      Serial.println(val);
      makedata(val, 16);
    }
    
    //send preamble
    oscWrite(irPin, 8000);
    delayMicroseconds(4000);

    //send data
    for(int i = 0; i < 32; i++)
    {
      //space
      oscWrite(irPin, 560);
      
      //data
      if(data[i] == '0')
      {
        delayMicroseconds(565);
        Serial.print('0');
      }
      else
      {
        delayMicroseconds(1690);
        Serial.print('1');
      }
    }
    Serial.println();
    oscWrite(irPin, 560);
  }
}

void oscWrite(int pin, int time)
{
  for(int i = 0; i < (time / 26) - 1; i++)
  {
    digitalWrite(pin, HIGH);
    delayMicroseconds(13);
    digitalWrite(pin, LOW);
    delayMicroseconds(13);
  }
}

void makedata(double foo, int ofs)
{
  for(int i = 0; i < 8; i++)
  {
    data[i + ofs] = '0';
    data[i + ofs + 8] = '0';
    if(foo / 2 > floor(foo / 2))
    {
      data[i + ofs] = '1';
    }
    else
    {
      data[i + ofs + 8] = '1';
    }
    foo = floor(foo / 2);
  }
}

Basically, the NEC protocol works as follows:

  1. an 8000us modulated pulse* is sent
  2. the signal is cut off for 4000us
  3. 8-bit device code is sent, followed by the inverted device code(0=1, 1=0).
  4. 8-bit command is sent, followed by the inverted command.

For the device- and command-codes, each bit is transmitted as a 560us pulse ON, followed by a 565us pulse OFF for a “0” or a 1690us pulse OFF for a “1”.

The Arduino waits for serial data to become available, and decodes the first byte recieved into binary and it’s inverted equivalent and puts it into the first 16 bits of the data-array. Then it fetches another byte and does the same filling out the next 16 bits.

Once that is done, it simply sends the headers and loops through the data-array sending the 0’s and 1’s.

For control, I have made a crude Visual Basic program to act as a web-to-arduino proxy and a php frontend. I had to try my way through the diffrent codes to figure out what they did, but beware! In the first 127 codes I twice encountered codes that instantly set the volume to max! Retarded if you ask me, except for perhaps building an IR-gun hard-coded with this code and shooting in peoples windows. ::slight_smile:

*modulated pulse: a signal turned on and off roughly 38.000 times pr second.