Arduinoで赤外線リモコンコードを読み出す 家庭でできるIoT! 4パルス目 [ESP32]
前回ちらっと書いたリモコンコードの受信です。
秋月電子で売られている赤外線受光素子( http://akizukidenshi.com/catalog/g/gI-04659/ )をデータシート通りに抵抗、コンデンサ等を接続し、OUT端子をESP8266に接続します。
この受光素子はサブキャリアを検出するとLowを出力、サブキャリアが無ければHigh(HI-Z)です。
ESP8266側では端子割込みを使ってLowやHighの時間を測定し、時間をビットに換算します。
比較的簡単な処理ですが、悩むのがフレームの終了検出で、NECフォーマットであればビット数は固定長ですが、AEHAフォーマットの場合はビット数は可変長となるので、どこまで取り込んで良いのか判りません。
ですがフレーム間の間隔は必ず空く仕様なので、時間でフレームの終端を強制的に決めてしまう事としました。
とは言え三菱のエアコンのリモコンコードはデータ部が18byte有り、もし全ビットが1であればフレーム長は250msを超えてしますので、いかがなものか?と思わないでもないですが、、、
まぁリモコンコードを見るだけの処理なので、細かい事は気にしません。
実際にスケッチを組んで読み出したものです。オーデリックのリモコンとアクオスのリモコンを受信しています。
オーデリックは前出の様にNECフォーマットです。アクオスはAEHAフォーマットでした。このリモコンコードはメーカーが仕様で示したものではなく、あくまでも自分で解析したコードである事に十分注意して下さい。仮に他のプログラムでこのコードを送信しても上手くは行かないと思います。学習リモコンの様にする場合は、受信したコードを送信可能なプログラムが別途必要です。なお、前回のプログラムでは使えます。
秋月電子で売られている赤外線受光素子( http://akizukidenshi.com/catalog/g/gI-04659/ )をデータシート通りに抵抗、コンデンサ等を接続し、OUT端子をESP8266に接続します。
この受光素子はサブキャリアを検出するとLowを出力、サブキャリアが無ければHigh(HI-Z)です。
ESP8266側では端子割込みを使ってLowやHighの時間を測定し、時間をビットに換算します。
比較的簡単な処理ですが、悩むのがフレームの終了検出で、NECフォーマットであればビット数は固定長ですが、AEHAフォーマットの場合はビット数は可変長となるので、どこまで取り込んで良いのか判りません。
ですがフレーム間の間隔は必ず空く仕様なので、時間でフレームの終端を強制的に決めてしまう事としました。
とは言え三菱のエアコンのリモコンコードはデータ部が18byte有り、もし全ビットが1であればフレーム長は250msを超えてしますので、いかがなものか?と思わないでもないですが、、、
まぁリモコンコードを見るだけの処理なので、細かい事は気にしません。
実際にスケッチを組んで読み出したものです。オーデリックのリモコンとアクオスのリモコンを受信しています。
オーデリックは前出の様に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 {} } }
オーデリック LEDシーリングライト リモコン付き LED一体型 電球色~昼光色 調光・調色タイプ ~12畳 SH8237LDR
- 出版社/メーカー: オーデリック
- メディア: ホーム&キッチン
オーデリック LEDシーリングライト リモコン付き LED一体型 電球色~昼光色 調光・調色タイプ ~14畳 SH8234LDR
- 出版社/メーカー: オーデリック
- メディア: ホーム&キッチン
Arduinoライブラリで天井照明を制御 家庭でできるIoT! 3パルス目 [ESP32]
オーデリック LEDシーリングライト リモコン付き LED一体型 電球色~昼光色 調光・調色タイプ ~12畳 SH8237LDR
- 出版社/メーカー: オーデリック
- メディア: ホーム&キッチン
誰も期待していないでしょうけれど、Blynkで動かす。
今回のネタは天井照明です。家にはLEDタイプのオーデリックの天井照明を全部の部屋に入れました。
アマゾンリンクの前の型ですが、多分リモコン制御に関しては変わらないと思います。
この天井照明は結構コストパフォーマンスに優れていると思います。12畳でリモコン付き、調光付きで実売が1万円切っていますから。家に入れたのは2015年3月ですので、4年以上安定稼働しています。またわざわざIoTにしなくても付属のリモコンに時計が付いていますので、指定時間に照明を消す/点けるができます。
さて、この天井照明をリモコンで制御するためにはリモコンコードを知らなくてはできませんが(※相変わらずリモコンコードの仕様は公開されていない)、、、とは言え秋月電子とかで売られている赤外線受光素子を用意すれば( http://akizukidenshi.com/catalog/g/gI-04659/ )、Arduinoを使って比較的容易にコードを読み取る事ができます。※受光についてはその内やります。
とりあえずこの天井照明はNECフォーマットとなっています。
一般的に家電に使われているリモコンフォーマットは、NECフォーマット、AEHAフォーマット、SONYフォーマットが有ります。これらのフォーマットの詳細については以下のページを読んで下さい。
ChaNさんのリモコンコードの解説ページ
http://elm-chan.org/docs/ir_format.html
ちょっと補足
キャリア:キャリアは使用する赤外線LEDで決まってしまいます。秋月で買える赤外線LED( http://akizukidenshi.com/catalog/g/gI-12612/ )は大概波長940μmです。要らないリモコンを分解して取り出しても構いません。半減角:15°(狭角)~60°(広角)や、LEDに流す電流で使い易さが変わってくるでしょう。
サブキャリア周波数:キャリアをパルス状にして出力する事で、ちまたに溢れている赤外線と、リモコンの赤外線を区別していますが、そのパルスの周波数です。一般的に38kHz前後です。
つまりリモコンコードのビット毎の0または1に対応するパターンに従って赤外線LEDをON/OFFさせれば良いことが判ります。この時ArduinoであればサブキャリアはanalogWrite、パルスの時間はdelayMicrosecondsを使えば実現できます。
/*************************************************************************/ /* NECタイプのデータ送信 */ /*************************************************************************/ void iRRemocon::txNEC(const unsigned char data[], unsigned int sz) { #define T_VALUE 555UL // 562UL #define PPM_ON 128 //170 #define PPM_OFF 255 analogWriteRange( 255 ); analogWriteFreq( 38 * 1000UL ); 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,0); }
ですがまぁ、折角エアコン制御を実現しているので、そこで使われている赤外線出力のClassを利用する事とします。
Classの使い方を知るために、三菱のエアコンのソースコードを見てみます。三菱のエアコンはAEHAフォーマットです。
MitsubishiHeatpumpIR.cpp
void MitsubishiHeatpumpIR::sendMitsubishi(IRSender& IR, uint8_t powerMode, uint8_t operatingMode, uint8_t fanSpeed, uint8_t temperature, uint8_t swingV, uint8_t swingH) { 長いので抜粋 // 40 kHz PWM frequency IR.setFrequency(38); // The Mitsubishi data is repeated twice for (int j=0; j<2; j++) { // Header IR.mark(MITSUBISHI_AIRCON1_HDR_MARK); IR.space(MITSUBISHI_AIRCON1_HDR_SPACE); // Data for (unsigned int i=0; i<sizeof(MitsubishiTemplate); i++) { IR.sendIRbyte(MitsubishiTemplate[i], MITSUBISHI_AIRCON1_BIT_MARK, MITSUBISHI_AIRCON1_ZERO_SPACE, MITSUBISHI_AIRCON1_ONE_SPACE); } // Pause between the first and the second data burst // Also modify one byte for the second burst on MSY model. This does not affect the checksum of the second burst if (j == 0) { IR.mark(MITSUBISHI_AIRCON1_BIT_MARK); IR.space(MITSUBISHI_AIRCON1_MSG_SPACE); if (_mitsubishiModel == MITSUBISHI_MSY) { MitsubishiTemplate[14] = 0x24; } } } // End mark IR.mark(MITSUBISHI_AIRCON1_BIT_MARK); IR.space(0); }
MitsubishiHeatpumpIR.h
/* Mitsubishi MSZ FD-25 heatpump control (remote control P/N KM09D 0052376) */ #ifndef MitsubishiHeatpumpIR_h #define MitsubishiHeatpumpIR_h #include "HeatpumpIR.h" 長いので抜粋 // Mitsubishi MSZ FD-25 timing constants (remote control P/N KM09D 0052376) #define MITSUBISHI_AIRCON1_HDR_MARK 3500 #define MITSUBISHI_AIRCON1_HDR_SPACE 1700 #define MITSUBISHI_AIRCON1_BIT_MARK 430 #define MITSUBISHI_AIRCON1_ONE_SPACE 1250 #define MITSUBISHI_AIRCON1_ZERO_SPACE 390 #define MITSUBISHI_AIRCON1_MSG_SPACE 17500 class MitsubishiHeatpumpIR : public HeatpumpIR { protected: // Cannot create generic Mitsubishi heatpump instances MitsubishiHeatpumpIR(); uint8_t _mitsubishiModel; // Tells whether this is FD or EF (or other supported model...) public: void send(IRSender& IR, uint8_t powerModeCmd, uint8_t operatingModeCmd, uint8_t fanSpeedCmd, uint8_t temperatureCmd, uint8_t swingVCmd, uint8_t swingHCmd); private: void sendMitsubishi(IRSender& IR, uint8_t powerMode, uint8_t operatingMode, uint8_t fanSpeed, uint8_t temperature, uint8_t swingVCmd, uint8_t swingHCmd); }; #endif
定義のMITSUBISHI_AIRCON1_HDR_MARKは赤外線フレームのLeader部の8Tに、MITSUBISHI_AIRCON1_HDR_SPACEはLeader部の4Tに相当します。
MITSUBISHI_AIRCON1_BIT_MARKはパルスを出している時間、MITSUBISHI_AIRCON1_ONE_SPACEはビット1のパルスの無い時間、MITSUBISHI_AIRCON1_ZERO_SPACEはビット0のパルスの無い時間に相当します。
ChaNさんの解説と微妙に時間が合わないのは、調整が入っているのかもしれません。
上記を参考にオーデリックのライブラリを作成してみました。現時点ではZIPインストールをせず、プロジェクトディレクトリに保存しているので、includeパスに注意が必要です。
odelic.h
/****************************************************************************/ /* お家のオーデリック製LED照明をなんとかするヘッダー */ /* Copyright (C) 2014 hamayan All Rights Reserved. */ /****************************************************************************/ #ifndef odelic_h #define odelic_h #include <Arduino.h> #include <HeatpumpIR.h> extern "C" { // #include <mul_tsk.h> } /****************************************************************************/ /* なにかの定義 */ /****************************************************************************/ #define NEC_T_PERIOD 562UL // 562us #define NEC_REPEAT_PERIOD 120UL // 108ms #define ODELIC_CHANNEL_1 0 #define ODELIC_CHANNEL_2 1 #define ODELIC_CHANNEL_3 2 typedef struct /*オーデリックのフォーマットはNECタイプ*/ { unsigned char customerCode[2]; unsigned char data[2]; } ODELIC_CEILING_LIGHT_CODE; class odelic : public HeatpumpIR { private: uint8_t channel; uint32_t startTim; void send( IRSender& IR, uint8_t *code ); public: odelic( uint8_t ch = 0 ); void onOff( IRSender& IR, bool onoff ); void coldLight( IRSender& IR, int value ); void warmLight( IRSender& IR, int value ); char type( void ); }; #endif /*odelic_h*/ /****************************************************************************/ /* Copyright (C) 2014 hamayan All Rights Reserved. */ /****************************************************************************/
odelic.cpp
/*************************************************************************/ /* お家のオーデリック製LED照明をなんとかするソース */ /* designed by hamayan since 2015/05/28 */ /*************************************************************************/ #include "odelic.h" /*************************************************************************/ /* 大域変数宣言 */ /*************************************************************************/ /*調光を行う時は連続して2つのコードを送信する。つまり寒色と暖色の両方のLEDを制御している*/ /*また、輝度毎にコードが異なる。それ以外に3byte目と4byte目は反転の関係となる*/ static const unsigned char on[] = { 0x84, 0x51, 0x9a ,0x65 }; /*ch2: 0x84, 0x51, 0x9b,0x64*/ static const unsigned char off[] = { 0x84, 0x51, 0x08 ,0xf7 }; /*ch2: 0x84, 0x51, 0x09,0xf6*/ static const unsigned char cold[][4] = { { 0x84, 0x51, 0x6c ,0x93 }, /*10% ch2: 0x84, 0x51, 0x6d,0x92*/ { 0x84, 0x51, 0x6e ,0x91 }, /*20% ch2: 0x84, 0x51, 0x6f,0x90*/ { 0x84, 0x51, 0x70 ,0x8f }, /*30% ch2: 0x84, 0x51, 0x71,0x8e*/ { 0x84, 0x51, 0x72 ,0x8d }, /*40% ch2: 0x84, 0x51, 0x73,0x8c*/ { 0x84, 0x51, 0x74 ,0x8b }, /*50% ch2: 0x84, 0x51, 0x75,0x8a*/ { 0x84, 0x51, 0x76 ,0x89 }, /*60% ch2: 0x84, 0x51, 0x77,0x88*/ { 0x84, 0x51, 0x78 ,0x87 }, /*70% ch2: 0x84, 0x51, 0x79,0x86*/ { 0x84, 0x51, 0x7a ,0x85 }, /*80% ch2: 0x84, 0x51, 0x7b,0x84*/ { 0x84, 0x51, 0x7c ,0x83 }, /*90% ch2: 0x84, 0x51, 0x7d,0x82*/ { 0x84, 0x51, 0x7e ,0x81 }, /*100% ch2: 0x84, 0x51, 0x7f,0x80*/ }; static const unsigned char warm[][4] = { { 0x84, 0x51, 0x58 ,0xa7 }, /*10% ch2: 0x84, 0x51, 0x59,0xa6*/ { 0x84, 0x51, 0x5a ,0xa5 }, /*20% ch2: 0x84, 0x51, 0x5b,0xa4*/ { 0x84, 0x51, 0x5c ,0xa3 }, /*30% ch2: 0x84, 0x51, 0x5d,0xa2*/ { 0x84, 0x51, 0x5e ,0xa1 }, /*40% ch2: 0x84, 0x51, 0x5f,0xa0*/ { 0x84, 0x51, 0x60 ,0x9f }, /*50% ch2: 0x84, 0x51, 0x61,0x9e*/ { 0x84, 0x51, 0x62 ,0x9d }, /*60% ch2: 0x84, 0x51, 0x63,0x9c*/ { 0x84, 0x51, 0x64 ,0x9b }, /*70% ch2: 0x84, 0x51, 0x65,0x9a*/ { 0x84, 0x51, 0x66 ,0x99 }, /*80% ch2: 0x84, 0x51, 0x67,0x98*/ { 0x84, 0x51, 0x68 ,0x97 }, /*90% ch2: 0x84, 0x51, 0x69,0x96*/ { 0x84, 0x51, 0x6a ,0x95 }, /*100% ch2: 0x84, 0x51, 0x6b,0x94*/ }; /*************************************************************************/ /* プロトタイプ宣言 */ /*************************************************************************/ /*************************************************************************/ /* インスタンス */ /*************************************************************************/ odelic::odelic( uint8_t ch ) { channel = ch; startTim = millis(); } /*************************************************************************/ /* send */ /*************************************************************************/ void odelic::send( IRSender& IR, uint8_t *code ) { uint8_t tempUC[4]; memcpy( tempUC, code, sizeof(tempUC) ); tempUC[2] = tempUC[2] + channel; tempUC[3] = tempUC[3] - channel; // 40 kHz PWM frequency IR.setFrequency( 38 ); //リピートでメソッドが呼ばれた時、強制的に間隔を開ける while( (millis() - startTim) < NEC_REPEAT_PERIOD ) delay( 10 ); // start time startTim = millis(); // Header IR.mark( 16 * NEC_T_PERIOD ); //frame ppm on IR.space( 8 * NEC_T_PERIOD ); //frame ppm off // Data for( unsigned int i = 0; i < sizeof( tempUC ); i++ ) { IR.sendIRbyte( tempUC[i], NEC_T_PERIOD, NEC_T_PERIOD, 3 * NEC_T_PERIOD ); // data,562us,562us,1686us // pulse on period, pulse off period at ZERO, pulse off period at 1 } // End mark IR.mark( NEC_T_PERIOD ); IR.space( 0 ); } /*************************************************************************/ /* 引数valueは2以上で100以下の数字 */ /*************************************************************************/ void odelic::coldLight( IRSender& IR, int value ) { if( value >= 2 && value <= 100 ) { value--; value /= 10; send( IR, (uint8_t *)cold[ value ] ); } } /*************************************************************************/ /* 引数valueは2以上で100以下の数字 */ /*************************************************************************/ void odelic::warmLight( IRSender& IR, int value ) { if( value >= 2 && value <= 100 ) { value--; value /= 10; send( IR, (uint8_t *)warm[ value ] ); } } /*************************************************************************/ /* 引数valueは0または1またはそれ以上で100以下の数字 */ /*************************************************************************/ void odelic::onOff( IRSender& IR, bool onoff ) { if( onoff ) send( IR, (uint8_t *)on ); else send( IR, (uint8_t *)off ); } /*************************************************************************/ /* リモコンフォーマットを答える */ /*************************************************************************/ char odelic::type( void ) { return 'N'; /*NECのN!*/ } /*************************************************************************/ /* end of file */ /* designed by hamayan since 2015/05/28 */ /*************************************************************************/
スケッチ側はこんなんなります。
#include "odelic.h" #define IR_CONT 12 // Ir control IRSenderBitBang irSender( IR_CONT ); odelic *room1 = new odelic( ODELIC_CHANNEL_1 ); /*************************************************************************/ /* blynk virtual pin 2 function. */ /*************************************************************************/ BLYNK_WRITE( V2 ) { int value = param.asInt(); if( value ) { room1->onOff( irSender, true ); Blynk.virtualWrite( V4, 100 ); Blynk.virtualWrite( V5, 100 ); } else { room1->onOff( irSender, false ); Blynk.virtualWrite( V4, 0 ); Blynk.virtualWrite( V5, 0 ); } } /*************************************************************************/ /* blynk virtual pin 3 function. */ /*************************************************************************/ BLYNK_WRITE( V3 ) { room1->coldLight( irSender, 70 ); room1->warmLight( irSender, 70 ); Blynk.virtualWrite( V4, 70 ); Blynk.virtualWrite( V5, 70 ); } /*************************************************************************/ /* blynk virtual pin 4 function. */ /*************************************************************************/ BLYNK_WRITE( V4 ) { int value = param.asInt(); room1->warmLight( irSender, value ); } /*************************************************************************/ /* blynk virtual pin 5 function. */ /*************************************************************************/ BLYNK_WRITE( V5 ) { int value = param.asInt(); room1->coldLight( irSender, value ); }
オーデリックの天井照明は、隣り合う部屋でリモコンを使った時に混信しないように、3チャネルまで設定できます。
オーデリック LEDシーリングライト リモコン付き LED一体型 電球色~昼光色 調光・調色タイプ ~14畳 SH8234LDR
- 出版社/メーカー: オーデリック
- メディア: ホーム&キッチン