Arduino初初教程9——紅外遙控

紅外遙控器發出的信號是一連串的二進制脈衝碼。爲了使其在無線傳輸過程當中免受其餘紅外信號的干擾,一般都是先將其調製在特定的載波頻率上,而後再經紅外發射二極管發射出去,而紅外線接收裝置則要濾除其餘雜波,只接收該特定頻率的信號並將其還原成二進制脈衝碼,也就是解調.
紅外接收頭如附件中所示:


這裏舉一個Arduino接受遙控器信號的例子。紅外接受頭佔用Arduino的數8。
(也能夠選擇nine_09y的帖子Arduino電子積木之紅外發射接收編解碼中的模塊)
先來看看遙控器的編碼方式,
遙控器發出的二進制脈衝碼載波頻率是38kHz,採用脈衝寬度調製,每一位的時間爲1.125ms或2.25ms ,邏輯0和邏輯1的定義如附件中圖2所示
20110716_e8c79a7acd52c6833b7fnGahEvlOo6eh 
而一個消息是由一個9ms的高電平開始,隨後有一個4.5ms的低電平,以後就是信息碼了.
1309252422_2 
例子接收圖中遙控器的VOL+按鈕的信號(信息碼0xfe01),而後讓引腳13上的LED閃爍一下.
程序以下(直接粘貼到Arduino開發環境下就可直接應用):
#define LED_RED 13//紅燈
#define IR_IN  8  //紅外接收
int Pulse_Width=0;//存儲脈寬
int  ir_code=0x00;//命令值
//定時器初始化函數
void timer1_init(void)
{
  TCCR1A = 0X00;
  TCCR1B = 0X05;//給定時器時鐘源  
  TCCR1C = 0X00;
  TCNT1 = 0X00;
  TIMSK1 = 0X00;
//禁止定時器溢出中斷
}
//執行譯碼結果函數
void remote_deal(void)
{
  switch(ir_code)
  {
  case 0xfe01://VOL+
    digitalWrite(LED_RED,HIGH);//燈亮
    delay(500);
    digitalWrite(LED_RED,LOW);//燈不亮
    break;
  }
}
//判斷邏輯值「0」和「1」子函數
char logic_value()
{
  while(!(digitalRead(8))); //低等待
  Pulse_Width=TCNT1;
  TCNT1=0;
  if(Pulse_Width>=7&&Pulse_Width<=10)//低電平560us
  {
    while(digitalRead(8));//是高就等待
    Pulse_Width=TCNT1;
    TCNT1=0;
    if(Pulse_Width>=7&&Pulse_Width<=10)//接着高電平560us
      return 0;
    else if(Pulse_Width>=25&&Pulse_Width<=27) //接着高電平1.7ms
      return 1;
  }
  return -1;
}
//接收命令碼脈衝函數
void pulse_deal()
{
  int i;
  //執行8個0
  for(i=0; i<8; i++)
  {
    if(logic_value() != 0) //不是0
        return;
  }
  //執行6個1
  for(i=0; i<6; i++)
  {
    if(logic_value()!= 1) //不是1
        return;
  }
  //執行1個0
  if(logic_value()!= 0) //不是0
      return;
  //執行1個1
  if(logic_value()!= 1) //不是1
      return;
  ir_code=0x00;//清零
  for(i=0; i<16;i++ )
  {
    if(logic_value() == 1)
    {
      ir_code |=(1<<i);
    }
  }
}
//譯碼函數
void remote_decode(void)
{
  TCNT1=0X00;      
  while(digitalRead(8))//是高就等待
  {
    if(TCNT1>=1563)  //當高電平持續時間超過100ms,代表此時沒有按鍵按下
    {
      ir_code = 0xff00;
      return;
    }  
  }
  //若是高電平持續時間不超過100ms
  TCNT1=0X00;
  while(!(digitalRead(8))); //低等待
  Pulse_Width=TCNT1;
  TCNT1=0;
  if(Pulse_Width>=140&&Pulse_Width<=141)//9ms
  {
    while(digitalRead(8));//是高就等待
    Pulse_Width=TCNT1;
    TCNT1=0;
    if(Pulse_Width>=68&&Pulse_Width<=72)//4.5ms
    {
      pulse_deal();
      return;
    }
    else if(Pulse_Width>=34&&Pulse_Width<=36)//2.25ms
    {
      while(!(digitalRead(8)));//低等待
      Pulse_Width=TCNT1;
      TCNT1=0;
      if(Pulse_Width>=7&&Pulse_Width<=10)//560us
      {
        return;
      }
    }
  }
}
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
void setup()
{
  unsigned char i;
  pinMode(LED_RED,OUTPUT);//設置與紅燈鏈接的引腳爲輸出模式
  pinMode(IR_IN,INPUT);//設置紅外接收引腳爲輸入
}
void loop()
{  
  timer1_init();//定時器初始化
  while(1)
  {
    remote_decode();  //譯碼
    remote_deal();   //執行譯碼結果
  }  
}
/////////////////////////////////////////////////////////////////
關於紅外遙控的學習,我的建議先用示波器捕捉遙控器發出的二進制編碼,經過捕捉到的內容可以解讀出按鍵的信息碼,而後再認真看一下程序中的譯碼子函數
紅外遙控的程序調起來可能會比較麻煩,可能須要反覆的調試幾回
須要多些耐心
[ 本帖最後由 晨光熹微 於 2011-7-16 00:17 編輯 ] php

附件   untitled.JPG  (20.83 KB)

2011-7-16 00:15 git

20110716_41558630e29cf4713e50W86JshXPGQNL

  luoji.JPG  (19.84 KB)

2011-7-16 00:15 函數

20110716_e8c79a7acd52c6833b7fnGahEvlOo6eh

相關文章
相關標籤/搜索