如视频无法正常播放,可点击这里前往B站观看
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
/* * 学霸型红外遥控器 * 太极创客 http://www.taichi-maker.com/ * Ver. 1.2 - 01/07/2017 * =====================功能说明===================== * 利用Arduino开发板记录并“重放”红外遥控信号 * 用户可以使用家中控制电器用的红外遥控器对准本装置的 * 红外接收器,本装置可将接收到的红外遥控信号记录至EEPROM。 * 当用户按下"发射"按键时,红外LED会发射记录的红外遥控信号 * 从而控制家中电器。 * * 本示例程序主要内容借鉴Ken Shirriff 的 IRremote 库示例程序IRrecord。 * * 本程序基于Ken Shirriff开发的IRremote库。如需获得该库文件 * 可前往以下网址获得: * http://arcfn.com (Ken Shirriff个人博客) * http://www.taichi-maker.com/ (太极创客官网) * * =====================电路连接====================== * 红外接收器 1838B OUT 引脚 --- Arduino Uno 引脚 11 * 红外发射 LED 正极 --- Arduino Uno 引脚 3 * 按键开关 --- Arduino Uno 引脚 12 * * 如需获得详细电路连接说明图,请参阅太极创客网站: * http://WWW.TAICHI-MAKER.COM * * 此示例程序为配合太极创客制作的 * 《零基础入门学用ARDUINO教程-智能应用篇》使用 * 版本更新说明 * V1.1 使用put get来 进行EEPROM存取 * V1.2 针对IRrecord代码进行优化 */ #include <IRremote.h> #include <EEPROM.h> #define codeTypeEAddr 0 // 存放红外信号编码类型EEPROM地址 #define codeLenEAddr 1 // 存放红外信号编码长度EEPROM地址 #define toggleEAddr 2 // 存放红外信号RC5/RC6类型EEPROM地址 #define codeValueEAddr 3 // 存放红外信号数值EEPROM地址 #define RECV_PIN 11 // 红外接收器 OUT 引脚 --- Arduino 引脚11 #define BUTTON_PIN 12 // 按键开关 --- Arduino 引脚12 #define STATUS_PIN LED_BUILTIN // 状态显示LED --- 开发板内置LED IRrecv irrecv(RECV_PIN); // 红外遥控接收器对象 IRsend irsend; // 红外遥控发射对象 decode_results results; // 储存接收到的红外遥控信息 void setup() { Serial.begin(9600); irrecv.enableIRIn(); // 启动红外接收 pinMode(BUTTON_PIN, INPUT_PULLUP); pinMode(STATUS_PIN, OUTPUT); delay(10); loadEepromValues(); // 从EEPROM中读取红外信号信息(具体信息请见函数部分) } // 红外信号存储变量 int codeType; // 红外信号编码类型 unsigned long codeValue; // 存放红外信号数值(如果不是raw型) unsigned int rawCodes[RAWBUF]; // raw型信号 int codeLen; // 红外信号编码长度 int toggle; // 红外信号RC5/RC6类型 // 记录收到的红外信号 void storeCode(decode_results *results) { codeType = results->decode_type; int count = results->rawlen; if (codeType == UNKNOWN) { //如果收到的信号是无法识别的协议,则存储为raw型数据 Serial.println("Received unknown code, saving as raw"); codeLen = results->rawlen - 1; // 存储raw型信号: // 将首个数值放弃(间隙) // 将信号转化为毫秒 // 细微调整信号内容,将信息变短将空档间隙变长从而取消红外接收信号的扰动 for (int i = 1; i <= codeLen; i++) { if (i % 2) { // 信号 rawCodes[i - 1] = results->rawbuf[i]*USECPERTICK - MARK_EXCESS; Serial.print(" m"); } else { // 空档间隙 rawCodes[i - 1] = results->rawbuf[i]*USECPERTICK + MARK_EXCESS; Serial.print(" s"); } Serial.print(rawCodes[i - 1], DEC); } Serial.println(""); } else { if (codeType == NEC) { //如果是NEC协议类型 Serial.print("Received NEC: "); if (results->value == REPEAT) { // Don't record a NEC repeat value as that's useless. Serial.println("repeat; ignoring."); return; } } else if (codeType == SONY) { //如果是SONY协议类型 Serial.print("Received SONY: "); } else if (codeType == PANASONIC) { //如果是PANASONIC协议类型 Serial.print("Received PANASONIC: "); } else if (codeType == JVC) { //如果是JVC协议类型 Serial.print("Received JVC: "); } else if (codeType == RC5) { //如果是RC5协议类型 Serial.print("Received RC5: "); } else if (codeType == RC6) { //如果是RC6协议类型 Serial.print("Received RC6: "); } else { Serial.print("Unexpected codeType "); //无法识别信号 Serial.print(codeType, DEC); Serial.println(""); } Serial.println(results->value, HEX); //输出信号数值 codeValue = results->value; codeLen = results->bits; } writeEepromVal(); //将收到的信号信息储存于eeprom } // 发射红外信号 void sendCode(int repeat) { if (codeType == NEC) { //如果是NEC协议信号 if (repeat) { //且如果是发射重复信号 irsend.sendNEC(REPEAT, codeLen); //发射NEC协议的重复信号 Serial.println("Sent NEC repeat"); } else { irsend.sendNEC(codeValue, codeLen); //否则发射NEC协议红外指令信号 Serial.print("Sent NEC "); Serial.println(codeValue, HEX); //串口监视器输出红外指令信号数值 } } else if (codeType == SONY) { // 发射的信号是SONY协议 irsend.sendSony(codeValue, codeLen); // 发射SONY协议红外指令信号 Serial.print("Sent Sony "); Serial.println(codeValue, HEX); } else if (codeType == PANASONIC) { // 发射的信号是PANASONIC协议 irsend.sendPanasonic(codeValue, codeLen); // 发射PANASONIC协议红外指令信号 Serial.print("Sent Panasonic"); Serial.println(codeValue, HEX); } else if (codeType == JVC) { // 发射的信号是JVC协议 irsend.sendJVC(codeValue, codeLen, false); // 发射JVC协议红外指令信号 Serial.print("Sent JVC"); Serial.println(codeValue, HEX); } else if (codeType == RC5 || codeType == RC6) { // 发射的信号是RC5或RC6协议 if (!repeat) { // 新按键按下后反转toggle位 toggle = 1 - toggle; } // 将toggle位放入信号代码中发送 codeValue = codeValue & ~(1 << (codeLen - 1)); codeValue = codeValue | (toggle << (codeLen - 1)); if (codeType == RC5) { // 发射的信号是RC5协议 Serial.print("Sent RC5 "); Serial.println(codeValue, HEX); irsend.sendRC5(codeValue, codeLen); } else { // 发射的信号是RC6协议 irsend.sendRC6(codeValue, codeLen); Serial.print("Sent RC6 "); Serial.println(codeValue, HEX); } } else if (codeType == UNKNOWN /* i.e. raw */) { // 假设信号频率 38 KHz irsend.sendRaw(rawCodes, codeLen, 38); Serial.println("Sent raw"); } } int lastButtonState; // 此变量用于判断发射红外信号的按键开关所处的状态 void loop() { int buttonState = !digitalRead(BUTTON_PIN); // 读取当前的按键开关状态(检查用户是否按下了按键开关) if (lastButtonState == HIGH && buttonState == LOW) { // 如果按键开关是被按下后再抬起的 Serial.println("Released"); // 通过串口监视器输出"按键抬起" irrecv.enableIRIn(); // 启动红外接收器信号接收 } if (buttonState) { // 如果按键开关处于被按下的状态 Serial.println("Pressed, sending"); // 通过串口监视器输出"按键按下" digitalWrite(STATUS_PIN, HIGH); // 闪烁状态显示红外LED告知用户当前"学霸遥控器"正在发射红外信号(点亮LED) sendCode(lastButtonState == buttonState); // 更新按键开关状态变量 digitalWrite(STATUS_PIN, LOW); // 闪烁状态显示红外LED告知用户当前"学霸遥控器"正在发射红外信号(熄灭LED) delay(50); // 信号发射间歇 } else if (irrecv.decode(&results)) { // 如果按键开关处于没有被按下的状态,则实时检查红外接收器并对接收到的信号进行解码 // 如果接收到的红外信号可以通过decode函数成功解码 digitalWrite(STATUS_PIN, HIGH); // 闪烁状态显示红外LED告知用户当前"学霸遥控器"正在发射红外信号(点亮LED) storeCode(&results); // 将解码的红外信号信息进行储存(非EEPROM储存) irrecv.resume(); // 恢复红外接收器 digitalWrite(STATUS_PIN, LOW); // 闪烁状态显示红外LED告知用户当前"学霸遥控器"正在发射红外信号(熄灭LED) } lastButtonState = buttonState; // 更新按键开关状态变量 } // 通过EEPROM读取红外信号信息 // 每次Arduino通电后,都会从EEPROM中读取存储的红外信号信息。 // 从而确保"学霸遥控器"在断电后依然可以保持上一次运行时所存储的 // 红外信号信息。 void loadEepromValues(){ codeType = EEPROM.read(codeTypeEAddr); delay(10); codeLen = EEPROM.read(codeLenEAddr); delay(10); toggle = EEPROM.read(toggleEAddr); delay(10); toggle = EEPROM.read(toggleEAddr); delay(10); EEPROM.get(codeValueEAddr, codeValue); } // 将红外信号信息储存于EEPROM // 每一次"学霸遥控器"接收到新的红外遥控信号 // 都将最新接收的红外遥控器储存于EEPROM // 从而确保信号信息不会因为Arduino断电而丢失 void writeEepromVal(){ EEPROM.write(codeTypeEAddr, codeType); delay(10); EEPROM.write(codeLenEAddr, codeLen); delay(10); EEPROM.write(toggleEAddr, toggleEAddr); delay(10); EEPROM.put(codeValueEAddr, codeValue); delay(10); } |