おもちゃラボ

Unityで遊びを作っていきます

【Arduino】赤外線を使って通信する(後編)

f:id:nn_hokuson:20210406214650j:plain

赤外線通信をする(前編)では赤外線通信に欠かせない搬送波の作成までを作りました。この記事では赤外線送信機と受信機を作っていきます。

nn-hokuson.hatenablog.com

目次は次のとおりです。

赤外線の送信機をつくる

それでは実際に赤外線通信の送信機を作ってみましょう。送信機といっても赤外線LEDとスイッチだけで構成された簡易的なものです。ハードウエアの構成は次のようになります。
f:id:nn_hokuson:20210414204200j:plain:w350

PWM出力をする10番ポートに赤外線LEDを接続します。また、4番ポートにタクトスイッチを接続します。このスイッチを押している間だけ赤外線通信が行われるようにします。今回は次の赤外線LEDを使用しました。

赤外線通信プログラム(Arduino版)

次にArduinoで赤外線の送信プログラムを作成しましょう。データのフォーマットは前回の記事で紹介したとおりです。このフォーマットに合わせてPWM出力をON/OFFします。次のプログラムをArduinoに書き込んでみましょう。

int top = 0;
const int onTime = 480; 
const int offTime = 380;

const unsigned char data[] = {0,1,0,0,1,0,1,1};

void setup() {
   pinMode(10, OUTPUT );    
   pinMode(4, INPUT_PULLUP);

  TCCR1A = B00100011;
  TCCR1B = B00011010;
  top = F_CPU / 38000 / 8 - 1;
  OCR1AL = top; 
  OCR1BL = OCR1AL / 3;
}

void sendData()
{
    //リーダ部
    OCR1A = top;
    _delay_us(3400);
    OCR1A = 0; 
    _delay_us(1700);

    //データ部
    for(int i = 0; i < 8; i++){
       OCR1A = top; 
       _delay_us(onTime);
       OCR1A = 0; 
       if(data[i]){ 
          _delay_us(offTime*3); 
       }
       else{   
          _delay_us(offTime);  
       }
    }

    //ストップ部
    OCR1A = top; 
    _delay_us(onTime);
    OCR1A = 0; 
    _delay_ms(65);
}

void loop() 
{
  if(digitalRead(4) == LOW){
    sendData();
  }
}

このプログラムではsetup関数の中でPWMを使って38kHzの搬送波を出力するように、レジスタの設定を行っています。レジスタの設定値については前回の記事を参照下さい。

nn-hokuson.hatenablog.com

sendData関数の中では赤外線通信のフォーマットに従って、ヘッダ部、データ部、ストップビット部の波形を作っています。OCR1A(PWM用のカウンタの上限値)を0設定するとPWMが停止することを利用して、ON/OFFを行っています。

赤外線通信プログラム(AVR版)

赤外線の送信機は、小型化したり、電池駆動にしたい場合も多いと思います。その場合はArduinoを使うのではなく、直接AVRを使うことになります。そこでAVR用のプログラムも参考程度に乗せておきます。下記はATTiny85を使用した場合のプログラムです。

//ATTiny85用のプログラム
#define F_CPU 1000000UL
#define F_IR  38000L  
#include <util/delay.h>

int top = 0;
const int onTime = 480; 
const int offTime = 380;
int Limit = 1000;

const unsigned char data[] =  = {0,1,0,0,1,0,1,1};
int prevD = LOW;

void setup() 
{
  pinMode(1, OUTPUT );
  pinMode(4, INPUT_PULLUP);

  // AVRだとdelayにTCCR0A/Bのタイマーを使うのでTCCR1を使う
  TCCR1 = B11010001;
  top = F_CPU / 38000  -  1; 
  OCR1C = top; 
  OCR1A = OCR1C / 3;  
}

void sendData()
{
    //リーダ部
    OCR1C = top; 
    _delay_us(3400); //AVRでdelayMicrosecondsはx8倍されるバグあり
    OCR1C = 0;
    _delay_us(1700);

    //データ部
    for(int i = 0; i < 8; i++){
       OCR1C = top; 
       _delay_us(onTime);
       OCR1C = 0; 
       if(data[i]){
          _delay_us(offTime*3);
       }
       else{  
          _delay_us(offTime);
       }
    }

    //ストップ部
    OCR1C = top;       
    _delay_us(onTime);
    OCR1C = 0;  
    _delay_ms(65);
}

void loop() 
{
  if( digitalRead(4) == LOW){
    sendData();
  }
}

Arduinoを使った赤外線送信プログラムとほぼ同じですが、タイマーのレジスタにはTCCR1A/Bの代わりにTCCR1 を使っています。また、タイマーの上限値はOCR1Cレジスタに、デューティー比はOCR1Aレジスタに設定します。

AVRにプログラムを書き込むには、専用のライターを使うのが簡単です。Arduino IDEを使ってAVRにプログラムを書き込む方法は次の記事を参考にして下さい。

nn-hokuson.hatenablog.com

赤外線の受信機をつくる

最後に赤外線の受信機を作成しましょう。使用した赤外線受信モジュールは下記のものです。赤外線受信モジュール自体は一般的なものなので、秋月電子などで購入したものでも同じような構成で動くはずです。

受信機のハードウエアは次のとおりです。赤外線持っジュールのスペックシートによると、正面から見て一番右の足がVcc、真ん中がGND、左がデータになっています。そこで、赤外線受信モジュールの左のピンをArduinoの7番ポートに接続しています。

f:id:nn_hokuson:20210414211415j:plain:w350

赤外線を受信するArduinoのプログラムは次のとおりです。

int input_pin = 7;

void setup()
{
    Serial.begin(9600);   
    pinMode(input_pin, INPUT); 
}

void loop()
{
  unsigned long dt; 
  int i , cnt;
  int receiveData[8];
  dt = 0;
  
  if (digitalRead(input_pin) == LOW) { 
    dt = micros();                             
    while (digitalRead(input_pin) == LOW) ;
    dt = micros() - dt;  
  }

  if (dt >= 3400) {  
    i = 0 ;
    while(digitalRead(input_pin) == HIGH) ;   
    while (1) {
      while(digitalRead(input_pin) == LOW) ; 
      dt = micros(); 
      cnt = 0 ;
      while(digitalRead(input_pin) == HIGH) { 
        delayMicroseconds(10) ; 
        cnt++ ;
        if (cnt >= 1200){ 
          break ;
        }
      }
      dt = micros() - dt;  
      if(dt >= 10000){ 
        break;
      }
      receiveData[i] = (dt >= 800) ? 1 : 0; 
      i++;
    }

    // 受信データの表示
    if (i != 0) {
      for(int j=0; j<i; j++){
        Serial.print(",");
        Serial.print(data[j]);
     }
    }
  }
}

この記事の最初にArduinoで作った赤外線送信機のボタンを押して、受信機でちゃんと正しいデータが送られてくることを確認しましょう!

まとめ

Arduinoで赤外線通信をする(前編)では赤外線通信に必要なフォーマットや、搬送波の作り方を説明しました。またArduinoで赤外線通信をする(後編)では赤外線の送信機と受信機を作りながらArduinoで赤外線通信をする方法を紹介しました。