現在、絶賛編集中の記事です。色々ウソが有るかもしれません。
Image may be NSFW.
Clik here to view.
前回ちらっと書いたリモコンコードの受信です。
秋月電子で売られている赤外線受光素子( http://akizukidenshi.com/catalog/g/gI-04659/ )をデータシート通りに抵抗、コンデンサ等を接続し、OUT端子をESP8266に接続します。
この受光素子はサブキャリアを検出するとLowを出力、サブキャリアが無ければHigh(HI-Z)です。
ESP8266側では端子割込みを使ってLowやHighの時間を測定し、時間をビットに換算します。
比較的簡単な処理ですが、悩むのがフレームの終了検出で、NECフォーマットであればビット数は固定長ですが、AEHAフォーマットの場合はビット数は可変長となるので、どこまで取り込んで良いのか判りません。
ですがフレーム間の間隔は必ず空く仕様なので、時間でフレームの終端を強制的に決めてしまう事としました。
とは言え三菱のエアコンのリモコンコードはデータ部が18byte有り、もし全ビットが1であればフレーム長は250msを超えてしますので、いかがなものか?と思わないでもないですが、、、
まぁリモコンコードを見るだけの処理なので、細かい事は気にしません。
Image may be NSFW.
Clik here to view.
実際にスケッチを組んで読み出したものです。オーデリックのリモコンとアクオスのリモコンを受信しています。
オーデリックは前出の様にNECフォーマットです。アクオスはAEHAフォーマットでした。このリモコンコードはメーカーが仕様で示したものではなく、あくまでも自分で解析したコードである事に十分注意して下さい。仮に他のプログラムでこのコードを送信しても上手くは行かないと思います。学習リモコンの様にする場合は、受信したコードを送信可能なプログラムが別途必要です。なお、前回のプログラムでは使えます。
Image may be NSFW.
Clik here to view.

秋月電子で売られている赤外線受光素子( http://akizukidenshi.com/catalog/g/gI-04659/ )をデータシート通りに抵抗、コンデンサ等を接続し、OUT端子をESP8266に接続します。
この受光素子はサブキャリアを検出するとLowを出力、サブキャリアが無ければHigh(HI-Z)です。
ESP8266側では端子割込みを使ってLowやHighの時間を測定し、時間をビットに換算します。
比較的簡単な処理ですが、悩むのがフレームの終了検出で、NECフォーマットであればビット数は固定長ですが、AEHAフォーマットの場合はビット数は可変長となるので、どこまで取り込んで良いのか判りません。
ですがフレーム間の間隔は必ず空く仕様なので、時間でフレームの終端を強制的に決めてしまう事としました。
とは言え三菱のエアコンのリモコンコードはデータ部が18byte有り、もし全ビットが1であればフレーム長は250msを超えてしますので、いかがなものか?と思わないでもないですが、、、
まぁリモコンコードを見るだけの処理なので、細かい事は気にしません。
Image may be NSFW.
Clik here to view.

オーデリックは前出の様にNECフォーマットです。アクオスはAEHAフォーマットでした。このリモコンコードはメーカーが仕様で示したものではなく、あくまでも自分で解析したコードである事に十分注意して下さい。仮に他のプログラムでこのコードを送信しても上手くは行かないと思います。学習リモコンの様にする場合は、受信したコードを送信可能なプログラムが別途必要です。なお、前回のプログラムでは使えます。
#include <ESP8266WiFi.h> void ICACHE_RAM_ATTR irRemocon_interrupt( void ); #define IR_CONT 12 /* Ir LED ON/OFF */ #define IR_RECV 13 /* Ir receive */ #define Max_IR_Bits_NEC 32 #define Max_IR_Bits_AEHA 256 #define NEC_HEADER_LOW_MIN_PERIOD 462UL #define NEC_HEADER_LOW_MAX_PERIOD 662UL #define AEHA_HEADER_LOW_MIN_PERIOD 350UL #define AEHA_HEADER_LOW_MAX_PERIOD 500UL unsigned long IR_Low_Time; // holds IR bursting time unsigned long IR_High_Time; // holds IR high idling time unsigned long Latest_Time_ms; unsigned short IR_Data[Max_IR_Bits_AEHA] = {0,}; // holds the bit length of each data bit by micro-sec. int IR_State; int IR_Bit_Count; bool IR_Active = false; // when true, the capturing IR data stream is valid char IR_formatType; void setup() { Serial.begin( 115200UL ); Serial.println( "\r\n\r\nIR recieve code print out." ); pinMode( IR_RECV, INPUT_PULLUP ); attachInterrupt( IR_RECV, irRemocon_interrupt, CHANGE ); } void loop() { if( IR_Active ) { if( IR_formatType == 'N' && (millis() - Latest_Time_ms) >= 18UL ) { if( irRemocon_available() >= 4 ) IR_nec(); irRemocon_init(); } else if( IR_formatType == 'A' && (millis() - Latest_Time_ms) >= 10UL ) { if( irRemocon_available() >= 6 ) IR_aeha(); irRemocon_init(); } } } /*************************************************************************/ /* int to hexadecimal */ /*************************************************************************/ char *itoh( char *dst, unsigned int value ) { sprintf( dst, "%02x", value ); return dst; } /*************************************************************************/ /* IR_REMOCON初期化 */ /*************************************************************************/ void irRemocon_init( void ) { IR_Active = false; // when 1, the capturing IR data stream is valid IR_formatType = 0; IR_State = 0; } /*************************************************************************/ /* データ数確認 */ /*************************************************************************/ int irRemocon_available( void ) { if( IR_Active ) return IR_State / 8; return 0; } /*************************************************************************/ /* NECタイプのデータ受信 */ /*************************************************************************/ int irRemocon_rxNEC( byte dst[], int size ) { int index = 0; for( int i = 0; i < Max_IR_Bits_NEC; i++ ) { dst[index] >>= 1; if ( IR_Data[i] > ((NEC_HEADER_LOW_MIN_PERIOD + NEC_HEADER_LOW_MAX_PERIOD) / 2) * 3 ) dst[index] |= 0x80; if( (i % 8) == 7 ) index++; } return index; } /*************************************************************************/ /* AEHAタイプのデータ受信 */ /*************************************************************************/ int irRemocon_rxAEHA( byte dst[], int size ) { volatile int limit = IR_State; int index = 0; for( int i = 0; i < limit; i++ ) { dst[index] >>= 1; if ( IR_Data[i] > ((AEHA_HEADER_LOW_MIN_PERIOD + AEHA_HEADER_LOW_MAX_PERIOD) / 2) * 3 ) dst[index] |= 0x80; if( (i % 8) == 7 ) index++; } return index; } /****************************************************************************/ /* IR RECEIVE for NEC format */ /****************************************************************************/ void IR_nec( void ) { int sz = irRemocon_available(); 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.println( str ); } } /****************************************************************************/ /* IR RECEIVE for AEHA format */ /****************************************************************************/ void IR_aeha( void ) { int sz = irRemocon_available(); 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.println( str ); } } /*************************************************************************/ /* IR_REMOCON割り込み */ /*************************************************************************/ void ICACHE_RAM_ATTR irRemocon_interrupt( void ) { if( digitalRead( IR_RECV ) == LOW ) // edge is low. { if( IR_Active ) //LOWからLOWまでの時間を計測して配列に保存する { unsigned long period = micros() - IR_Low_Time; if( IR_formatType == 'N' && period >= NEC_HEADER_LOW_MIN_PERIOD * 2 && period <= NEC_HEADER_LOW_MAX_PERIOD * 4 ) { if( IR_State < Max_IR_Bits_NEC ) { IR_Data[IR_State++] = (unsigned short)period; IR_Bit_Count = IR_State; Latest_Time_ms = millis(); } else irRemocon_init(); } else if( IR_formatType == 'A' && period >= AEHA_HEADER_LOW_MIN_PERIOD * 2 && period <= AEHA_HEADER_LOW_MAX_PERIOD * 4 ) { if( IR_State < Max_IR_Bits_AEHA ) { IR_Data[IR_State++] = (unsigned short)period; IR_Bit_Count = IR_State; Latest_Time_ms = millis(); } else irRemocon_init(); } } IR_Low_Time = micros(); } else // edge is high. { unsigned long period = micros() - IR_Low_Time; if( period >= NEC_HEADER_LOW_MIN_PERIOD * 8 ) // NECフォーマット { IR_Active = true; IR_State = 0; IR_High_Time = millis(); //先頭フレームの後半の時間となる IR_formatType = 'N'; Latest_Time_ms = millis(); } else if( period >= AEHA_HEADER_LOW_MIN_PERIOD * 8 ) // 家製協(AEHA)フォーマット { IR_Active = true; IR_State = 0; IR_High_Time = millis(); //先頭フレームの後半の時間となる IR_formatType = 'A'; Latest_Time_ms = millis(); } else {} } }
Image may be NSFW.
Clik here to view.![ESP-WROOM-02開発ボード ESP-WROOM-02開発ボード]()
Clik here to view.

- 出版社/メーカー: スイッチサイエンス(Switch Science)
- メディア: おもちゃ&ホビー
Image may be NSFW.
Clik here to view.![オーデリック LEDシーリングライト リモコン付き LED一体型 電球色~昼光色 調光・調色タイプ ~12畳 SH8237LDR オーデリック LEDシーリングライト リモコン付き LED一体型 電球色~昼光色 調光・調色タイプ ~12畳 SH8237LDR]()
Clik here to view.

オーデリック LEDシーリングライト リモコン付き LED一体型 電球色~昼光色 調光・調色タイプ ~12畳 SH8237LDR
- 出版社/メーカー: オーデリック
- メディア: ホーム&キッチン
Image may be NSFW.
Clik here to view.![オーデリック LEDシーリングライト リモコン付き LED一体型 電球色~昼光色 調光・調色タイプ ~14畳 SH8234LDR オーデリック LEDシーリングライト リモコン付き LED一体型 電球色~昼光色 調光・調色タイプ ~14畳 SH8234LDR]()
Clik here to view.

オーデリック LEDシーリングライト リモコン付き LED一体型 電球色~昼光色 調光・調色タイプ ~14畳 SH8234LDR
- 出版社/メーカー: オーデリック
- メディア: ホーム&キッチン