概要

赤外線モジュールをGR-COTTONに接続してリモコン受信してみます。


準備

GR-COTTON、USBケーブル(マイクロBタイプ)、赤外線モジュールの3つを準備します。

GR-COTTONにはピンソケット(丸ピン)を取り付ける必要があります。赤外線モジュールの足は適当な長さに切ります。なお、赤外線モジュールの足が細いため、温湿度センサーや、デジタルコンパス用のソケットではきちんと接続されません。この場合、丸ピンタイプのソケットを重ねることで解決できます。

赤外線モジュールの購入についてはこちら(秋月電子通商Web)

ピンソケット(丸ピン)の購入についてはこちら(秋月電子通商Web)

下図のように赤外線モジュールを、GR-COTTONに接続します。

GR-COTTONの裏面にある白いジャンパーが3V3、USB側にします。BATT側にある場合は引き抜いて、USB側に差し込んでください。


赤外線の受信を確かめる。

まずは赤外線モジュールがリモコンからの赤外線をキャッチしているか確認します。

赤外線のキャッチを青LEDにエコーするだけのサンプルプログラムです。


#include <arduino.h>
void setup() {
  pinMode(2, INPUT_PULLUP);   
  pinMode(24, OUTPUT); //blue led
  digitalWrite(24, HIGH);
}
   
void loop() {
  digitalWrite(24, digitalRead(2));
}




赤外線を受信しない間、省電力にする。

リモコンから操作しない間はなるべく省電力にしたいですよね。

赤外線をキャッチするまで省電力にするサンプルです。このサンプルはボタンスイッチと似ており、ピン2に割り当たっている割り込みを使っています。


#include <arduino.h>

void ir_receive(){
  digitalWrite(23, LOW);
  setPowerManagementMode(PM_NORMAL_MODE); // for use delay
  delayMicroseconds(1000);
  digitalWrite(23, HIGH);
}
void setup() {
  pinMode(2, INPUT_PULLUP);
  attachInterrupt(0, ir_receive, FALLING);
    
  pinMode(23, OUTPUT); //green led
  digitalWrite(23, HIGH);
}
   
void loop() {
  setPowerManagementMode(PM_STOP_MODE);
  delay(0xffffffff); // into stop mode
}






リモコンのボタンに応じてLEDを光らせる。

このサンプルは、以下のリモコンのA, B, Cボタンを押したときにLEDを光らせます。

このリモコンはNECフォーマットに準拠しています。サンプルではNECフォーマットに合わせた信号の分析をしてLEDを光らせる他、シリアルモニターに信号の内容を表示しています。

リモコンの購入についてはこちら(秋月電子通商Web)

Cottonリモートシリアル

#include <arduino.h>

#define IR_PIN 2
#define IR_INTERRUPT 0
 
uint8_t g_ir_data = 0;
bool    g_ir_available = false;
 
void ir_receive_interrupt();
void ir_receive_start();
uint8_t ir_getData();
bool ir_available();
 
void setup() {
  setPowerManagementMode(PM_STOP_MODE);
  Serial.begin(9600);
  pinMode(IR_PIN, INPUT_PULLUP);
  ir_receive_start();
   
  pinMode(22, OUTPUT);
  pinMode(23, OUTPUT);
  pinMode(24, OUTPUT);
  digitalWrite(22, HIGH);
  digitalWrite(23, HIGH);
  digitalWrite(24, HIGH);
 
}
  
void loop() {
  ir_receive_start();
  delay(0xFFFFFFFF); // hold STOP mode until receiving IR signal.
 
  if(ir_available()){
    Serial.println(ir_getData(), HEX);
    Serial.flush();
    switch (ir_getData()) {
      case 0xD8: // POWER BUTTON
        digitalWrite(22, LOW);
        delay(100);
        digitalWrite(22, HIGH);
        break;
      case 0xF8: // A BUTTON
        digitalWrite(23, LOW);
        delay(100);
        digitalWrite(23, HIGH);
        break;
      case 0x78: // B BUTTON
        digitalWrite(24, LOW);
        delay(100);
        digitalWrite(24, HIGH);
        break;
      case 0x58: // C BUTTON
        digitalWrite(22, LOW);
        digitalWrite(24, LOW);
        delay(100);
        digitalWrite(22, HIGH);
        digitalWrite(24, HIGH);
        break;
      default:
        break;
      }
    }   
}
 
/************ IR utility function ***************/
void ir_receive_interrupt(){
 
  unsigned long last_time;
 
  detachInterrupt(IR_INTERRUPT);
  last_time = micros();
   
  // confirm if reader code is correct
  uint8_t err = 0;
  while(!digitalRead(IR_PIN)){ // until change from low to high
    if((micros() - last_time) > 10000){ // interval low should be 9ms or less 
        err = true;
        break;
    }
  }
  while(digitalRead(IR_PIN)){ // until change from high to low
    if((micros() - last_time) > 15000){ // interval of reader code should be 13.5ms or less
        err = true;
        break;
    }
  }
  if(((micros() - last_time) < 13000) || (err == true)){ // Unknown code
    attachInterrupt(0, ir_receive_interrupt, FALLING);
    g_ir_available = false;
    return; // not available remote controller
  }
   
  // get data
  uint8_t receive_count = 0;
  uint8_t temp_ir_data[4] = {0};
  g_ir_data = 0;
  last_time = micros();
  while((32 > receive_count) && ((micros() - last_time) < 80000)){
     // interval of a frame data should be 76.5ms or less
    last_time = micros();
    while(!digitalRead(IR_PIN) && ((micros() - last_time) < 1000)){
     // interval of low state is about 0.56ms. 
    }
    while(digitalRead(IR_PIN) && ((micros() - last_time) < 2500)){
     // interval of a bit is between 1.125ms and 2.25ms
    }
    if((micros() - last_time) > 1500){
        bitSet(temp_ir_data[receive_count / 8], receive_count % 8);
    }
    receive_count++;
  }
   
  if(temp_ir_data[2] == (uint8_t)~temp_ir_data[3]){
        g_ir_data = temp_ir_data[2]; // set actual data
        g_ir_available = true;
  }
   
}
 
void ir_receive_start(){
  attachInterrupt(IR_INTERRUPT, ir_receive_interrupt, FALLING);
}
 
uint8_t ir_getData(){
  g_ir_available = false;
  return g_ir_data;
}
 
bool ir_available(){
  return g_ir_available;
}