■ 使用する機能:
- 外部割込み: attachInterrupt(1, Check_IR, CHANGE)
- 1: GR-KURUMIの3番ピンです。 リモコン受信パルスの入力
- CheckIR: 割込みが発生すると、void CheckIR(void) がコールされます。
- CHANGE: 割込みは、3番ピンの「立ち上がり」と「立ち下がり」の両方のエッジで割込みが発生します。
- 3番ピンのレベルセンス: digitalRead(IR_Pin)
- IR_Pin: #define IR_Pin 3 ・・・ 3番ピンをアサインしています。
- LOW: 3番ピンの割込みが「立ち下り」エッジで起こったことになります。
- HIGH: 3番ピンの割込みが「立ち上がり」エッジで起こったことになります。
- フリーランライマー micros()
- マイコンのリセット直後から、このタイマーが起動します。マイクロ秒単位でカウントします。
- 外部割込みが発生し、次の割込みが発生しるまでの時間を計測します。これにより、赤外線リモコンのHIGHパルスとLOWパスルの幅を計測します。
- unsigned long IR_Low_Time ; // 赤外線パルスのLOWパルスの長さ(マイクロ秒)
- unsigned long IR_High_Time; // 赤外線パルスのHIGHパルスの長さ(マイクロ秒)
- unsigned long IR_Data[Max_IR_Bits]; // 赤外線パルスのビット長(時間)を記録します。
- int IR_State; // 赤外線パルスのどの位置のビットかを保持しています。
- 0: ヘッダービットです。
- 1 から 32: データビットです。
- int IR_Active; // 赤外線パルスが有効で、そのストリーム中にいるかをチェックします。
- 0: 赤外線パルスはない。
- 1: 赤外線パルスのストリームの中にいる状態です。
- 赤外線パルスが来ると割込みがかかり、Check_ID()関数がコールされます。
- まず、digitalRead(IR_Pin) で、割込みが赤外線パスルの「立下り」なのか「立上り」なのかをチェックします。
- 赤外線パルスが「立上り」の場合: 直前のLOWパルスの時間「micros() - IR_Low_Time」を計測します。
- ②の位置: この時間が「HEADER_Low_min」より長い場合、HEADERビットが来たと判定し「IR_Active = 1」を有効にっします。
- ②の位置以外: データビットと見なせます。しかし、「Data_Low_min」よりパルスが短い場合は、ノイズによるLOWパルスですのでエラーと判断し「IR_Active = 0」とします。
- 最後の立上り: 割込みの外、つまり Loop() 関数の中で、
「if (IR_Active == 1 && micros() - IR_High_Time > IR_Tail_Max) 」を実行し赤外線パルスの終了を判定し、「IR_Active = 0」を実行します。 - 赤外線パルスが「立下り」の場合: ストリーム中にいるか「IR_Active == 1」 をチェックします。
- もし、ストリーム中にある場合は、「IR_Data[IR_State] = micros() - IR_Low_Time;」を実行しパルス幅(時間)を保存して、「IR_State++」を実行しビット位置を先に進めます。
■ 全体プログラム:
/*
Infra-red IR-remote capture program version 1.0
by Kaz Kinoshita, Insutitute of Daiichi Technologies
date of 2014-10-23
*/
#include <RLduino78.h>
#define LED_R 22 // LED Red is assigned to Pin 22
#define LED_G 23 // LED Green is assigned to Pin 23
#define LED_B 24 // LED Blue is assigned to Pin 24
#define LED_OFF 1 // LED turns off when LED port is set to LOW.
#define LED_ON 0 // LED turn on whrn the port is set to HIGH
#define IR_Pin 3
// Pin 3 is set to capture infra-red remote control signal.
// Set the interrupt polarity of the pin to low-active and high-active edge senses.
#define HEADER_Low_min 8000
// The low state of IR-HEADER is about 9000 usec (micro-second).
// I specify it must be longer than 8000 usec.
#define Data_Low_min 200
// Low state of IR data bit about 500 usec..
// Noise pulses are usually 10 to 50 mic
#define IR_Tail_Max 5000
// defines the end of IR data stream
#define Max_IR_Bits 35
// Reserve enough length of bits. This IR remote has 32 bits
unsigned long IR_Low_Time = 0; // holds IR bursting time
unsigned long IR_High_Time = 0; // holds IR high idling time
unsigned long IR_Data[Max_IR_Bits] = {
0}; // holds the bit length of each data bit by micro-sec.
unsigned long IR_Bits; // 32 bits of IR data
byte IR_ID = 0; // the first 8-bit of IR data.
byte IR_ID_N = 0; // the second 8-bit of IR data, IR_ID_N = !IR_ID
byte IR_CMD = 0; // the 3rd 8-bit of IR data
byte IR_CMD_N = 0; // the 4th 8-bit of IR data, IR_CMD_N = !IR_CMD
int IR_Active = 0; // when 1, the capturing IR data steam is valid
int IR_State = 0;
// defines the bit position of IR bit stream.
// valid IR bit steam must be 0 to 32.
void Check_IR(){ // Infra-red remote signal detection interrupt
if (digitalRead(IR_Pin) == LOW) {
if (IR_Active == 1) {
digitalWrite(LED_R, LED_ON);
IR_Data[IR_State] = micros() - IR_Low_Time;
IR_State++;
if (IR_State > Max_IR_Bits - 1) IR_State = Max_IR_Bits - 1;
}
IR_Low_Time = micros();
return;
}
else {
digitalWrite(LED_R, LED_OFF);
IR_High_Time = micros();
if(micros() - IR_Low_Time < Data_Low_min){
IR_Active = 0;
return;
}
if (micros() - IR_Low_Time > HEADER_Low_min) { // Detect the low state of HEADER
IR_Active = 1;
IR_State = 0;
}
}
}
void setup() {
Serial.begin(9600);
pinMode(LED_R, OUTPUT);
pinMode(LED_G, OUTPUT);
pinMode(LED_B, OUTPUT);
pinMode(IR_Pin, INPUT);
attachInterrupt(1, Check_IR, CHANGE); // 1 sets Pin 3 for interrupt with low/high-active edges
digitalWrite(LED_R, LED_OFF);
digitalWrite(LED_G, LED_OFF);
digitalWrite(LED_B, LED_OFF);
Serial.println("Ready for capturing IR stream!");
}
void loop() {
// Find the tail of IR bit stream
if (IR_Active == 1 && micros() - IR_High_Time > IR_Tail_Max) {
Serial.println("-- Pulse length of each IR-bit (micro seconds) --");
Serial.print("bit 0 (HEADER): ");
Serial.println(IR_Data[0]);
IR_ID = 0;
IR_ID_N = 0;
IR_CMD = 0;
IR_CMD_N = 0;
for (int i = 1; i <= 32; i++) {
if (i <= 8) {
IR_ID = IR_ID << 1;
if ( IR_Data[i] > 1500 ) IR_ID = IR_ID | 0x01;
else IR_ID = IR_ID & 0xFE;
}
if (i > 8 && i <= 16) {
IR_ID_N = IR_ID_N << 1;
if ( IR_Data[i] > 1500 ) IR_ID_N = IR_ID_N | 0x01;
else IR_ID_N = IR_ID_N & 0xFE;
}
if (i > 16 && i <= 24) {
IR_CMD = IR_CMD << 1;
if ( IR_Data[i] > 1500 ) IR_CMD = IR_CMD | 0x01;
else IR_CMD = IR_CMD & 0xFE;
}
if (i > 24 && i <= 32) {
IR_CMD_N = IR_CMD_N << 1;
if ( IR_Data[i] > 1500 ) IR_CMD_N = IR_CMD_N | 0x01;
else IR_CMD_N = IR_CMD_N & 0xFE;
}
Serial.print("bit ");
Serial.print(i);
Serial.print(" = ");
Serial.println(IR_Data[i]);
IR_Data[i] = 0; // initialize the capture data
}
Serial.println("-- ID Value --");
Serial.print("ID = ");
Serial.println(IR_ID, HEX);
Serial.print("ID_N = ");
Serial.println(IR_ID_N, HEX);
if (IR_ID == byte(~IR_ID_N) ) Serial.println("No ID Error");
else Serial.println("ID Error");
Serial.println("--CMD Value --");
Serial.print("CMD = ");
Serial.println(IR_CMD, HEX);
Serial.print("CMD_N = ");
Serial.println(IR_CMD_N, HEX);
if (IR_CMD == byte(~IR_CMD_N) ) Serial.println("No CMD Error");
else Serial.println("CMD Error");
IR_Active = 0; // Close IR-bit decoding session and wait for the next stream
IR_State = 0;
}
}
■ 実行結果
/*
Infra-red IR-remote capture program version 1.0
by Kaz Kinoshita, Insutitute of Daiichi Technologies
date of 2014-10-23
*/
#include <RLduino78.h>
#define LED_R 22 // LED Red is assigned to Pin 22
#define LED_G 23 // LED Green is assigned to Pin 23
#define LED_B 24 // LED Blue is assigned to Pin 24
#define LED_OFF 1 // LED turns off when LED port is set to LOW.
#define LED_ON 0 // LED turn on whrn the port is set to HIGH
#define IR_Pin 3
// Pin 3 is set to capture infra-red remote control signal.
// Set the interrupt polarity of the pin to low-active and high-active edge senses.
#define HEADER_Low_min 8000
// The low state of IR-HEADER is about 9000 usec (micro-second).
// I specify it must be longer than 8000 usec.
#define Data_Low_min 200
// Low state of IR data bit about 500 usec..
// Noise pulses are usually 10 to 50 mic
#define IR_Tail_Max 5000
// defines the end of IR data stream
#define Max_IR_Bits 35
// Reserve enough length of bits. This IR remote has 32 bits
unsigned long IR_Low_Time = 0; // holds IR bursting time
unsigned long IR_High_Time = 0; // holds IR high idling time
unsigned long IR_Data[Max_IR_Bits] = {
0}; // holds the bit length of each data bit by micro-sec.
unsigned long IR_Bits; // 32 bits of IR data
byte IR_ID = 0; // the first 8-bit of IR data.
byte IR_ID_N = 0; // the second 8-bit of IR data, IR_ID_N = !IR_ID
byte IR_CMD = 0; // the 3rd 8-bit of IR data
byte IR_CMD_N = 0; // the 4th 8-bit of IR data, IR_CMD_N = !IR_CMD
int IR_Active = 0; // when 1, the capturing IR data steam is valid
int IR_State = 0;
// defines the bit position of IR bit stream.
// valid IR bit steam must be 0 to 32.
void Check_IR(){ // Infra-red remote signal detection interrupt
if (digitalRead(IR_Pin) == LOW) {
if (IR_Active == 1) {
digitalWrite(LED_R, LED_ON);
IR_Data[IR_State] = micros() - IR_Low_Time;
IR_State++;
if (IR_State > Max_IR_Bits - 1) IR_State = Max_IR_Bits - 1;
}
IR_Low_Time = micros();
return;
}
else {
digitalWrite(LED_R, LED_OFF);
IR_High_Time = micros();
if(micros() - IR_Low_Time < Data_Low_min){
IR_Active = 0;
return;
}
if (micros() - IR_Low_Time > HEADER_Low_min) { // Detect the low state of HEADER
IR_Active = 1;
IR_State = 0;
}
}
}
void setup() {
Serial.begin(9600);
pinMode(LED_R, OUTPUT);
pinMode(LED_G, OUTPUT);
pinMode(LED_B, OUTPUT);
pinMode(IR_Pin, INPUT);
attachInterrupt(1, Check_IR, CHANGE); // 1 sets Pin 3 for interrupt with low/high-active edges
digitalWrite(LED_R, LED_OFF);
digitalWrite(LED_G, LED_OFF);
digitalWrite(LED_B, LED_OFF);
Serial.println("Ready for capturing IR stream!");
}
void loop() {
// Find the tail of IR bit stream
if (IR_Active == 1 && micros() - IR_High_Time > IR_Tail_Max) {
Serial.println("-- Pulse length of each IR-bit (micro seconds) --");
Serial.print("bit 0 (HEADER): ");
Serial.println(IR_Data[0]);
IR_ID = 0;
IR_ID_N = 0;
IR_CMD = 0;
IR_CMD_N = 0;
for (int i = 1; i <= 32; i++) {
if (i <= 8) {
IR_ID = IR_ID << 1;
if ( IR_Data[i] > 1500 ) IR_ID = IR_ID | 0x01;
else IR_ID = IR_ID & 0xFE;
}
if (i > 8 && i <= 16) {
IR_ID_N = IR_ID_N << 1;
if ( IR_Data[i] > 1500 ) IR_ID_N = IR_ID_N | 0x01;
else IR_ID_N = IR_ID_N & 0xFE;
}
if (i > 16 && i <= 24) {
IR_CMD = IR_CMD << 1;
if ( IR_Data[i] > 1500 ) IR_CMD = IR_CMD | 0x01;
else IR_CMD = IR_CMD & 0xFE;
}
if (i > 24 && i <= 32) {
IR_CMD_N = IR_CMD_N << 1;
if ( IR_Data[i] > 1500 ) IR_CMD_N = IR_CMD_N | 0x01;
else IR_CMD_N = IR_CMD_N & 0xFE;
}
Serial.print("bit ");
Serial.print(i);
Serial.print(" = ");
Serial.println(IR_Data[i]);
IR_Data[i] = 0; // initialize the capture data
}
Serial.println("-- ID Value --");
Serial.print("ID = ");
Serial.println(IR_ID, HEX);
Serial.print("ID_N = ");
Serial.println(IR_ID_N, HEX);
if (IR_ID == byte(~IR_ID_N) ) Serial.println("No ID Error");
else Serial.println("ID Error");
Serial.println("--CMD Value --");
Serial.print("CMD = ");
Serial.println(IR_CMD, HEX);
Serial.print("CMD_N = ");
Serial.println(IR_CMD_N, HEX);
if (IR_CMD == byte(~IR_CMD_N) ) Serial.println("No CMD Error");
else Serial.println("CMD Error");
IR_Active = 0; // Close IR-bit decoding session and wait for the next stream
IR_State = 0;
}
}
■ 実行結果
0 件のコメント:
コメントを投稿