红外发射与接收
目录
目的
红外遥控是一种无线、非接触控制技术,具有抗干扰能力强,信息传输可靠,功耗低,成本低,易实现等显著优点,被诸多电子设备特别是家用电器广泛采用,并越来越多的应用到计算机系统中。本课我们就来学学红外遥控的发射和接收。
设备
Microduino-CoreSTM32是采用 STM32F103CBT6芯片的ARM开发板,采用独特的Upin7接口,大小与一枚一元硬币差不多大,完全兼容Microduino其他扩展模块。
- 其他硬件设备
- 面包板跳线 一盒
- 面包板 一块
- 红外接收头 一个
- 红外发射管(可从家里的旧遥控器中找到) 一个
- USB数据连接线 一根
- 470欧姆电阻 一个
- 按键开关 一个
原理
常用的红外线信号传输协议有ITT协议、NEC协议、Nokia NRC协议、Sharp协议、Philips RC-5协议、Philips RC-6协议,Philips RECS-80协议,以及Sony SIRC协议等。
本课采用一个NEC协议的红外发射遥控器和一个红外一体接收头,做红外的接收解码实验。采用一个红外发射头和一个红外一体接收头做红外的发送实验。
常见的红外发送和接收器如下图所示:
红外接收一体头包含了对红外信号的接收、滤波、放大等处理,能够大幅度介绍外界的干扰,方便的接收红外传输信号。
NEC协议
下面以NEC协议为例对红外收发的原理进行讲解。
NEC编码的一帧(通常按一下遥控器按钮所发送的数据)由引导码(或起始码)、地址码及数据码组成,,如下图所示。
NEC编码有8位地址码、8位命令码;地址码和命令码均传送两次,一次是原码,一次是反码,以确保可靠;PWM(脉冲宽度编码)方式;载波频率38kHz;每一位用时1.12ms或2.25ms。 引导码及数据的定义如下图所示,当一直按住一个按钮的时候,会隔110ms左右发一次引导码(重复),并不带任何数据。
NEC协议采用PWM编码,每个脉冲宽560μs,载波频率38kHz(约21个周期)。逻辑“1”需时2.25ms,逻辑“0”需时1.12ms。NEC协议的“0”和“1”的表示方法如上图所示。推荐的载波占空比为1/4或1/3。
实验一
红外接收
红外接收的实验的接线其实很简单,如上图所示。红外接收头凸出的一面朝向自己,最右边的引脚VCC接Microduino-CoreSTM32的VCC,中间的引脚GND接Microduino-CoreSTM32的GND,最左边的引脚OUT接Microduino-CoreSTM32的D8引脚。
注意:接线要仔细,不能接反,接反很容易把元器件烧坏。
程序
#include "IRremote.h"
#define Serial SerialUSB
int RECV_PIN = 8;
IRrecv irrecv(RECV_PIN);
IRsend irsend;
decode_results results;
// Dumps out the decode_results structure.
// Call this after IRrecv::decode()
void dump(decode_results *results)
{
int count = results->rawlen;
if (results->decode_type == UNKNOWN)
{
Serial.print("Unknown encoding: ");
}
else 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: ");
}
else if (results->decode_type == PANASONIC)
{
Serial.print("Decoded PANASONIC - Address: ");
Serial.print(results->panasonicAddress,HEX);
Serial.print(" Value: ");
}
else if (results->decode_type == JVC)
{
Serial.print("Decoded JVC: ");
}
Serial.print(results->decode_type, HEX);
Serial.print(results->value, HEX);
Serial.print(" (");
Serial.print(results->bits, DEC);
Serial.println(" bits)");
Serial.print("Raw (");
Serial.print(count, DEC);
Serial.print("): ");
for (int i = 0; i < count; i++)
{
if ((i % 2) == 1)
{
Serial.print(results->rawbuf[i]*USECPERTICK, DEC);
}
else
{
Serial.print(-(int)results->rawbuf[i]*USECPERTICK, DEC);
}
Serial.print(" ");
}
Serial.println("");
}
void setup()
{
irrecv.enableIRIn(); // Start the receiver
}
void loop()
{
if (irrecv.decode(&results))
{
// Serial.print(results.decode_type, HEX);
// Serial.println(results.value, HEX);
dump(&results);
irrecv.resume(); // Receive the next value
}
delay(1000);
}
程序说明: 程序需要用到IRremote库,下载地址:
- 红外接收引脚定义为Microduino-CoreSTM32的8号引脚。
- dump(decode_results *results) 函数用来判断接收到的红外码属于哪种传输协议(NEC、SONY、RC5、RC6、PANASONIC、JVC还是非协议码)。
调试
步骤一:接好电路图。
步骤二:下载IRremote库,解压到Maple IDE安装文件夹目录下的libraries文件夹中。 步骤三:拷贝实验一源代码到Maple IDE中,编译,下载。 步骤四:下载完成后,打开串口监视界面。 步骤五:用红外发射遥控把的发射头对准红外接收头,并按下遥控器上不同的按键,观察串口监视界面的变化。
结果
按遥控器上不同的按键后,串口监视界面会显示不同的按键信号,下图是分别按下1、2、3、4、5、6、7、8、9、0后收到的32位数据。
实验二
红外发送
红外发送部分,用一个按键控制红外发射头发射红外信号,当按键按下后红外接收头接收从红外发射头发射的数据,并把接收的命令显示在串口监视界面上。原理图如下所示:
如图所示红外发射头的正极接 Microduino CoreSTM32 的D12引脚,红外接收头的OUT接 Microduino CoreSTM32 的D8引脚,按键控制引脚为D2。
程序
/* IR send pin 12,IR receive pin 8
** timer 3 ch 1 for IR send data
** recv pin 8 whatever, using timer2 channel 1 for 50us sampling
** pin 8 to Sharp GP1UX311QS 38khz
*/
#include "IRremote.h"
#define Serial SerialUSB
int RECV_PIN = 8; // IR receive pin
int buttonPin = 2; //button control pin
IRrecv irrecv(RECV_PIN);
IRsend irsend;
decode_results results;
void setup()
{
pinMode(buttonPin, INPUT);
pinMode(2,OUTPUT);
irrecv.enableIRIn(); // Start the receiver
}
// Dumps out the decode_results structure.
// Call this after IRrecv::decode()
void dump(decode_results *results)
{
int count = results->rawlen;
if (results->decode_type == UNKNOWN)
{ Serial.print("Unknown encoding: "); }
else 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: "); }
else if (results->decode_type == PANASONIC)
{
Serial.print("Decoded PANASONIC - Address: ");
Serial.print(results->panasonicAddress,HEX);
Serial.print(" Value: ");
}
else if (results->decode_type == JVC)
{ Serial.print("Decoded JVC: "); }
Serial.print(results->value, HEX);
Serial.print(" (");
Serial.print(results->bits, DEC);
Serial.println(" bits)");
}
void loop()
{
long sonycmd[] = {0xA9A,0x91A,0x61A}; // power 0 7
int buttonState=digitalRead(buttonPin); //read the button state
if(buttonState==HIGH) //send the Sony command after press the button
{
irsend.sendSony(sonycmd[0],12); //send Sony power command
Serial.print("Send Sony power command: ");
Serial.print(sonycmd[0],HEX);
Serial.println(" (12 bits) ");
delay(6); // allow gap time to grow
}
else
{ digitalWrite(buttonPin,LOW); }
// IR receive
if (irrecv.decode(&results))
{
dump(&results); //get the type of the infrared data frame
irrecv.resume(); // Receive the next value
}
delay(200);
}
程序同样需要用到IRremote库,下载地址:
本程序基本上和红外接收程序相同,不同的地方是在接收前加了一段通过按键按下发送Sony红外协议命令的程序。
调试
步骤一:按照原理图连接电路图。
步骤二:复制代码到Maple IDE编译器并编译代码。
步骤三:下载代码,打开串口监视界面。
步骤四:按下按键观察串口监视界面显示的数据。
结果
- 按键未按下时,串口监视界面没有数据显示。
- 按下按键后,串口界面显示发射的命令以及发射后通过接收头接收到的命令。如下图所示:
- 大家可以通过以下函数发射不同标准的红外命令帧。
- void sendNEC(unsigned long data, int nbits);
- void sendSony(unsigned long data, int nbits);
- void sendRaw(unsigned int buf[], int len, int hz);
- void sendRC5(unsigned long data, int nbits);
- void sendRC6(unsigned long data, int nbits);
- void sendDISH(unsigned long data, int nbits);
- void sendSharp(unsigned long data, int nbits);
- void sendPanasonic(unsigned int address, unsigned long data);
- void sendJVC(unsigned long data, int nbits, int repeat);