ArduinoとIRLEDで自宅のシーリングライトを操作する

#最終目標
Arduino uno R3を使って自室のエアコン・シーリングライトをボタンでON、OFFを操作できるようにする。
ESP8266を使って外部からのPOSTで制御できるようにする。（<-コレは今回機材が届いてないので次回）

#シーリングライト編

##Arduino uno R3を使ってシーリングライトの赤外線リモコンの解析をする
###使用機材
* Arduino uno R3
* [赤外線リモコン受信モジュール](https://osoyoo.com/ja/2015/03/25/ir-receiver-module/)
* TOSHIBA　シーリングライトのリモコン(NLER001-LC)

###回路
正式な回路は公式に乗ってますのでそちらを参照してください。
回路を間違えるとモジュールが壊れる可能性があります。
![IRreceiver.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556423/675cfbc8-947f-7663-78ea-54363027d88f.jpeg)

回路は、使用モジュールによって違う可能性があります。
注意してくれぐれも調べずにマネをしないようにお願いします。

###ソースコード
[Arduino IDE](https://www.arduino.cc/en/main/software)を使用しています。
このコードでは[IRremote](https://github.com/z3t0/Arduino-IRremote)のSampleCodeを使用します。
以下は、SampleCode（IRrecvDumpV2.ino）にコメントを加えたものです。

```c++:IRrecvDumpV2.ino
//------------------------------------------------------------------------------
// Include the IRremote library header
//
#include <IRremote.h>

//------------------------------------------------------------------------------
// Tell IRremote which Arduino pin is connected to the IR Receiver (TSOP4838)
//
int recvPin = 11; //IR receiverのモジュールのData（Serial pin）
IRrecv irrecv(recvPin);

//+=============================================================================
// Configure the Arduino
//
void  setup ( ){
  Serial.begin(9600);   // Status message will be sent to PC at 9600 baud
                        //シリアルモニタの右下のbpsと同じにする。
  irrecv.enableIRIn();  // Start the receiver
}

//+=============================================================================
// Display IR code
//
void  ircode (decode_results *results){
  // Panasonic has an Address
  if (results->decode_type == PANASONIC) {
    Serial.print(results->address, HEX);
    Serial.print(":");
  }

  // Print Code
  Serial.print(results->value, HEX);
}

//+=============================================================================
// Display encoding type
//
void  encoding (decode_results *results)
{
  switch (results->decode_type) {
    default:
    case UNKNOWN:      Serial.print("UNKNOWN");       break ;
    case NEC:          Serial.print("NEC");           break ;
    case SONY:         Serial.print("SONY");          break ;
    case RC5:          Serial.print("RC5");           break ;
    case RC6:          Serial.print("RC6");           break ;
    case DISH:         Serial.print("DISH");          break ;
    case SHARP:        Serial.print("SHARP");         break ;
    case JVC:          Serial.print("JVC");           break ;
    case SANYO:        Serial.print("SANYO");         break ;
    case MITSUBISHI:   Serial.print("MITSUBISHI");    break ;
    case SAMSUNG:      Serial.print("SAMSUNG");       break ;
    case LG:           Serial.print("LG");            break ;
    case WHYNTER:      Serial.print("WHYNTER");       break ;
    case AIWA_RC_T501: Serial.print("AIWA_RC_T501");  break ;
    case PANASONIC:    Serial.print("PANASONIC");     break ;
    case DENON:        Serial.print("Denon");         break ;
  }
}

//+=============================================================================
// Dump out the decode_results structure.
//
void  dumpInfo (decode_results *results)
{
  // Check if the buffer overflowed
  if (results->overflow) {
    Serial.println("IR code too long. Edit IRremoteInt.h and increase RAWBUF");
    return;
  }

  // Show Encoding standard
  Serial.print("Encoding  : ");
  encoding(results);
  Serial.println("");

  // Show Code & length
  Serial.print("Code      : ");
  ircode(results);
  Serial.print(" (");
  Serial.print(results->bits, DEC);
  Serial.println(" bits)");
}

//+=============================================================================
// Dump out the decode_results structure.
//
void  dumpRaw (decode_results *results)
{
  // Print Raw data
  Serial.print("Timing[");
  Serial.print(results->rawlen-1, DEC);
  Serial.println("]: ");

  for (int i = 1;  i < results->rawlen;  i++) {
    unsigned long  x = results->rawbuf[i] * USECPERTICK;
    if (!(i & 1)) {  // even
      Serial.print("-");
      if (x < 1000)  Serial.print(" ") ;
      if (x < 100)   Serial.print(" ") ;
      Serial.print(x, DEC);
    } else {  // odd
      Serial.print("     ");
      Serial.print("+");
      if (x < 1000)  Serial.print(" ") ;
      if (x < 100)   Serial.print(" ") ;
      Serial.print(x, DEC);
      if (i < results->rawlen-1) Serial.print(", "); //',' not needed for last one
    }
    if (!(i % 8))  Serial.println("");
  }
  Serial.println("");                    // Newline
}

//+=============================================================================
// Dump out the decode_results structure.
//
void  dumpCode (decode_results *results)
{
  // Start declaration
  Serial.print("unsigned int  ");          // variable type
  Serial.print("rawData[");                // array name
  Serial.print(results->rawlen - 1, DEC);  // array size
  Serial.print("] = {");                   // Start declaration

  // Dump data
  for (int i = 1;  i < results->rawlen;  i++) {
    Serial.print(results->rawbuf[i] * USECPERTICK, DEC);
    if ( i < results->rawlen-1 ) Serial.print(","); // ',' not needed on last one
    if (!(i & 1))  Serial.print(" ");
  }

  // End declaration
  Serial.print("};");  // 

  // Comment
  Serial.print("  // ");
  encoding(results);
  Serial.print(" ");
  ircode(results);

  // Newline
  Serial.println("");

  // Now dump "known" codes
  if (results->decode_type != UNKNOWN) {

    // Some protocols have an address
    if (results->decode_type == PANASONIC) {
      Serial.print("unsigned int  addr = 0x");
      Serial.print(results->address, HEX);
      Serial.println(";");
    }

    // All protocols have data
    Serial.print("unsigned int  data = 0x");
    Serial.print(results->value, HEX);
    Serial.println(";");
  }
}

//+=============================================================================
// The repeating section of the code
//
void  loop ( )
{
  decode_results  results;        // Somewhere to store the results

  if (irrecv.decode(&results)) {  // Grab an IR code
    dumpInfo(&results);           // Output the results
    dumpRaw(&results);            // Output the results in RAW format
    dumpCode(&results);           // Output the results as source code
    Serial.println("");           // Blank line between entries
    irrecv.resume();              // Prepare for the next value
  }
}
```

###解析結果
```:赤外線解析結果
シーリングライト　点灯
Encoding  : NEC
Code      : E73045BA (32 bits)
Timing[67]: 
     +10150, -5000     + 700, -1850     + 700, -1850     + 650, -1850
     + 700, - 600     + 650, - 600     + 700, -1850     + 700, -1850
     + 650, -1900     + 650, - 600     + 650, - 600     + 700, -1850
     + 650, -1850     + 700, - 600     + 650, - 600     + 700, - 550
     + 700, - 600     + 650, - 600     + 700, -1850     + 700, - 600
     + 650, - 550     + 700, - 600     + 700, -1850     + 650, - 600
     + 700, -1850     + 700, -1800     + 700, - 600     + 650, -1850
     + 700, -1850     + 700, -1850     + 700, - 550     + 700, -1850
     + 700, - 600     + 650
unsigned int  rawData[67] = {10150,5000, 700,1850, 700,1850, 650,1850, 700,600, 650,600, 700,1850, 700,1850, 650,1900, 650,600, 650,600, 700,1850, 650,1850, 700,600, 650,600, 700,550, 700,600, 650,600, 700,1850, 700,600, 650,550, 700,600, 700,1850, 650,600, 700,1850, 700,1800, 700,600, 650,1850, 700,1850, 700,1850, 700,550, 700,1850, 700,600, 650};  // NEC E73045BA
unsigned int  data = 0xE73045BA;

消灯　
Encoding  : NEC
Code      : E730D12E (32 bits)
Timing[67]: 
     +10150, -5050     + 650, -1850     + 700, -1850     + 700, -1850
     + 650, - 600     + 700, - 550     + 700, -1850     + 700, -1850
     + 700, -1850     + 650, - 600     + 700, - 550     + 700, -1850
     + 700, -1850     + 700, - 550     + 700, - 550     + 700, - 600
     + 700, - 550     + 700, -1850     + 700, -1850     + 650, - 600
     + 700, -1850     + 650, - 600     + 700, - 550     + 700, - 600
     + 650, -1850     + 700, - 600     + 700, - 550     + 700, -1850
     + 700, - 550     + 700, -1850     + 700, -1850     + 650, -1850
     + 700, - 600     + 650
unsigned int  rawData[67] = {10150,5050, 650,1850, 700,1850, 700,1850, 650,600, 700,550, 700,1850, 700,1850, 700,1850, 650,600, 700,550, 700,1850, 700,1850, 700,550, 700,550, 700,600, 700,550, 700,1850, 700,1850, 650,600, 700,1850, 650,600, 700,550, 700,600, 650,1850, 700,600, 700,550, 700,1850, 700,550, 700,1850, 700,1850, 650,1850, 700,600, 650};  // NEC E730D12E
unsigned int  data = 0xE730D12E;
```
このうち、赤外線を送信してシーリングライトをON,OFFするのに必要なデータは、EncodingとCodeだけである。
EncodingとCodeだけは、しっかりとメモっておこう。

##IRLEDを使用してシーリングライトをON,OFFを切り替える

解析してしまえば、このシーリングライトはもはやArduinoさんの配下である。

###使用機材
* Arduino uno R3
* 赤外線LED
* タクトボタン
* 抵抗１００Ω

###回路
私は、残念なことに初心者です。「回路が汚い！！」怒りはやめて欲しい。ごめんなさい。
![IRsend.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556423/7c636a2c-4fbc-8349-1b72-df6973f399e1.jpeg)


###ソースコード
```c++:CeilingLightController
/*
using IRremote library
*/

#include <IRremote.h>

// pin number
#define light_on_button 12
#define light_off_button 8

void setup(){
  // setting button pin mode 
    pinMode(light_on_button,INPUT) ;
    pinMode(light_off_button,INPUT) ; 

    // Serial begin speed = 115200
    Serial.begin(115200);
}

void loop(){

    // read button state 
    // ボタンの状態をread
    unsigned int light_on_status = digitalRead(light_on_button);
    unsigned int light_off_status = digitalRead(light_off_button);

    if(light_off_status == LOW){ //ボタン下が押された時light off
        IRsend irsend;
        irsend.sendNEC(0xE730D12E,32); // FormatがNECだったのでsendNEC()
                    //(data,bit) Codeのところに書いてあるやつ 
        Serial.println("light off");
      }else if(light_on_status == LOW){ // ボタン上が押された時light on
        IRsend irsend;
        irsend.sendNEC(0xE73045BA,32); // FormatがNECだったのでsendNEC()
                    //(data,bit) Codeのところに書いてあるやつ              
        Serial.println("light on");
      }

      //delay time between this loop to next loop
    delay(500); //次のloopを始めるまでに５００msの遅延
}
```

コレでリモコンから出る赤外線の情報と同じ情報を送信することができる。


##結果
何も苦労することがなく出来た。


## 次回
エアコンをArduinoの支配下にする。