Gadget Renesas

Linking Ideas and Electronics

GR Atelier

Title:Let's try the function on GR-KURUMI, outside interrupt vol.

Displayed Name:@chobichan

Let's try the function on GR-KURUMI, outside interrupt  vol.

Concept / Overview
GR-KURUMI can handle an interrupt with terminal 2 or 3, Let's try!
####

Remote controller haking with outside interrpt

The home appliance, infrared-rays remote controller transmit signals by modulation method in which it pause or resume ON/OFF signal of infrared LED or carrier wave. The frequency of carrier wave is approximately 38kHz.

Due to digital type, carrier wave is represented as bit stream with 0 or 1. Each bit consist of “having” or “not having” status of carrier wave, if “not having” time is equals with “having” one, 0 will show up, If “not having” time is three times as “having” one, 1 will show up.

 

 

 

 

As for time T, specified 0.56ms in NEC format, 0.4ms in AEHA format. Get ready receiver IC for infrared remote control instead of judging 0 or 1 sampling of 38kHz career wave by micro controller interruption.
http://akizukidenshi.com/catalog/g/gI-04659/

Resister IC can depict HIGH/LOW only depend on “having” or “not having” period of carrier wave. Based on this HIGH/LOW, bit conversion processing is required.

 

 

####

About NEC format

There are several schemes for coding of infrared remote controller. SONY, NEC, AEHA (Association for Electric Home Appliances) format are typical. 
※ Since I don’t have any home appliance with Sony format, we don’t care it this time.
Please refer to below URL for NEC format in details.
http://japan.renesas.com/support/faqs/faq_results/Q1000000-Q9999999/mpumcu/com/remo_012j.jsp

NEC format is user-friendly with the fixed frame-length at 32bit. However, it can handle data only up to 1byte. 
It’s not intended for home appliances use which is requiring complicated operation, but widely used for the ones with just simple work such as ceiling area lighting.

####

About AEHA format

On AEHA format, its frame-length is variable, can transmit data up to 10 byte. However handling is complicated.

Please refer to below URL which Akizuki posted in the public.
http://akizukidenshi.com/download/k4174_format.pdf
Also please refer to chan-san’s site.
http://elm-chan.org/docs/ir_format.html

Widely used for home appliance which is requiring intricate operation such as air conditioner.

####

About remote controller code

Though either NEC format or AEHA is standard specification, any home appliance manufacturers doesn’t disclose their remote control code. 

There are many users for electronic kit hacking on the infrared remote control. They analyze code by themselves and post it in the public on internet. 
http://japan.renesasrulz.com/gr_user_forum_japanese/b/webcompilerupdate/archive/2014/10/24/gr-kurum.aspx
Please refer to above URL for receiving infrared remote controller with GR-KURUMI. 

Without obtaining the remote controller code from manufacturer, matching data pattern receipt by micro controller with the button of remote controller, we can handle home appliances in our own way.
Called universal remote, just memorizing the pattern and sending it out, even custom code can be dealt with a series of data pattern, everything is going well.

※ Cut and try is indispensable?

####

Connection for remote controller signal reception

 

 

 

 

 

Referring the datasheet for receiver IC, let’s provide it with wiring.
Receiver IC is subject to noise due to its handling of week signal.

Get ready condenser etc. as specified.

IR_RECV is connected with terminal 2 on GR-KURUMI.

The oscilloscope shows the waves monitoring IR_RECV.

Using NEC format.

 

 

 

####

Program for remote controller signal reception

 

 

The output of receiver IC is connected with terminal 2. Record the every time for interrupt happen with handler registered on attachInterrupt, calculate interval time for interrupt, we can see the time for ON or OFF.

The duration time for the leader part may be helpful for the distinction of NEC from AEHA format. 
Those are big difference between two, NEC format is 13.5ms in total for ON/OFF. while AEHA format is 4.8ms.

Next, convert duration time for ON~ON into bit stream, save the data every 8 bit. 
The chart shows execution result.
NEC format is in LED lighting from IRIS OHYAMA.
AEHA format in AQUOS, sharp LCD TV.

 

Here is the sample code.

/*

Infra-red IR-remote capture program version 1.0
by Kaz Kinoshita, Insutitute of Daiichi Technologies
date of 2014-10-23

*/
/* ------------------------------------------------------------------------ */
/* 赤外線リモコンの受信をしてみる                  */
/*                                             designed by hamayan          */
/*                                             Copyright(C) hamayan         */
/*                                             since 2004 - 2016            */
/* ------------------------------------------------------------------------ */
#include  

#if !defined( _MULTITASK_H_ )
#define  dly_tsk(tim)  delay(tim)
#define  rot_rdq()
#define  loc_cpu()     interrupts()
#define  unl_cpu()     noInterrupts()
#endif /*_MULTITASK_H_ */

char *itoh( char *dst, unsigned int value );
void irRemocon_init( void );
void irRemocon_interrupt( void );
int  irRemocon_availableNEC( void );
int  irRemocon_availableAEHA( void );
int  irRemocon_rxNEC( byte dst[], int size );
int  irRemocon_rxAEHA( byte dst[], int size );
void IR_nec( void );
void IR_aeha( void );

#define  IR_RECV     2 // Ir RECEIVE
#define  IR_Pin      IR_RECV
#define  IR_CONT     3 // Ir LED ON/OFF
#define  IR_RECV_INT  0 // Ir RECEIVE interrupt number
#define  Max_IR_Bits 35
#define  Max_IR_Bits_AEHA 256
#define  HEADER_Low_min 8000UL
#define  Data_Low_min 200UL

unsigned long IR_Low_Time;    // holds IR bursting time
unsigned long IR_High_Time;   // holds IR high idling time
unsigned short IR_Data[Max_IR_Bits_AEHA] = {0,};  // holds the bit length of each data bit by micro-sec.
//unsigned long IR_Bits;   // 32 bits of IR data
int IR_State;
int IR_Active;       // when 1, the capturing IR data steam is valid
char IR_formatType;

void setup()
{
  Serial.begin( 9600 );
  Serial.println("IR remote control test.");
  attachInterrupt(IR_RECV_INT, irRemocon_interrupt, CHANGE);
  // 1 sets Pin 2 for interrupt with low/high-active edges

  while( 1 )
  {
    if( IR_Active == 1 )
    {
      if(IR_formatType == 'N') IR_nec();
      else if(IR_formatType == 'A') IR_aeha();
    }
  delay( 10UL );
  }
}

void loop()
{
}

char *itoh( char *dst, unsigned int value )
{
  sprintf( dst, "%02x", value );

  return dst;
}

/*************************************************************************/
/* IR_REMOCON初期化                                                      */
/*************************************************************************/
void irRemocon_init( void )
{
  IR_Low_Time = 0;    // holds IR bursting time
  IR_High_Time = 0;   // holds IR high idling time
  IR_Active = 0;       // when 1, the capturing IR data steam is valid
  IR_formatType = 0;
  IR_State = 0;
}

/*************************************************************************/
/* IR_REMOCON割り込み                                                    */
/*************************************************************************/
void irRemocon_interrupt( void )
{
  if(digitalRead(IR_Pin) == LOW)
  {
    if(IR_Active == 1)  //LOWからLOWまでの時間を計測して配列に保存する
    {
      if(IR_State < Max_IR_Bits_AEHA)
      {
        IR_Data[IR_State++] = (unsigned short)(micros() - IR_Low_Time);
      }
      else
      {
        irRemocon_init();
      }
    }
    IR_Low_Time = micros();
    return;
  }
  else
  {
    //IR_High_Time = micros();
    if(micros() - IR_Low_Time < Data_Low_min)  //LOWの期間が200μs以下をフィルターしている
    {
      IR_Active = 0;
      return;
    }

    unsigned long lTime = micros() - IR_Low_Time;
    if (lTime > HEADER_Low_min)  //LOWの期間が8000μsを超える場合はNECフォーマットだとしている
    {
      IR_Active = 1;
      IR_State = 0;
      IR_High_Time = millis();  //先頭フレームの後半の時間となる
      IR_formatType = 'N';
    }
    else if (lTime > 2500UL)  //LOWの期間が2500μsを超える場合は家製協(AEHA)フォーマットだとしている
    {
      IR_Active = 1;
      IR_State = 0;
      IR_High_Time = millis();  //先頭フレームの後半の時間となる
      IR_formatType = 'A';
    }
    else if (lTime > 2000UL)  //LOWの期間が2000μsを超える場合はSONYフォーマットだとしている
    {
      IR_Active = 1;
      IR_State = 0;
      IR_High_Time = millis();  //先頭フレームの後半の時間となる
      IR_formatType = 'S';
    }
  }
}

/*************************************************************************/
/* NECタイプのデータ数確認                                               */
/*************************************************************************/
int irRemocon_availableNEC( void )
{
  unsigned long hTime = millis() - IR_High_Time;
  //if (IR_Active == 1 && (IR_Data[IR_State] >= 10000 || IR_State >= 200 || hTime > 200UL))
  if (IR_Active == 1 && (IR_Data[IR_State] >= 10000 || hTime > 100UL))
  {
    return ((IR_State - 2) / 8) + 1;
  }

  return 0;
}

/*************************************************************************/
/* AEHAタイプのデータ数確認                                              */
/*************************************************************************/
int irRemocon_availableAEHA( void )
{
  unsigned long hTime = millis() - IR_High_Time;
  //if (IR_Active == 1 && (IR_Data[IR_State] >= 10000 || IR_State >= 200 || hTime > 200UL))
  if (IR_Active == 1 && (IR_Data[IR_State] >= 10000 || hTime > 200UL))
  {
  return ((IR_State - 2) / 8) + 1;
  }

  return 0;
}

/*************************************************************************/
/* NECタイプのデータ受信                                                 */
/*************************************************************************/
int irRemocon_rxNEC( byte dst[], int size )
{
  int i;
  volatile int limit = IR_State;
  int index = 0;

  for (i = 1; i <= limit; i++)
  {
    dst[index] >>= 1;
    if ( IR_Data[i] > 1500 ) dst[index] |= 0x80;
    if( !(i % 8) ) index++;
    if(index >= size) break;
  }

  IR_Active = 0;    // Close IR-bit decoding session and wait for the next stream
  IR_State = 0;

  return index;
}

/*************************************************************************/
/* AEHAタイプのデータ受信                                                */
/*************************************************************************/
int irRemocon_rxAEHA( byte dst[], int size )
{
  int i;
  volatile int limit = IR_State;
  int index = 0;

  for (i = 1; i <= limit; i++)
  {
    dst[index] >>= 1;
    if ( IR_Data[i] > 1200 ) dst[index] |= 0x80;
    if( !(i % 8) ) index++;
    if(index >= size) break;
  }

  IR_Active = 0;    // Close IR-bit decoding session and wait for the next stream
  IR_State = 0;

  return index;
}

/****************************************************************************/
/* IR RECEIVE for NEC format                                                */
/****************************************************************************/
void IR_nec( void )
{
  int sz;

  if( (sz = irRemocon_availableNEC() ) >= 4 )
  {
    byte *iRData = new byte[sz];
    sz = irRemocon_rxNEC( iRData, sz );

    String str = "";
    char asc[8];
    for(int i = 0; i < sz; i++)
    {
      str += itoh(asc,(unsigned int)iRData[i]);
      str += ",";
    }
    delete[] iRData;

    if(str.length() > 0)
    {
      Serial.print("type NEC:sz=");
      Serial.print(sz,DEC);
      Serial.print(" code:");
      //      Serial.write((const unsigned char*)&str[0],str.length());
      Serial.println(str);
    }
  }
}

/****************************************************************************/
/* IR RECEIVE for AEHA format                                               */
/****************************************************************************/
void IR_aeha( void )
{
  int sz;

  if( (sz = irRemocon_availableAEHA()) >= 6 )
  {
    byte *iRData = new byte[sz];
    sz = irRemocon_rxAEHA( iRData, sz );

    char buf[8];
    String str = "";
    for(int i = 0; i < sz; i++)
    {
      str += itoh(buf,(unsigned int)iRData[i]);
      str += ",";
    }
    delete[] iRData;

    if(str.length() > 0)
    {
      Serial.print("type AEHA: sz=");
      Serial.print(sz,DEC);
      Serial.print(" code:");
      //      Serial.write((const unsigned char*)&str[0],str.length());
      Serial.println(str);
    }
  }
}


 


 

####

Connection for remote controller signal transmission

 

 

 

 

 

 

 

 

As for transmission, recommend direct output from port of micro controller since a dedicated IC is not popular.
IR_CONT is connected with terminal 3 on GR-KURUMI.

Using transistor to have several infrared LEDs turn ON/OFF simultaneously.seems no problem to operate a LED with port directly since the terminals on GR-KURUMI allow a larger current to flow than expectation except analog shared port.

The schematics in the chart , turn LED ON when IR_CONT is LOW.

 

 

 

####

Program for remote controller signal transmission

Next stage, let’s transmit remote control codes for LED lighting or TV, which have been obtained with receipt program.

The terminal 3 connecting with IR_CONT is capable of PWM output in analogWrite. With PWM outpu, generate carrier wave of 38kHz. 
Outputting carrier wave with time, or modulating the bit stream by pause.

 

  pinMode(IR_CONT, OUTPUT);
  analogWriteFrequency((uint32_t)38 * 1000);  //set IR carrier

 

Receiver side will accept the carrier wave in the range of 39~40kHz, probably.

The scheme for modulation 1 is as follows.

 

 #define T_VALUE  555UL
  #define PPM_ON   170
  #define PPM_OFF  255

  analogWrite(IR_CONT,PPM_ON);
  delayMicroseconds(T_VALUE * 1);  //1T
  analogWrite(IR_CONT,PPM_OFF);
  delayMicroseconds(T_VALUE * 3);  //3T

 

 

 

The scheme for modulation 0 is as follows.

 

 

  analogWrite(IR_CONT,PPM_ON);
   delayMicroseconds(T_VALUE * 1);  //1T
   analogWrite(IR_CONT,PPM_OFF);
   delayMicroseconds(T_VALUE * 1);  //1T

 

The code sampling with receipt program is as follows.

const unsigned char TVOnOff[] = {0xaa,0x5a,0x8f,0x12,0x16,0xd1};
const unsigned char light01On[]  = {0x84,0x51,0x9a,0x65};
const unsigned char light01Off[] = {0x84,0x51,0x08,0xf7};

 

We can use the sane code to have AQUOS TV power ON/OFF.
Need to modify the code for LED lighting. 
Send out this code every 1 bit by above modulation scheme and added stop bit at last.



 

Here is the sample code.

/*

Infra-red IR-remote capture program version 1.0
by Kaz Kinoshita, Insutitute of Daiichi Technologies
date of 2014-10-23

*/
/* ------------------------------------------------------------------------ */
/* 赤外線リモコンの送信をしてみる                                           */
/*                                             designed by hamayan          */
/*                                             Copyright(C) hamayan         */
/*                                             since 2004 - 2016            */
/* ------------------------------------------------------------------------ */
#include 

#if !defined( _MULTITASK_H_ )
#define  dly_tsk(tim)  delay(tim)
#define  rot_rdq()
#define  loc_cpu()     interrupts()
#define  unl_cpu()     noInterrupts()
#endif /*_MULTITASK_H_ */

void irRemocon_txNEC(const byte data[], unsigned int sz);
void irRemocon_txAEHA(const byte data[], unsigned int sz);

#define  IR_CONT     3 // Ir LED ON/OFF

const unsigned char TVOnOff[] = {0xaa,0x5a,0x8f,0x12,0x16,0xd1};
const unsigned char light01On[]  = {0x84,0x51,0x9a,0x65};
const unsigned char light01Off[] = {0x84,0x51,0x08,0xf7};

void setup()
{
  Serial.begin( 9600 );
  Serial.println("IR remote control test.");
  pinMode(IR_CONT, OUTPUT);
  analogWriteFrequency((uint32_t)38 * 1000);  //set IR carrier

  while( 1 )
  {
    Serial.println("TV on.");
    irRemocon_txAEHA( TVOnOff, sizeof(TVOnOff) );
    delay( 1000UL );
    Serial.println("Light off.");
    irRemocon_txNEC( light01Off, sizeof(light01Off) );
    delay( 5 * 1000UL );
    Serial.println("TV off.");
    irRemocon_txAEHA( TVOnOff, sizeof(TVOnOff) );
    delay( 1000UL );
    Serial.println("Light on.");
    irRemocon_txNEC( light01On, sizeof(light01On) );
    delay( 5 * 1000UL );
  }
}

void loop()
{
}

char *itoh( char *dst, unsigned int value )
{
  sprintf( dst, "%02x", value );

  return dst;
}

/*************************************************************************/
/* NECタイプのデータ送信                                                 */
/*************************************************************************/
void irRemocon_txNEC(const byte data[], unsigned int sz)
{
//#define T_VALUE  562UL
#define T_VALUE  555UL
#define PPM_ON   170
#define PPM_OFF  255

loc_cpu();
analogWrite(IR_CONT,0);
//frame ppm on
analogWrite(IR_CONT,PPM_ON);
delayMicroseconds(T_VALUE * 16);  //16T
//frame ppm off
analogWrite(IR_CONT,PPM_OFF);
delayMicroseconds(T_VALUE * 8);  //8T

for(int i = 0; i < sz; i++)
{
byte temp = data[i];
for(int j = 0; j < 8; j++)
{
if(temp & 0x01)
{
//frame ppm on
analogWrite(IR_CONT,PPM_ON);
delayMicroseconds(T_VALUE * 1);  //1T
//frame ppm off
analogWrite(IR_CONT,PPM_OFF);
delayMicroseconds(T_VALUE * 3);  //3T
}
else
{
//frame ppm on
analogWrite(IR_CONT,PPM_ON);
delayMicroseconds(T_VALUE * 1);  //1T
//frame ppm off
analogWrite(IR_CONT,PPM_OFF);
delayMicroseconds(T_VALUE * 1);  //1T
}
temp >>= 1;
}
}

//stop bit
//frame ppm on
analogWrite(IR_CONT,PPM_ON);
delayMicroseconds(T_VALUE * 1);  //1T
//frame ppm off
analogWrite(IR_CONT,PPM_OFF);
unl_cpu();
}

/*************************************************************************/
/* AEHAタイプのデータ送信                                                */
/*************************************************************************/
void irRemocon_txAEHA(const byte data[], unsigned int sz)
{
#undef T_VALUE
#define T_VALUE  425UL
//#define PPM_ON   170  //170
//#define PPM_OFF  255

loc_cpu();
analogWrite(IR_CONT,0);
//frame ppm on
analogWrite(IR_CONT,PPM_ON);
delayMicroseconds(T_VALUE * 8);  //8T
//frame ppm off
analogWrite(IR_CONT,PPM_OFF);
delayMicroseconds(T_VALUE * 4);  //4T

for(int i = 0; i < sz; i++)
{
byte temp = data[i];
for(int j = 0; j < 8; j++)
{
if(temp & 0x01)
{
//frame ppm on
analogWrite(IR_CONT,PPM_ON);
delayMicroseconds(T_VALUE * 1);  //1T
//frame ppm off
analogWrite(IR_CONT,PPM_OFF);
delayMicroseconds(T_VALUE * 3);  //3T
}
else
{
//frame ppm on
analogWrite(IR_CONT,PPM_ON);
delayMicroseconds(T_VALUE * 1);  //1T
//frame ppm off
analogWrite(IR_CONT,PPM_OFF);
delayMicroseconds(T_VALUE * 1);  //1T
}
temp >>= 1;
}
}

//stop bit
//frame ppm on
analogWrite(IR_CONT,PPM_ON);
delayMicroseconds(T_VALUE * 1);  //1T
//frame ppm off
analogWrite(IR_CONT,PPM_OFF);
unl_cpu();
dly_tsk(10);
}


 

####

Infrared remote controller hacking for realizing IOT

When you'd like to realize IOT by yourself, we will recommend the hacking on infrared remote controller.


We can expect to maintain security high level unless we handle power supply of apparatus directly.

※ On the other hand, in the case of appliance which allow AC input to power on/off automatically or with remote controller, we need to consider the risk that will come into conflict with the law.

Be careful of an accidental fire.

Renesas MVP infomation @chobichan

General hard engineer, occasinally writing for technical magazine ...

 

Follow

share