IR센서 사용하기

IR Sensor 와 리모콘



위 사진에 나오는 리모콘을 사용합니다. 키 배열이 다르거나 다른 종류의 리모콘이라면
입력되는 값이 다르기 때문에 그에 맞게 소스를 수정해야 할 것입니다.
IrRemote.hpp 의 소스에서 키값 정의 부분을 수정하시면 됩니다.


회로구성


센서의 다리가 세개이고, 한쪽은 - 로 반대편은 S 로 표시되어 있습니다.
- 족은 GND 에 연결하고 가운데는  5V,  S  쪽은 3번핀에 연결하였습니다.


소스코드


#include "IRRemote.hpp"

int RECV_PIN = 3;
IRRemote irrecv(RECV_PIN);

void setup()
{
  Serial.begin(9600);
  irrecv.start();
  irrecv.useRepeat(true);
}

void loop() {
  if (irrecv.receive()) {
    Serial.println(irrecv.toString());
  }
}

리모콘으로 부터 입력받은 키를 시리얼 모니터에 출력합니다.
IRRemote.hpp 를 사용하는데, 아래 코드를 사용하면 됩니다.


<IrRemote.hpp>


#include <IRremote.h>

#define Unkown 0x0
#define CHm   0xFFA25D
#define CH    0xFF629D
#define CHp   0xFFE21D
#define REW   0xFF22DD
#define FF    0xFF02FD
#define PLAY  0xFFC23D
#define Minus 0xFFE01F
#define Plus  0xFFA857
#define EQ    0xFF906F
#define NUM0  0xFF6897
#define p100  0xFF9867
#define p200  0xFFB04F
#define NUM1  0xFF30CF
#define NUM2  0xFF18E7
#define NUM3  0xFF7A85
#define NUM4  0xFF10EF
#define NUM5  0xFF38C7
#define NUM6  0xFF5AA5
#define NUM7  0xFF42BD
#define NUM8  0xFF4AB5
#define NUM9  0xFF52AD

#define _CHm   0xE318261B
#define _CH    0x511DBB
#define _CHp   0xEE886D7F
#define _REW   0x52A3D41F
#define _FF    0xD7E84B1B
#define _PLAY  0x20FE4DBB
#define _Minus 0xF076C13B
#define _Plus  0xA3C8EDDB
#define _EQ    0xE5CFBD7F
#define _NUM0  0xC101E57B
#define _p100  0x97483BFB
#define _p200  0xF0C41643
#define _NUM1  0x9716BE3F
#define _NUM2  0x3D9AE3F7
#define _NUM3  0x6182021B
#define _NUM4  0x8C22657B
#define _NUM5  0x488F3CBB
#define _NUM6  0x449E79F
#define _NUM7  0x32C6FDF7
#define _NUM8  0x1BC0157B
#define _NUM9  0x3EC3FC1B

class IRRemote {
  private:

    long _lastValue = 0;
    bool use_repeat = true;

    IRrecv *irrecv;
    decode_results results;

  public:

    IRRemote(int signalPin) {
      irrecv = new IRrecv(signalPin);
    }

    ~IRRemote() {
      delete irrecv;
    }

    /**
       IR센싱 시작
    */
    void start() {
      irrecv->enableIRIn();
    }

    /**
       버튼을 누르고 있는 동안 값을 전달할지 여부 결정 (기본값 : true)
       @param repeatable 반복키 사용여부
    */
    void useRepeat(bool repeatable) {
      use_repeat = repeatable;
    }

    /**
       IR센서값 읽기
       @return 값 입력 여부
    */
    bool receive() {
      int received = irrecv->decode(&results);
      if (received) {
        irrecv->resume();
        adjustValue(&results);
        //if (results.decode_type == UNKNOWN) return false;
        if (!isValid(results.value))  return false;
        if (!use_repeat && results.value == 0xFFFFFFFF) {
          _lastValue = Unkown;
          return false;
        }
        parseValue();
      }
      return received ? true : false;
    }

    /**
       입력된 센서값 조회
       @return 센서값
    */
    long value() {
      return _lastValue;
    }

    /**
       입력된 센서값을 텍스트로 반환
       @return 눌려진 버튼 텍스트
    */
    const char* toString() {
      switch (_lastValue) {
        case CHm : return "CH-";
        case CH  : return "CH";
        case CHp : return "CH+";
        case REW : return "|<<";
        case FF  : return ">>|";
        case PLAY : return ">||";
        case Minus : return "-";
        case Plus : return "+";
        case EQ : return "EQ";
        case NUM0 : return "0";
        case p100 : return "100+";
        case p200 : return "200+";
        case NUM1 : return "1";
        case NUM2 : return "2";
        case NUM3 : return "3";
        case NUM4 : return "4";
        case NUM5 : return "5";
        case NUM6 : return "6";
        case NUM7 : return "7";
        case NUM8 : return "8";
        case NUM9 : return "9";
      }
      return "";
    }

  protected:

    void adjustValue(decode_results *recv) {
      long value = recv->value;
      switch (value) {
        case _CHm : recv->value = CHm; break;
        case _CH  : recv->value = CH; break;
        case _CHp : recv->value = CHp; break;
        case _REW : recv->value = REW; break;
        case _FF  : recv->value = FF; break;
        case _PLAY : recv->value = PLAY; break;
        case _Minus : recv->value = Minus; break;
        case _Plus : recv->value = Plus; break;
        case _EQ : recv->value = EQ; break;
        case _NUM0 : recv->value = NUM0; break;
        case _p100 : recv->value = p100; break;
        case _p200 : recv->value = p200; break;
        case _NUM1 : recv->value = NUM1; break;
        case _NUM2 : recv->value = NUM2; break;
        case _NUM3 : recv->value = NUM3; break;
        case _NUM4 : recv->value = NUM4; break;
        case _NUM5 : recv->value = NUM5; break;
        case _NUM6 : recv->value = NUM6; break;
        case _NUM7 : recv->value = NUM7; break;
        case _NUM8 : recv->value = NUM8; break;
        case _NUM9 : recv->value = NUM9; break;
      }
    }
    
    long parseValue() {
      long value = results.value;
      if (value == 0xFFFFFFFF) { //repeat
        return _lastValue;
      }
      _lastValue = value;
      return value;
    }

    bool isValid(long value) {
      switch (value) {
        case CHm :
        case CH  :
        case CHp :
        case REW :
        case FF  :
        case PLAY :
        case Minus :
        case Plus :
        case EQ :
        case NUM0 :
        case p100 :
        case p200 :
        case NUM1 :
        case NUM2 :
        case NUM3 :
        case NUM4 :
        case NUM5 :
        case NUM6 :
        case NUM7 :
        case NUM8 :
        case NUM9 :
        case 0xFFFFFFFF:
          return true;
      }
      _lastValue = Unkown;
      return false;
    }
};

키를 한 땀 한 땀 입력하면서 얻은 값을 바탕으로 만들었습니다.
같은 키인데도 여러경우의 값이 나타나게 되서 두가지 케이스만 적어 넣었습니다.
입력 각도가 기울어지거나 거리가 멀어지면 쓰레기값이 입력되거나
엉뚱한 값이 나오게 -값이 중간에 잘리거나 하는 것 같습니다- 되어 인식률이 빠릿빠릿 하진 않습니다.