Title:Let's try the function on GR-KURUMI, outside interrupt vol.
Displayed Name:@chobichan
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.
General hard engineer, occasinally writing for technical magazine ...