ゆるく楽しむプログラミング

赤外線リモコン受信ユニット

赤外線リモコン受信ユニット OSRB38C9AA と SPS-440-1 の使い方
SPS-440-1 は3.3~5V駆動、OSRB38C9AA は5V駆動
外形的に、OSRB38C9AA は指向性が強く、SPS-440-1 は全周囲均一。
固定機器を操作するならOSRB38C9AA 、動くおもちゃに使用するならSPS-440-1 の方が良いと思う。


この受信ユニットは待機時にはHIGH、38Khzで点滅する赤外線光を受講するとLOWを出力します。
単純なユニットなのでソフトウエア的には完全に互換性があります。
両方の受光ユニットを並べて出力をロジックアナライザで計測した結果を見ても、同じ出力波形になっているのが確認できます。


接続

ArduinoUNOで外部割込みを使う(ライブラリを使用する)場合には2番ピンに接続します。
割り込みを付買わない場合には何番ピンでもOK




赤外線リモコンの通信フォーマット(通信プロトコル)

赤外線リモコンの通信フォーマットはIEEEやISOの厳密な規格が決まっておらず、各メーカーが独自に作成しているようです。
日本国内のメーカーではディファクトスタンダードになっているのは NECフォーマット、家電協会フォーマット、SONYフォーマットの3強のようです。
これ以外に無い訳ではなく、比較的このフォーマットを使用しているメーカーが多いだけのようです。

秋月電子で購入できる良さげな赤外線リモコンがNECフォーマットなので、NECフォーマットで使ってみます

NECフォーマット

下図は受信ユニットの出力信号です、送信側は赤外線LEDの38KHzパルスになるので、フォーマットは同じですが表記が変わります。
赤外線リモコンの通信フォーマットで検索して見つかる解説は38Khzパルスの出力時間で表現されています。

562μ秒単位の信号変化でLOW信号の長さで0/1を判断可能。
ボタンを押した初回はFrameが孫伸され、108m秒以上押し続けるとRepeatが送信されます。
Repeatは直前に受信したFrameと同じの意味なので、最後にの受信したFrameの情報を保持しておく必要があります。



ArduinoIDEのスケッチ

信号の変化間隔が652μ秒と長いので、ポーリング処理でも十分処理が間に合います。
割り込みを使わない方法だとマイコンチップの違いの影響を受けないので使いまわしが出来てソレなりに便利です。

ReciveIR.zip
※ <>を全角<>に置き換えています。コピペの際は注意してください。
/**
 * 超シンプル 赤外線リモコン受信(NECフォーマット)
 */

#define BAUDRATE 9600
#define DATAPIN 6   //       ArduinoUNO:2   M5Stamp:19 RaspberryPi PICO:8

/*
 * 赤外線リモコン受信
 */
#define NECT 562 // クロック基準時間(NECフォーマット)
bool iRrepeatCoomand ;
uint16_t iRAddr ;
uint8_t iRCommand ;

bool readIrData( ) {
  bool retStat = true ;
  uint8_t readData[4] ;
  int setPos = 0 ;
  int bitLen = 0 ;
  int stat = HIGH ;
  uint8_t bitData ;
  unsigned long beginTime ;
  unsigned long passTime ;
  memset(readData,0,sizeof(readData)) ;
  iRrepeatCoomand = false ;

  // ----- データ受信開始待ち -----
  while(digitalRead(DATAPIN) == HIGH) ;

  // ----- FRAMAE受信開始 -----
  beginTime = micros();
  while(digitalRead(DATAPIN) == LOW) ;
  passTime = micros() - beginTime ;
  if (passTime < NECT * 12  || passTime > NECT * 20) {
    return false ;
  }

  // ----- FRAMAE種別 -----
  beginTime = micros();
  while(digitalRead(DATAPIN) == HIGH) ;
  passTime = micros() - beginTime ;
  if (passTime <= NECT * 6) {
    // Repeace FRAME
    iRrepeatCoomand = true ;
    return true ;
  }

  // ----- データ受信 -----
  bitData = 0x01 ;
  beginTime = micros();
  bitLen = 0 ;
  stat = LOW ;
  passTime = 0 ;
  while (bitLen < 32 && passTime < NECT * 6) {
    passTime = micros() - beginTime ;
    if (digitalRead(DATAPIN) !=  stat) {
      if (stat == HIGH) {
        // ----- 1Bit 受信 -----
        if (passTime >= NECT * 2) {
          readData[setPos] |= bitData ;
        }
        if (bitData != 0x80) {
          bitData <<= 1 ;
        } else {
          bitData = 0x01 ;
          setPos ++ ;
        }
        beginTime = micros();
        bitLen ++ ;
        stat = LOW ;
      } else {
        beginTime = micros();
        stat = HIGH ;
      }
    }
  }
  bitData = ~readData[3] ;
  retStat = (bitData == readData[2]) ? true :false ;
  iRAddr = readData[1] << 8 | readData[0] ;
  iRCommand = readData[2] ;

  return retStat ;
}

void setup() {
  Serial.begin(BAUDRATE);
  Serial.println("\nIr Recive - Read") ;
  pinMode(DATAPIN, INPUT);
}

void loop() {
  if (readIrData( )) {
    if (iRrepeatCoomand) {
      Serial.print("Repeat ") ;
    }
    Serial.print("Addr:") ;
    Serial.print(iRAddr,HEX) ;
    Serial.print("  Command:") ;
    Serial.println(iRCommand,HEX) ;
  }
  delay(10) ;
}

ライブラリを使用する方法

ArduinoIDEの赤外線リモコンライブラリを使用する場合は
[ツール]-[ライブラリを管理]から IRRemote を検索して、Arduino-IRremoteライブラリを追加
 [スケッチ例]-[IRRemote]-[SimpleReceiver]を使用します
ヘッダ部分にフォーマットの選択があるので、対応するリモコンのメーカーのコメントを外せばOK
海外メーカーのリモコンにも対応しています。


解説動画