Pages: [1]   Go Down
Author Topic: NEC IR protocol  (Read 7180 times)
0 Members and 1 Guest are viewing this topic.
Tønsberg, Norway
Offline Offline
Full Member
***
Karma: 0
Posts: 148
Arduino rocks hard!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, I need your help! I know posts have been written about interfacing using modulated IR before but I can't remember anything covering the NEC protocol, just Sharp/Sony etc.

From what I managed to gather online, this is the code I have come up with:
Code:
int irPin = 13;
int data[32] = {0,0,0,1,1,1,0,0,1,1,1,0,0,0,1,1,1,0,1,0,1,0,0,0,0,1,0,1,0,1,1,1};
//int data[32] = {0,0,0,1,1,1,0,0,1,1,1,0,0,0,1,1,1,1,1,0,1,0,0,0,0,0,0,1,0,1,1,1};

void setup()
{
  pinMode(irPin, OUTPUT);
}

void loop()
{

  //send preamble
  oscWrite(irPin, 9000);
  delayMicroseconds(4500);
  
  //send data
  for(int i = 0; i < 32; i++)
  {
    //space
    oscWrite(irPin, 565);
    
    //data
    if(data[i] == 0)
    {
      delayMicroseconds(560);
    }
    else
    {
      delayMicroseconds(1690);
    }
    
  }
  oscWrite(irPin, 565);
  delay(500);
  
}

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

The data variable contains the signal for sending Mute to my tv and the commented data variable contains Volume Up. I found these by using an IR-demodulator to read the signals off of my remote so I know they should be good.

Still, it does nothing... During my testing the Mute-command worked twice, with no explanation for why! Also, I assume the carrier is good enough, since I wrote a program that uses oscWrite to output a continous carrier and that blocked the TV's remote completely.


Please help!
Logged

Dreaming of extra senses through sensory substitution/agumentation since.. well, for ever.. =P
Going to automate my home, just gotta find the perfect DIY solution first!

0
Offline Offline
Newbie
*
Karma: 0
Posts: 35
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

hmmmm.. i don't see "oscWrite" in the arduino reference.  What does it mean and where does it explain it in the reference here:  http://www.arduino.cc/en/Reference/HomePage
Logged

Tønsberg, Norway
Offline Offline
Full Member
***
Karma: 0
Posts: 148
Arduino rocks hard!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for the reply but did you read the code I posted? =P Hehe.

oscWrite is not in the refference because it doesn't exist. Or rather, I wrote it as you can see if you look at the code. =) It generates the 38KHz carrier needed to send info.
Logged

Dreaming of extra senses through sensory substitution/agumentation since.. well, for ever.. =P
Going to automate my home, just gotta find the perfect DIY solution first!

0
Offline Offline
Newbie
*
Karma: 0
Posts: 35
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

duhhhhhh i see it now.. i didn't then.. smiley

Logged

Tønsberg, Norway
Offline Offline
Full Member
***
Karma: 0
Posts: 148
Arduino rocks hard!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Not much interest for replacing countless remotes lying around with a central system controlled from a cellphone/bluetooth-device, it seems.. :'(

Something occurred to me yesterday.. Could my data simply be wrong? The fact that the mute-command worked twice (with a program that transmitted it every 500ms) is very strange. Also, I have researched the NEC-protocol even more and can't find anything wrong with my code. What I am thinking is that the device code (first 8 bits, next 8 bits is device code inverted) is simply wrong. Don't know how this could happen as I read it straight off my working remote but when I get home from work today I will make a program that tests all 256 possible device codes. Hope it works!
Logged

Dreaming of extra senses through sensory substitution/agumentation since.. well, for ever.. =P
Going to automate my home, just gotta find the perfect DIY solution first!

Tønsberg, Norway
Offline Offline
Full Member
***
Karma: 0
Posts: 148
Arduino rocks hard!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

There was surprisingly little interest in this topic but I will at least share the code I have now that I have finally gotten it to work. As far as I can see, the NEC-protocol works roughly as follows:

preamble:
8000us carrier ON
4000us OFF

device code:
8 bit code
8 bit code inverted (1 becomes 0, 0 becomes 1)

command code:
8 bit code
8 bit code inverted (1 becomes 0, 0 becomes 1)

560us carrier ON


For the data part, a 0 is transmitted as:
560us carrier ON
565us OFF

...and a 1 is transmitted as
560us carrier ON
1690us OFF

Here comes the code:
Code:
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);
  }
}

And here is a small list of the 256 possible device codes (the numbers are ASCII-codes):
Code:
56 = device code for our TV

0-9 = channel 0-9
10 = -- (2 digit channel)
12 = channel up
13 = channel down

17 = "normal" (set volume low)

20 = TV/AV
21 = mute
22 = volume up
23 = volume down
24 = OK
25 = menu (says "sleep", don't know what this is)
26 = menu - color

28 = power
29 = last channel (P<->P)
64 = mono/stereo
66 = menu - color
69 = on-screen clock
70 = text tv
75 = sound bass?
76 = on-screen clock
85 = sound bass?
125 = volum max?! RETARDEEEED!
128 = volum max?! RETARDEEEED!

I haven't gotten further than 128. It was getting late last night and when I stumbled onto those two codes that set the volume to max I decided to stop for the time beeing before my girlfriend decided to take a roller to the back of my head or something. -__-'


Anyways, I'm waiting for my internet hookup and my brand new HTC S730 phone. With this, I will make a smooth interface to control the arduino (and thus the TV, DVD-player, a couple of LED-bars and who knows what else). I can hardly wait! =D
Logged

Dreaming of extra senses through sensory substitution/agumentation since.. well, for ever.. =P
Going to automate my home, just gotta find the perfect DIY solution first!

0
Offline Offline
Newbie
*
Karma: 0
Posts: 37
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This really helped me out! Thanks!
I needed to shorten the timings a little to get it to look the same as my captured remote.

http://www.flickr.com/photos/matthewvenn/3452643310/
Logged

Tønsberg, Norway
Offline Offline
Full Member
***
Karma: 0
Posts: 148
Arduino rocks hard!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Nice! Good to be of service (and awesome that you mentioned me on your flicker site!) 8-)
Logged

Dreaming of extra senses through sensory substitution/agumentation since.. well, for ever.. =P
Going to automate my home, just gotta find the perfect DIY solution first!

taipei
Offline Offline
Newbie
*
Karma: 0
Posts: 20
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Plastbox,

Thanks for your share. I've borrowed your code and customize for BenQ MP612C Projector that speaks NEC IR protocol and it works fine.

here is my code:

Code:

#define TOPBIT 0x80000000
#define NEC_HDR_MARK      9000
#define NEC_HDR_SPACE     4500
#define NEC_BIT_MARK       560
#define NEC_ONE_SPACE     1690
#define NEC_ZERO_SPACE     560
#define NEC_BITS 32

#define DUTY_CYCLE         1/3       // Carrier duty cycle
#define PERIOD             26        // 38kHz, 1/38kHz =~ 26us
#define ACTIVE_HIGH       (PERIOD * DUTY_CYCLE)
#define ACTIVE_LOW        (PERIOD - (PERIOD * DUTY_CYCLE))

int IR_LED = 13;
unsigned long power = 0x000C40BF;    // BenQ Projector Power code

void setup()
{
  pinMode(IR_LED, OUTPUT);
}

void mark(long time)
{
  for(int i = 0; i < (time / PERIOD); i++)
  {
    digitalWrite(IR_LED, HIGH);
    delayMicroseconds(ACTIVE_HIGH - 4); // digitalWrite() takes 4us
    digitalWrite(IR_LED, LOW);
    delayMicroseconds(ACTIVE_LOW - 4); // digitalWrite() takes 4us
  }  
}

void sendNEC(unsigned long data)
{
    // Leader code
    mark(NEC_HDR_MARK);
    delayMicroseconds(NEC_HDR_SPACE);
  
    for (int i = 0; i < NEC_BITS; i++)
    {
      mark(NEC_BIT_MARK);
      if (data & TOPBIT)
        delayMicroseconds(NEC_ONE_SPACE);
      else
        delayMicroseconds(NEC_ZERO_SPACE);
  
      data <<=1;
    }
    
    // stop bit
    mark(NEC_BIT_MARK);
}  
  
void loop()
{  
  // send power IR signal to Projector every 5 seconds
  delay(5000);
  sendNEC(power);
}

Cooper Maa
Logged

My Arduino study notes:
http://coopermaa2nd.blogspot.com/

Cupertino, CA
Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Interesting (and surprisingly quiet) thread.  I'm curious to try playing with NEC IR codes, but don't know how to read the codes coming out of my remotes.  I can see the NEC-looking pulses on a 'scope, but I don't have an application to read them conveniently.

Did you ever write a matching Arduino program to dump NEC command messages to the serial port?  Or is there some software tool (hopefully compatible with OSX or Linux) that can do this?  With no way to read codes, there's no way to really try writing them...
Logged

Norway
Offline Offline
Sr. Member
****
Karma: 4
Posts: 423
microscopic quantum convulsions of space-time
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Use the excellent IRremote library from Ken Shirriff: http://www.arcfn.com/2009/08/multi-protocol-infrared-remote-library.html
He has several example programs incuded, that you can use to read the IR from one of the supported protocolls.
Logged

Pages: [1]   Go Up
Jump to: