概要
赤外線モジュールを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
}
このサンプルは、以下のリモコンのA, B, Cボタンを押したときにLEDを光らせます。
このリモコンはNECフォーマットに準拠しています。サンプルではNECフォーマットに合わせた信号の分析をしてLEDを光らせる他、シリアルモニターに信号の内容を表示しています。
リモコンの購入についてはこちら(秋月電子通商Web)
#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;
}