/*
IRremote
An IR LED must be connected to Arduino PWM pin 3.
Copyright Ken Shirriff
http://arcfn.com
2019.7.16 By MGP.
Only for Air conditioner. https://www.mygraphpaper.com blog.
*/
#include <IRremote.h>
//請注意執行本程式前, 需將 IRremoteInt.h 內 RAWBUF, _GAP 改回預設值
//IRremoteInt.h
//#define RAWBUF 101
//#define _GAP 5000
//創維機頂盒 遙控器數字 0~9 的NEC編碼
//N00~N09必須有值,沒有的請補 0
#define N00 0x80BFE11E
#define N01 0x80BF49B6
#define N02 0x80BFC936
#define N03 0x80BF33CC
#define N04 0x80BF718E
#define N05 0x80BFF10E
#define N06 0x80BF13EC
#define N07 0x80BF51AE
#define N08 0x80BFD12E
#define N09 0x80BF23DC
//自家的冷氣空調編碼參數
//所有的 rawData_X 陣列必須有值,沒有的請補 byte rawData_X[1] = { 0 }; //(X為對應的數字)
#define RAW_HDR_MARK 3350
#define RAW_HDR_SPACE 1800
#define RAW_BIT_MARK 400 // 450 -> 17 times. 400 -> 66 times. 350 -> 55 times.
#define RAW_ONE_SPACE 1350 // 1350 -> 11 times. 1300 -> 11 times. 500 -> 65 times.
#define RAW_ZERO_SPACE 500 // 500 -> 65 times. 450 -> 40 times. 400 -> 2 times.
#define RAW_RPT_MARK 400 //Repeat Gap
#define RAW_RPT_SPACE 16950
int rawData_Bits = 144 ;
//0 關機 (不用考慮其它參數設定)
byte rawData_0[18] = { 0xC4, 0xD3, 0x64, 0x80, 0x0, 0x0, 0x18, 0xB0, 0x6C, 0x2, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8 };
//1 保留 不使用的數字請用下行宣告做預設值
byte rawData_1[1] = { 0 };
//2 保留 不使用的數字請用下行宣告做預設值
byte rawData_2[1] = { 0 };
//3 保留 不使用的數字請用下行宣告做預設值
byte rawData_3[1] = { 0 };
//4 保留 不使用的數字請用下行宣告做預設值
byte rawData_4[1] = { 0 };
//5 快速冷房:開機 , 冷氣 , 25度 , 風速4級(最大) , 風向自動
byte rawData_5[18] = { 0xC4, 0xD3, 0x64, 0x80, 0x0, 0x4, 0x18, 0x90, 0x6C, 0x22, 0x46, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4C };
//6 一般使用:開機 , 冷氣 , 26度 , 風速自動, 風向自動
byte rawData_6[18] = { 0xC4, 0xD3, 0x64, 0x80, 0x0, 0x4, 0x18, 0x50, 0x6C, 0x2, 0x46, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF4 };
//7 一般使用:開機 , 冷氣 , 27度 , 風速自動, 風向自動
byte rawData_7[18] = { 0xC4, 0xD3, 0x64, 0x80, 0x0, 0x4, 0x18, 0xD0, 0x6C, 0x2, 0x46, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC };
//8 一般使用:開機 , 冷氣 , 28度 , 風速自動, 風向自動
byte rawData_8[18] = { 0xC4, 0xD3, 0x64, 0x80, 0x0, 0x4, 0x18, 0x30, 0x6C, 0x2, 0x46, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8C };
//9 搭配風扇:開機 , 冷氣 , 29度 , 風速自動, 風向自動
byte rawData_9[18] = { 0xC4, 0xD3, 0x64, 0x80, 0x0, 0x4, 0x18, 0xB0, 0x6C, 0x2, 0x46, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4C };
//以下為程式碼--------------------------------------------------------------------------------------------------------------------------
#define IR_NUM_SIZE 10 //使用0-9,共10個按鍵
int recvPin = 2; //紅外線接收在 Pin2; 發射內定在 Pin3
//int Pin9_SW = 9; //Pin9 按鈕保留
int Recv_Enable_LED_Pin = 10; //Pin10 啟動指示燈
int LED_Buzzer_Pin = 11; //Pin11 動作指示燈及聲音
int khz = 38; //使用 38kHz 頻率發射
IRrecv irrecv(recvPin); //設定接收用 Pin
IRsend irsend; //發射用
decode_results results; //儲存接收結果用
uint8_t IR_MAP_Index; //儲存找到對應的 0-9 數字
struct NUM_MAP { //將0-9的紅外線編碼對應成數字 0-9 ,方便比對搜尋
unsigned long IR_CODE;
uint8_t INDEX_NUM;
};
static struct NUM_MAP IR_MAP[IR_NUM_SIZE] = {{N00, 0}, {N01, 1}, {N02, 2}, {N03, 3}, {N04, 4}, {N05, 5}, {N06, 6}, {N07, 7}, {N08, 8}, {N09, 9}};
//控制 動作指示燈及聲音
void ST_LED_Buzzer (int Send_Status) {
while ( Send_Status > 0 ) {
if (Send_Status >= 5) {
digitalWrite(LED_Buzzer_Pin, HIGH);
delay(400);
digitalWrite(LED_Buzzer_Pin, LOW);
delay(400);
Send_Status = Send_Status - 5;
} else {
digitalWrite(LED_Buzzer_Pin, HIGH);
delay(150);
digitalWrite(LED_Buzzer_Pin, LOW);
delay(150);
Send_Status = Send_Status - 1;
}
}
}
//發送紅外線編碼陣列, 位元由左至右發送, 資料共計 rawData_Bits 位元
//void RAWIRSend(發送陣列資料, 陣列大小, 發射位元數, 發射頻率)
void RAWIRSend(byte SendRAWData[], unsigned int SendRAWData_Len, unsigned int SendRAWData_Bits, unsigned int hz)
{
int Rep_Temp = 0;
unsigned int rawData_Bits_Count =0;
byte Mask = 1;
if (RAW_RPT_SPACE > 0) Rep_Temp = 2;
else Rep_Temp = 1;
irsend.enableIROut(hz); // khz
irsend.space(max(RAW_HDR_MARK,RAW_HDR_SPACE)); //Initial signal
for (int j = 0; j < Rep_Temp; j++) { // if Repeat
//Start Single
irsend.mark(RAW_HDR_MARK);
irsend.space(RAW_HDR_SPACE);
for (unsigned int i = 0; i < SendRAWData_Len; i++) {
for (Mask = B10000000; Mask > 0; Mask >>= 1) {
if (rawData_Bits_Count < SendRAWData_Bits) {
if (SendRAWData[i] & Mask) {
//Bit 1
irsend.mark(RAW_BIT_MARK);
irsend.space(RAW_ONE_SPACE);
}
else {
//Bit 0
irsend.mark(RAW_BIT_MARK);
irsend.space(RAW_ZERO_SPACE);
}
rawData_Bits_Count++;
}
}
}
if (Rep_Temp > 1) {
//Send Repeat Single
irsend.mark(RAW_RPT_MARK);
irsend.space(RAW_RPT_SPACE);
}
irsend.space(max(RAW_HDR_MARK,RAW_HDR_SPACE)); //Stop Single
}
}
//初始設定
void setup()
{
Serial.begin(9600); //與電腦序列埠通訊連接用
irrecv.enableIRIn(); //充許接收紅外線信號
pinMode(Recv_Enable_LED_Pin, OUTPUT); //初始 啟動指示燈 腳位
pinMode(LED_Buzzer_Pin, OUTPUT); //初始 動作指示燈及聲音 腳位
pinMode(13, OUTPUT); //初始 開發板指示燈 腳位
digitalWrite(Recv_Enable_LED_Pin, HIGH);//打開 啟動指示燈, 要關閉請改 LOW
digitalWrite(LED_Buzzer_Pin, LOW); //關閉 動作指示燈及聲音
digitalWrite(13, HIGH); //打開 主板指示燈, 要關閉請改 LOW
}
//主程式迴圈
void loop() {
if (irrecv.decode(&results)) { //是否偵測到紅外線信號
if (results.decode_type == NEC) { //判斷為哪個數字鍵, 只偵測 NEC 編碼
Serial.print("NEC Code : "); //提供序列埠監看
Serial.print(results.value, HEX);
IR_MAP_Index = IR_NUM_SIZE;
for (uint8_t i = 0; i < IR_NUM_SIZE; i++) {
if (results.value == IR_MAP[i].IR_CODE) {
IR_MAP_Index = IR_MAP[i].INDEX_NUM;
break;
}
}
Serial.print(" Map Index : ");
Serial.println(IR_MAP_Index, DEC);
if (IR_MAP_Index < IR_NUM_SIZE) { //是否有找到對應的數字鍵
delay(100); //收發間隔,穩定用
switch (IR_MAP_Index) { //保留每個數字對應的程式操作空間
case 0:
ST_LED_Buzzer (10); //蜂鳴器先叫, 以免和冷氣混在一起
RAWIRSend(rawData_0, sizeof(rawData_0) / sizeof(rawData_0[0]), rawData_Bits, khz);
break;
case 1:
ST_LED_Buzzer (1); //蜂鳴器先叫, 以免和冷氣混在一起
RAWIRSend(rawData_1, sizeof(rawData_1) / sizeof(rawData_1[0]), rawData_Bits, khz);
break;
case 2:
ST_LED_Buzzer (2); //蜂鳴器先叫, 以免和冷氣混在一起
RAWIRSend(rawData_2, sizeof(rawData_2) / sizeof(rawData_2[0]), rawData_Bits, khz);
break;
case 3:
ST_LED_Buzzer (3); //蜂鳴器先叫, 以免和冷氣混在一起
RAWIRSend(rawData_3, sizeof(rawData_3) / sizeof(rawData_3[0]), rawData_Bits, khz);
break;
case 4:
ST_LED_Buzzer (4); //蜂鳴器先叫, 以免和冷氣混在一起
RAWIRSend(rawData_4, sizeof(rawData_4) / sizeof(rawData_4[0]), rawData_Bits, khz);
break;
case 5:
ST_LED_Buzzer (5); //蜂鳴器先叫, 以免和冷氣混在一起
RAWIRSend(rawData_5, sizeof(rawData_5) / sizeof(rawData_5[0]), rawData_Bits, khz);
break;
case 6:
ST_LED_Buzzer (6); //蜂鳴器先叫, 以免和冷氣混在一起
RAWIRSend(rawData_6, sizeof(rawData_6) / sizeof(rawData_6[0]), rawData_Bits, khz);
break;
case 7:
ST_LED_Buzzer (7); //蜂鳴器先叫, 以免和冷氣混在一起
RAWIRSend(rawData_7, sizeof(rawData_7) / sizeof(rawData_7[0]), rawData_Bits, khz);
break;
case 8:
ST_LED_Buzzer (8); //蜂鳴器先叫, 以免和冷氣混在一起
RAWIRSend(rawData_8, sizeof(rawData_8) / sizeof(rawData_8[0]), rawData_Bits, khz);
break;
case 9:
ST_LED_Buzzer (9); //蜂鳴器先叫, 以免和冷氣混在一起
RAWIRSend(rawData_9, sizeof(rawData_9) / sizeof(rawData_9[0]), rawData_Bits, khz);
break;
}
irrecv.enableIRIn(); //IRRemote 在發射的時候會把接收功能停掉, 重開接收
} else {
irrecv.resume(); //沒收到定義的 0-9 信號, 重新接收
}
}
irrecv.resume(); //沒收到NEC信號, 重新接收
}
}