红外发射与接收

来自Microduino Wikipedia
跳转至: 导航搜索

目的

红外遥控是一种无线、非接触控制技术,具有抗干扰能力强,信息传输可靠,功耗低,成本低,易实现等显著优点,被诸多电子设备特别是家用电器广泛采用,并越来越多的应用到计算机系统中。本课我们就来学学红外遥控的发射和接收。

设备

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);

视频