Search

2011年7月6日 星期三

Arduino - 使用RF模組

    關於無線射頻的應用最常見的大概就是遙控玩具了所以不多做說明,要讓Arduino使用RF收發模組必須要知道Arduino的Digital pin 0 & pin 1,pin 0是RXD(Receive Data)接收資料的,pin 1是TXD(Transmit Data)送出資料的,所以要發送資料的Arduino的TXD要接上RF發射模組,接收資料的Arduino的RXD要接上RF接收模組,這樣兩個電路就可以"單向"傳輸資料了,其實原本我打算使用IR的方式控制我的小六足,但是後來發現IR會有角度的問題,所以後來就決定使用RF的方式。


準備:

  • RF收發模組(比如TG-11,頻率315MHz)
  • VirtualWire Library(解壓縮放到Arduino IDE下的libraries資料夾即可)

實驗:

    在開始之前要先看看VirtualWire Library的一些宣告跟定義,這裡這裡,vw_set_ptt_inverted用來啟動RF模組,vw_setup用來初始化傳輸速度,接著vw_set_tx_pin與vw_rx_start分別用來設定TXD與RXD的腳位,vw_rx_start則讓接收模組開始接收資料,vw_send則是要送出的資料與其長度,vw_wait_tx等資料送出完畢後返回,vw_get_message用來將接收到的資料與其長度存在buffer區塊,VW_MAX_MESSAGE_LEN是預定義的信息最大長度,兩組電路的接線也很簡單,首先兩組電路的RF模組都要接上電源以及接地(紅線與黑線),發射資料的Arduino要將Digital pin 1(TXD)接上RF發射模組的Data腳(黃線),接收資料的要將Digital pin 0(RXD)接上RF接收模組的Data腳(黃線),實際腳位會因模組的不同而有所變動,但是概念都相同的,可以看下圖是TG-11收發模組的接線圖。

發射電路:





接收電路:





程式:

    每次送出一位元組的資料,用字元"a"與"b"作為兩個狀態,當接收電路收到"a"表示設定Digital pin 13為HIGH讓上面的LED發亮,收到"b"時則將Digital pin 13設定為LOW關閉LED。

發射端:


#include <VirtualWire.h> 
const char *a = "a";
const char *b = "b"; 

void setup()
{
  vw_set_ptt_inverted(true);
  vw_setup(2400);
  vw_set_tx_pin(1);
}

void loop()
{
  delay(1000);
  
  vw_send((uint8_t *)a, strlen(a)); 
  vw_wait_tx();
  
  delay(1000);
  
  vw_send((uint8_t *)b, strlen(b)); 
  vw_wait_tx(); 
}




接收端:

#include <VirtualWire.h> 
uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;

const int LED = 13;

void setup()
{
  pinMode(LED, OUTPUT);
  digitalWrite(LED,LOW);
  
  vw_set_ptt_inverted(true);
  vw_setup(2400);
  vw_set_rx_pin(0);
  vw_rx_start();
}

void loop()
{
  if (vw_get_message(buf, &buflen)) {
    switch(buf[0])
    {
      case 'a':
      digitalWrite(LED,HIGH);
      break;
      case 'b': 
      digitalWrite(LED,LOW);
      break;
    }
  }
}




==================================


因為我的相機被人拿去使用,所以暫時無法拍攝一些DEMO....等我買了D3100在陸續補上XDD

==============2011/07/08===============

如果VirtualWire這個lib跟Servo這個lib一起compile會出現像multiple definition of `__vector_11'這類error,原因似乎是兩個lib都使用同樣的timer1,可以改用SoftwareServo這個舊版的lib解決這問題,但是控制的servo似乎有數量限制,目前在弄小六足原本是打算用兩片Arduino個別控制三隻腳,這樣會各佔用9個pin,然後再用第三片Arduino去連接RF跟一些感測器,接著在讓那片Arduino跟另外兩片控制腳的去溝通XD

22 則留言:

  1. 最近也在碰ARDUINO+RF
    遇到了問題,照你上面的程式碼沒有動作..
    我現在手中只有FSI000A跟CDR03A這塊RF接收模組
    不知道是不是沒用TG-11這個RF模組才不能動@@
    可以給我這個新手解惑一下XD

    回覆刪除
  2. 未知大大你好,FSI000A看了一下是發射模組,這部份比較簡單,理論上你Arduino的TXD也就是Digital pin 1要接FSI000A的DATA腳,然後5v接上FSI000A的VCC,GND接上GND應該就可以了,至於CDR03A看了一下也只有四支腳,理論上也是你第二塊Arduino的RXD要接上DATA然後5V接上VCC,GND接上GND。

    話說這兩個模組都是四支腳的樣子照理說有兩支是VCC跟GND然後一支DATA,剩下那個是ANT腳似乎是用來強化天線收訊的,兩個模組都一樣。

    回覆刪除
  3. 當然最糟的情況可能是你的模組有問提或是不相容

    回覆刪除
  4. 這模組有接過HT12E跟12D編解碼IC,測試過是正常的
    現在也在想,模組不相容這種方法使用...
    或是我的方法做錯,只用一塊ARDUINO作接收發先做測試
    而這樣產生問題,能請GCY大大在解惑一下THX

    回覆刪除
  5. 你可以把程式貼出來看看嗎,因為我之前好像有這樣試過,就是把發射那段程式擺在接收之後,但是因為收發沒有同步所以會是敗的喔!除非你有辦法平行處理

    回覆刪除
  6. 大致上跟你原本的程式差不多
    我是這個樣只寫的@@

    ---------------------
    #include
    const char *a = "a";
    const char *b = "b";
    uint8_t buf[VW_MAX_MESSAGE_LEN];
    uint8_t buflen = VW_MAX_MESSAGE_LEN;
    const int LED = 13;
    void setup()
    {
    pinMode(LED, OUTPUT);
    digitalWrite(LED,LOW);
    vw_set_ptt_inverted(true);
    vw_setup(2400);
    vw_set_tx_pin(1);
    vw_set_rx_pin(0);
    vw_rx_start();
    }

    void loop()

    {
    delay(1000);
    vw_send((uint8_t *)a, strlen(a));
    vw_wait_tx();
    delay(1000);
    vw_send((uint8_t *)b, strlen(b));
    vw_wait_tx();

    if (vw_get_message(buf, &buflen))
    {
    switch(buf[0])
    {
    case 'a':
    digitalWrite(LED,HIGH);
    break;

    case 'b':
    digitalWrite(LED,LOW);
    break;
    }
    }
    }

    回覆刪除
  7. 未知大大我就是說這樣會有問題,因為當你發送資料的時候接收是停止的,然後當接收的時候發送是停止的,所以建議去找兩個Arduino再來試試

    回覆刪除
  8. 感謝GCY大大的解答,去試試看兩塊版能不能成功@@

    回覆刪除
  9. 完全依循 GCY 大大的貼文程序且未做任何修改
    結果功能正常(LED#13每秒開/滅一次)

    想請問RF一般可傳輸的距離多少?
    我用 433MHz 的 RF,尚未加裝天線
    結果要在5公分內才能正常閃爍,好慘

    回覆刪除
  10. To Chris大大

    我用315MHz傳輸距離試過最遠可以隔一個房間,沒有加裝天線喔!

    所以不敢確定是不是你的RF有問題

    回覆刪除
  11. 昨重買了一個 RF $250, 結果正常了
    謝謝 GCY 大大

    回覆刪除
  12. 請問一下 我應用了你的VirtualWire Library裡面4個.pde的程式
    編譯時,會出現14:22: error: WProgram.h: No such file or directory 的問題,我在網路上找沒有WProgram.h的程式
    請問這個問題要怎樣解決

    回覆刪除
  13. WProgram.h你下載Arduino IDE裡面library就有的了,我確定022 到 1.0一定有。

    回覆刪除
  14. 大大我把WProgram.h放進去之後發現錯誤由找不到WProgram.h變成一大堆的錯誤。
    我目前是直接進到VirtualWire.cpp 把#include "WProgram.h"變成註解
    //#include "WProgram.h"
    請問沒有WProgram.h會影響到程式的運作功能嗎

    回覆刪除
  15. 請問一下
    我用的RF收發模組是(ASK發射模組 TX8)(ASK超外差接收模組RXB8)頻率:433.92 MHZ
    照大大上面的方法都沒反應...
    是不是跟他的編碼有關係?

    回覆刪除
  16. 請問rf接收器可以接任何汽車遙控器的訊號嗎

    回覆刪除
    回覆
    1. 我猜是可以的, 但要先知道你遙控器的頻率是多少

      刪除
  17. 我買的是TG-11 發射.315MHz接收模組都是4pin
    發射端跟接收端的接線都是跟您一樣
    也使用您的範例程式
    兩者距離5公分以內還算靈敏
    但超過就會LAG甚至接收不到訊號
    請問這是模組壞掉還是其他問題?
    或著供電關係?
    (有試過接筆電.行動電源.9V外接電池)

    回覆刪除
  18. 我想利用SHY-J6122TR模組+arduino(2個)+will搖桿控制遙控車,目前馬達電路跟馬達程式都可以運轉,對RF程式沒有頭緒,不知如何下手把馬達程式應用在RF程式上,是不是能請大大給我點指導。
    以下是我的馬達程式:
    #include
    #include

    ArduinoNunchuk nunchuk = ArduinoNunchuk();

    int MBa = 3; //宣告後馬達正轉訊號為pin3
    int MBb = 4; //宣告後馬達反轉訊號為pin4
    int MFa = 5; //宣告前馬達正轉訊號為pin5
    int MFb = 6; //宣告前馬達反轉訊號為pin6
    int posX, posY,potX,potY; // 暫存馬達角度的變數


    void setup()
    {
    nunchuk.init();
    pinMode(MBa, OUTPUT);
    pinMode(MBb, OUTPUT);
    pinMode(MFa, OUTPUT);
    pinMode(MFb, OUTPUT);
    }

    void loop()
    {

    nunchuk.update(); //更新數值
    posX = nunchuk.analogX;
    posY = nunchuk.analogY;
    potX = nunchuk.accelX;
    potY = nunchuk.accelY;
    if(nunchuk.zButton==1)
    {
    if(potY<540) //後退判斷
    {
    digitalWrite(MBb,HIGH);
    digitalWrite(MBa,LOW);
    delay(20);}

    else if(potY>545) //前進判斷
    {
    digitalWrite(MBa,HIGH);
    digitalWrite(MBb,LOW);
    delay(20);}

    else if(potX<540) //左轉判斷
    {
    digitalWrite(MFb,HIGH);
    digitalWrite(MFa,LOW);
    delay(20);}

    else if(potX>545) //右轉判斷
    {
    digitalWrite(MFa,HIGH);
    digitalWrite(MFb,LOW);
    delay(20);}
    else //停止轉判斷
    {
    digitalWrite(MBa,LOW);
    digitalWrite(MBb,LOW);
    digitalWrite(MFb,LOW);
    digitalWrite(MFa,LOW);
    delay(20);}
    }
    if(nunchuk.zButton==0)
    {
    if(posY<125) //後退判斷
    {
    digitalWrite(MBb,HIGH);
    digitalWrite(MBa,LOW);
    delay(20);}

    else if(posY>135) //前進判斷
    {
    digitalWrite(MBa,HIGH);
    digitalWrite(MBb,LOW);
    delay(20);}

    else if(posX<125) //左轉判斷
    {
    digitalWrite(MFb,HIGH);
    digitalWrite(MFa,LOW);
    delay(20);}

    else if(posX>135) //右轉判斷
    {
    digitalWrite(MFa,HIGH);
    digitalWrite(MFb,LOW);
    delay(20);}

    else //停止轉判斷
    {
    digitalWrite(MBa,LOW);
    digitalWrite(MBb,LOW);
    digitalWrite(MFb,LOW);
    digitalWrite(MFa,LOW);
    delay(20);}
    }
    }

    回覆刪除
  19. GCY大大您好,有幸拜讀您的文章。請教一下,此無線模組是可以以一對多的模式?例如一個發放端,兩個接收端?打擾您了。感謝。

    回覆刪除
  20. gcy 大大你好,想請問一下我使用315MHz接收發射模組,照著上面的程式來做,為什麼會都沒反應呢?使用uno板子

    回覆刪除
  21. 你好 我想請問一下關於實驗內容第一段的部分 這裡或這裡 是表示什麼意思??

    回覆刪除