前述
灵感来源:看了网上这么大红外发送接收的教程,普遍发现都是用一个Arduino单独进行接收发送,于是我就产生了一个灵感:用一块 Arduino uno 板同时进行红外发送和接收!
这是我的第一篇博客,写的可能不太好,希望这篇文章对你有所启发!谢谢!
为什么要用一块Arduino同时进行红外发送和接收
有些时候我们的红外遥控器距离不够远,这时,我们希望找到一个通信中间站来进行信号的转接,这时,我们就可以用Arduino接收数据,再进行发送,这样我们Arduino就相当于一个中继器了!
又或者说有些时候,我们想让Arduino接收数据,但是板子有时候会有异常,这时我们希望板子通过红外来反馈数据告诉我们出现了什么问题。(相信这个还有更多的应用,有待开发)
注意
这篇文章并不能让你实现用一块Arduino接收到它自己发射的红外信号!!!
接下来我讲了一下红外发送和接收的原理(基于定时器),如果你想快速实现上述功能,你只需阅读最后一个板块(即总结部分)。
单块Arduino红外接收和单块Arduino红外发送
这个相信大家在网上可以找到很多的博客和教程,这里我就不具体的说了,具体的请自行去网上查找,这里我就推荐一篇写的比较好的关于红外发射和接收的文章
https://www.arduino.cn/thread-1220-1-1.html(红外接收篇)
https://www.arduino.cn/thread-1394-1-1.html (红外发射篇)
单块Arduino红外同时进行红外发送和接收
发送
我们知道,红外接收已经封装好了库函数,在setup里面有一句很重要的话:
irrecv.enableIRIn(); // Start the receiver
这句话什么意思?就是初始化红外接收,其实在库文件里我们可以看到Arduino是怎么初始化红外接收的。那我们就一起来看看库文件里面的函数原型吧!
这句话很重要,是重置定时器2的意思!!!
接收
现在我们再来看看发送的函数。
看到画横线的没有?interrupt 是定时器2中断的意思!
注:对定时器不太了解的自行百度!
可见如果使用了这个发送函数,那么下一次接收的时候定时器2的计数就不会是从0开始了,这样接收函数无法正常执行(具体原因这里就不具体解释了,你可以去查查相关资料,简单的说就是接收到的波形不是完整的,这样你的单片机就无法判断,甚至无法解析,卡在某一处地方),接收红外波会让红外波形紊乱,这时定时器无法正常使用了,由此我们需要重新将定时器2的计数清零(当然,你也可以修改上图中的定时器中断换为其他定时器)。
总结
最后,无论前面你看没有看懂,你只要记住,每次使用发送函数发送完红外后就加一句代码
irrecv.enableIRIn(); // Start the receiver
就可以再次进行再次的接收了!!!
你可以试下没有这句话的结果。
/* D5接灯泡 ,D3接红外发射头,D11接红外接收器 */
#include <IRremote.h>
int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
IRsend irsend;
decode_results results;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);//串口通信
irrecv.enableIRIn(); // Start the receiver
pinMode(5,OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
if (irrecv.decode(&results))
{
Serial.println(results.value, HEX);
if(results.value==0x00FF38C7)//key : OK (对应红外遥控器的OK键)
{
digitalWrite(5,LOW);
}
if(results.value==0x00FF9867)//key ;0
{
digitalWrite(5,HIGH);
delay(1000);
}
irsend.sendNEC(0x00FF9867, 32);//模拟发送 OK
irrecv.resume(); // Receive the next value
}
}
最后附上一个代码示例:
两个单片机上同时烧这个程序就能看到效果了!(一个板子接收自己发射的信号还是不太行,因为我们Arduino程序时一直执行的,不能在接收的同时进行发送,可能分别调用不同的计时器,再用上线程理论上可以实现,但是我还没试过)
/* D5接灯泡 ,D3接红外发射头,D11接红外接收器 */
#include <IRremote.h>
int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
IRsend irsend;
decode_results results;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);//串口通信
irrecv.enableIRIn(); // Start the receiver
pinMode(5,OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
if (irrecv.decode(&results))
{
Serial.println(results.value, HEX);
if(results.value==0x00FF38C7)//key : OK (对应红外遥控器的OK键)
{
digitalWrite(5,LOW);
}
if(results.value==0x00FF9867)//key ;0
{
digitalWrite(5,HIGH);
delay(1000);
}
irsend.sendNEC(0x00FF9867, 32);//模拟发送 OK
irrecv.enableIRIn();
irrecv.resume(); // Receive the next value
}
}