技术热线: 4007-888-234

Arduino编程:使用红外遥控器控制继电器开关

更新时间: 2019-11-16
阅读量:8611

在本文中,英锐恩单片机开发工程师分享了一个使用红外遥控器控制继电器开关的案例。红外(IR)通信技术早在WiFi和蓝牙之前就已经存在,它仍然是实现典型家庭自动化系统主要组件的关键组件。例如,IR技术仍用于无线耳机,家庭安全系统中的入侵检测以及手持遥控器中,用于控制家庭娱乐系统(电视,DVD,音箱等),空调装置和其他家用电器。由于红外技术需要在发射器和接收器单元之间形成视线,因此它只能用于连接短距离的设备,例如在同一房间。

QQ截图20191116114651.png

在这里,将展示如何制作基于Arduino的IR接收器,以解码来自TV/DVD遥控器的IR信号。根据与遥控器上特定按钮对应的解码值,我们将对Arduino进行编程以控制多个继电器开关。

电路设置

遥控器发送的红外信号很容易受到附近其他红外源(例如加热器和白炽灯)的干扰。因此,为了使接收器区分IR信号和所有其他红外噪声源,已发射的IR信号被调制。对于调制,需要稳定的载波频率(通常为30–60 kHz),其中38Khz是最常用的载波频率。尽管有几种数字调制技术,但大多数现代消费类电子产品都使用幅移键控(ASK)来设计IR遥控器。在ASK中,载波的幅度根据数字输入信号而变化。逻辑1由一定幅度的载波信号表示,而逻辑0通过将载波幅度更改为零(或将其关闭)表示。

在此方案中,我们将使用来自电视遥控器的IR信号来控制多个继电器开关。为此,我们需要一个IR接收器电路,该电路将解调电视遥控器发送的IR信号。解调后的数字输出可以由Arduino直接解释。

TSOP1740红外接收器内置了该方案的接收电路。TSOP17XX系列是小型接收器,具有集成在一个封装中的光电探测器和前置放大器,可以用于红外遥控系统。内部还使用了带通滤波器,积分器级和自动增益控制来抑制有害噪声。名称的后两位(XX)代表带通的中心频率。因此,TSOP1740适用于40 KHz的调制IR信号。

TSOP.png

下面显示的是该方案所需的完整电路设置。TSOP17340的解调后输出将输出到Arduino引脚D11。在此演示中使用了一个双继电器控制板。两个继电器的控制引脚(IN1和IN2)由Arduino的D6和D7 I/O引脚驱动。整个电路在5V下工作。

circuit.png

此方案中使用的继电器板具有光耦合器,用于在输入控制引脚和输出继电器驱动器电路之间进行电气隔离。这两个继电器单元的板载驱动器电路可在低电平有效输入下工作。这意味着必须将IN引脚拉低以激活继电器。以下电路描述了继电器控制逻辑的工作方式。同样的电路也适用于第二继电器单元。跳线JP1允许你为输出侧(继电器及其晶体管驱动器)选择单独的电源(在板上标记为JD-VCC)。如果要为整个电路使用相同的5V电源,则需要在VCC和JD-VCC引脚之间放置一个并联跳线。从电路图中可以很容易地看出,输入端的逻辑0接通了光耦合器,然后激活了继电器。

relayboard.jpg

硬件设置完成后,我们现在将对Arduino Nano进行编程,以接收TSOP1738解调后的输出并解释遥控器上各个按钮按下的代码。不同制造商设计了许多不同的红外协议标准或数据格式,供消费类电子产品使用。最常用的协议是Philips的RC-5和RC-6,Sony的SIRC,NEC,JVC。这些协议中的每一种都有自己的发送数据格式,该格式由一些地址位和一些命令位组成。

#include <IRremote.h>
int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results;
void dump(decode_results *results) {
 int count = results->rawlen;
 if (results->decode_type == UNKNOWN) {
 Serial.println("Could not decode message");
 } 
 else {
 Serial.println("Signal received.");
 if (results->decode_type == NEC) {
 Serial.print("Decoded NEC, ");
 } 
 else if (results->decode_type == SONY) {
 Serial.print("Decoded SONY, ");
 } 
 else if (results->decode_type == RC5) {
 Serial.print("Decoded RC5, ");
 } 
 else if (results->decode_type == RC6) {
 Serial.print("Decoded RC6, ");
 }
 Serial.print("Value= ");
 Serial.print(results->value, DEC);
 Serial.print(" (");
 Serial.print(results->bits, DEC);
 Serial.println(" bits)");
 }
 
}
void setup()
{
 Serial.begin(9600);
 Serial.println("IR decoder");
 irrecv.enableIRIn(); // Start the receiver
}
int on = 0;
unsigned long last = millis();
void loop() {
 if (irrecv.decode(&results)) {
 // Wait for 0.5sec before decoding another code
 if (millis() - last > 500) {
 
 dump(&results);
 }
 last = millis(); 
 irrecv.resume(); // Receive the next value
 }
}


我们将分两个步骤为该方案开发Arduino固件。首先,我们将编写一个简单的程序来找出遥控器上特定按钮的数字代码(或十进制值)。它将读取IR接收器的输出,对消息进行解码,并在串行监视器窗口上打印出所用协议的类型以及所传输代码的十进制值。这样做的程序在下面发布(代码改编自Ken Shirriff编写的IRrelay示例)。

此测试程序的硬件设置与上面描述的相同。现在,将遥控器对准面包板上的TSOP1740模块,然后按一个按钮,你将在串行监视器窗口上看到该按钮的解码十进制值。确保串行监视器的波特率选择为9600。如果你的遥控器使用IRremote库的受支持协议列表中未提供的其他数据编码方案,则它将无法解码该代码。这里用两个不同的遥控器进行了测试:一个遥控器是Sony Blueray播放器,另一个是HP多合一电脑,它能够同时解码。在串行监视器窗口中,可以看到HP遥控器使用Philips RC-6协议,而Sony使用其自己的SIRC协议。在Sony遥控器上为VOL+和VOL-。

testserialmonitor.png

现在我们知道特定按钮按下会发送什么代码,我们可以修改代码以实现用于切换继电器电路的附加逻辑。我们将对Arduino进行编程以执行以下逻辑。

按下VOL +时,继电器1打开。
按下VOL-时,继电器1将关闭。
按下CH +时,继电器2打开。
按下CH-时,继电器2将关闭。
按下暂停按钮时,两个继电器都将关闭。
按下PLAY按钮时,两个继电器都打开。

以下为执行此任务的代码:

#include <IRremote.h>
#define SW1 6 // Relay control pins are 6 and 7
#define SW2 7
int RECV_PIN = 11; // IR receive pin is 11
IRrecv irrecv(RECV_PIN);
long int decodedCode; 
decode_results rcv;
void controlRelays(){
 if(decodedCode == 1168) digitalWrite(SW1, LOW); 
 if(decodedCode == 3216) digitalWrite(SW1, HIGH); 
 if(decodedCode == 144) digitalWrite(SW2, LOW); 
 if(decodedCode == 2192) digitalWrite(SW2, HIGH); 
 if(decodedCode == 625479){
 digitalWrite(SW1, HIGH); // All off 
 digitalWrite(SW2, HIGH); 
 }
 if(decodedCode == 363335){
 digitalWrite(SW1, LOW); // All on 
 digitalWrite(SW2, LOW);
 }
 delay(300);
}
void setup(){
 pinMode(SW1, OUTPUT);
 pinMode(SW2, OUTPUT);
 digitalWrite(SW1, HIGH); // Relay is active low, so HIGH will turn it off at startup
 digitalWrite(SW2, HIGH); 
 Serial.begin(9600);
 Serial.println("IR relay controller");
 irrecv.enableIRIn(); 
}
void loop(){
 if (irrecv.decode(&rcv)) {
 Serial.print("Signal received, Value= ");
 decodedCode = rcv.value;
 Serial.println(decodedCode, DEC);
 controlRelays();
 irrecv.resume(); 
 }
}


将程序上传到Arduino之后,享受通过遥控器打开和关闭继电器的乐趣。就可以轻松地将更多的继电器添加到Arduino的其他免费I/O引脚,并添加更多的if语句,以类似的方式控制它们。

以上就是英锐恩单片机开发工程师分享的使用红外遥控器控制继电器开关的方法。英锐恩专注单片机应用方案设计与开发,提供8位单片机、16位单片机、32位单片机