Let's Make Robots!

Arduino RF Communication using RX & TX link Modules

RF communication link between two Arduinos
  • Control method:

This Tip/Walk-Through will guide you through a simple one way communication link between two Arduinos.

The Project uses these RX/TX Radio Frequency (RF) Link Modules.

Edit :- Links updated - old ones where retired .Boooooo

(Thanks to Fritsl for bringing these cool babies to my attention ,i just had to try them out on my arduino and i am well impressed with thier performance )

Both Transmitter and Receiver together cost less than two tin cans with a piece of long string connected between !!!!!!!

You will have to download the Virtualwire.h library and install it to your arduinos  hardware/libraries folder

More info on the Virtualwire communications library can be found http://www.open.com.au as pdf file


Receiver :- Basic link Arduino Mega using a  RF Link Receiver - 315Mhz


Only Four wires are required, i have used a audio cable from a cd drive which i rewired to accept the cables (neat).

Yellow is the Antenna - approx 30cm long (other end connected to thin air)

Red is connected to 5 Volts

White is the Received data (in my case connected to pin 23 on the mega - can be easily assigned to another pin)

Black is Ground (it has three separate ground pins all connected together!!!!!!)


 // Receiver Code     (as the code is very short i post direct here, its adapted from Mike McCauleys pdf file above)


// RF Link using VirtualWire to receive messages
// simplex (one-way) receiver with a 315MHz RF Link Receiver module
// rx pin 23 on mega


#include <VirtualWire.h>  // you must download and install the VirtualWire.h to your hardware/libraries folder
#undef int
#undef abs
#undef double
#undef float
#undef round
void setup()
{
    Serial.begin(9600);    

// Initialise the IO and ISR
    vw_set_ptt_inverted(true);    // Required for RX Link Module
    vw_setup(2000);                   // Bits per sec
    vw_set_rx_pin(23);           // We will be receiving on pin 23 (Mega) ie the RX pin from the module connects to this pin.
    vw_rx_start();                      // Start the receiver
}

void loop()
{
    uint8_t buf[VW_MAX_MESSAGE_LEN];
    uint8_t buflen = VW_MAX_MESSAGE_LEN;

    if (vw_get_message(buf, &buflen)) // check to see if anything has been received
    {
    int i;
     // Message with a good checksum received.
        
    for (i = 0; i < buflen; i++)
    {
        Serial.print(buf[i]);  // the received data is stored in buffer
        }
    Serial.println("");
     }
}


 

 

 


 Transmitter :- Basic link using an  Arduino Duemilanova and a  RF Link Transmitter - 315Mhz


 

This also has 4 wires and the same trick with the cd audio socket to make neat connection.

Black connected to Ground

White is the transmit data cable connected to pin 3 on the Arduino (however this is easy to re-assign to suit your needs)

Red is the power supply connected to 5 Volt pin on Arduino (actually you can apply anywhere between 2 Volts and 12 Volts - the higher the voltage the stronger the RF signal)

Grey (sticking out of the Top is the Antenna - around 30cm long


// Transmitter Code


 

// RF Link using VirtualWire to Transmit messages
// simplex (one-way) receiver with a 315MHz RF Link Transmitter module
// tx pin 3 on Duemilanova (arduino)

 
#include <VirtualWire.h>  // you must download and install the VirtualWire.h to your hardware/libraries folder
#undef int
#undef abs
#undef double
#undef float
#undef round
void setup()
{
     // Initialise the IO and ISR
    vw_set_ptt_inverted(true); // Required for RF Link module
    vw_setup(2000);                 // Bits per sec
    vw_set_tx_pin(3);                // pin 3 is used as the transmit data out into the TX Link module, change this to suit your needs.
}

void loop()
{
    const char *msg = "LMR-II Rocks";       // this is your message to send

   vw_send((uint8_t *)msg, strlen(msg));
   vw_wait_tx();                                          // Wait for message to finish
   delay(200);
}


 


Power them both up and switch on the Serial monitor to 2400 Baud on the receiving Arduino (mega in our case)

 

Then Hey Presto Communication link established......... up to 152.4 Meters (thats 500 feet in old currency)

I tested (Tx at 5 Volts) from my Basement to roof (5 stories) no problem ( Mega impressed)

Ending Side Mystery :- Why did i use pin 23 as the Rx pin on the Arduino Mega ?

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Hello , how can I get these parts , please ?

Please contact me : albwasil@live.com

 

Or via my blog http://www.albwasil.com/

Just click on the blue RX/TX links at start of blog and you will be zapped into the right direction.

sparkfun actually doesn't sell them anymore and don't have a suggested replacement which sucks! They don't have a supplier anymore

Thanks for tip off......... No worries they have equivalents ......see new links at start of blog........

Again trying to understand this, all I want to do is to receive the value "A" which I have. It writes it to me via serial.

Problem comes when trying to use a IF statement at it, like I want my robot to drive forward when the letter A is sent.
But C++ stops me from using it with this error:

 

MotorIC.cpp: In function 'void loop()':

MotorIC:58: error: ISO C++ forbids comparison between pointer and integer

 

 

How can I convert the char message, to something I can use?

 

   uint8_t buf[VW_MAX_MESSAGE_LEN];

    uint8_t buflen = VW_MAX_MESSAGE_LEN;

 

    if (vw_get_message(buf, &buflen)) // Non-blocking

    {

int i; 

// Message with a good checksum received, dump it.

for (i = 0; i < buflen; i++)

{

        message = (buf[i]);

        }

     }

 

     Serial.println(message);

 

     if (message == "A")

         Drive(0);

}

 

You are comparing pointer and integer because "A" with double quotes is a C string and C strings are pointers (char *). To fix that compilations error change your code to this:
if (message == 'A') // Notice single quotes

By the looks of it you may have some other problems with that code snippet but I'll leave resolving them to you for now :-)

 

Hi  Gareth!

I'm with a little bit of difficult with sending and receiving numbers. Here is my problem: I'm making a automatic time measurement for mountain bike. In the start, the biker will cross for a optic sensor that will stop the time and send the time to the arduino, that will be on the bike with a lcd screen (arduino need to stored this time, like the time1 for example). When the athlete cross the finish other optic sensor will send the time to the arduino in the bike (like time2), that will make a simple subtraction and give the total time from the trail. Star and finish i will use 2 arduino pro mini with two 315MHZ transmitter and int the bike i will use one 315MHZ receiver and a arduino pro mini. My problem is how the receiver will differentiate the time transmitted from the start and the finish, to store the correct time1 and time2. I was thinking to put an "A" and a "B" in the first buf position for each one. So, by this letter i can make a simple switch in the first position for the receiving. But how can i attribute the others buf position to a time1 and time2 variable? And how can i send the number with "A" and "B" in the first position?

Receiver:

void setup()
{
    Serial.begin(9600);  
    vw_set_ptt_inverted(true);  
    vw_setup(2000);                 
    vw_set_rx_pin(23);         
    vw_rx_start();                    
}

void loop()
{
    uint8_t buf[VW_MAX_MESSAGE_LEN];
    uint8_t buflen = VW_MAX_MESSAGE_LEN;
    if (vw_get_message(buf, &buflen)) {
       switch (buf[0])
       {
           case 'A':
           time1
           break;
           case 'B':
           time2
           break;
       }
ShowTime();
}

 

Thanks!

Renke

Being a Mountain bike fan, i am intruiged by your idea. (would be good for training)

Its best if i direct you to this article Wii-Easy Rider as it gives more details for transmitting and receiving multiple asynchonous variables (and how to attach extra characters to front of Tx data)

and also here  RF temparature/humidity display , both these articles have test code attached.

hey gareth,

this stuff is awesome!

I have two arduino boards, a sender and reciever like you have used, two servos and a wii nunchuck.

Is it possible to have one board with the nunchuck sending a signal to another which is connect to the servos, thus
being a wireless pan/tilt system using a wii nunchuck??

I really have no idea on how to do this, if you could help me that would be awesome, I have attatched a code which can pan/tilt two servos using the nunchuck one one arduino board all wired up. WOuld you be able to separate these into what i was talking about above?

"#include <Wire.h>
#include <string.h>
#include <stdio.h>

uint8_t outbuf[6];

int cnt = 0;
int ledPin = 13;

int servoPin = 7;
int servoPin2 = 8;

int pulseWidth = 0;
int pulseWidth2 = 0;

long lastPulse = 0;
long lastPulse2 = 0;

int z_button = 0;
int c_button = 0;

int refreshTime = 20;

int minPulse = 1000;
int minPulse2 = 500;

int dtime=10;

#define pwbuffsize 10
long pwbuff[pwbuffsize];
long pwbuffpos = 0;
long pwbuff2[pwbuffsize];
long pwbuffpos2 = 0;

void setup()
{
    Serial.begin (19200);
    Wire.begin ();
    nunchuck_init ();
    pinMode(servoPin, OUTPUT);
    pinMode(servoPin2, OUTPUT);

    pulseWidth = minPulse;
    pulseWidth2 = minPulse2;
    Serial.print ("Finished setup\n");
}

void nunchuck_init()
{
    Wire.beginTransmission (0x52);
    Wire.send (0x40);
    Wire.send (0x00); 
    Wire.endTransmission ();
}

void send_zero()
{
    Wire.beginTransmission (0x52);
    Wire.send (0x00);
    Wire.endTransmission ();
}

int t = 0;

void loop()
{
    t++;
    long last = millis();

    if( t == 1) {

        t = 0;

        Wire.requestFrom (0x52, 6);

        while (Wire.available ()) {
            outbuf[cnt] = nunchuk_decode_byte (Wire.receive ());
            digitalWrite (ledPin, HIGH);
            cnt++;
        }

        if (cnt >= 5) {

            //            printNunchuckData();

            int z_button = 0;
            int c_button = 0;

            if ((outbuf[5] >> 0) & 1)
                z_button = 1;
            if ((outbuf[5] >> 1) & 1)
                c_button = 1;

            switch (c_button) {
            case 1:
                switch (z_button) {
                case 0:
                    break;
                case 1:
                    muovi();
                    break;
                }
                break;
            case 0:
                switch (z_button) {
                case 0:
                    delay(10000);
                    break;
                case 1:
                    delay(3000);
                    break;
                }
                break;
            }
        }

        cnt = 0;
        send_zero();

    } // if(t==)

    updateServo();

    delay(dtime);
}


void updateServo() {

    if (millis() - lastPulse >= refreshTime) {

        digitalWrite(servoPin, HIGH);
        delayMicroseconds(pulseWidth);
        digitalWrite(servoPin, LOW);

        digitalWrite(servoPin2, HIGH);
        delayMicroseconds(pulseWidth2);
        digitalWrite(servoPin2, LOW);

        lastPulse = millis();
    }
}

int i=0;
void printNunchuckData()
{
    int joy_x_axis = outbuf[0];
    int joy_y_axis = outbuf[1];
    int accel_x_axis = outbuf[2]; // * 2 * 2;
    int accel_y_axis = outbuf[3]; // * 2 * 2;
    int accel_z_axis = outbuf[4]; // * 2 * 2;

    int z_button = 0;
    int c_button = 0;

    if ((outbuf[5] >> 0) & 1)
        z_button = 1;
    if ((outbuf[5] >> 1) & 1)
        c_button = 1;
    if ((outbuf[5] >> 2) & 1)
        accel_x_axis += 2;
    if ((outbuf[5] >> 3) & 1)
        accel_x_axis += 1;

    if ((outbuf[5] >> 4) & 1)
        accel_y_axis += 2;
    if ((outbuf[5] >> 5) & 1)
        accel_y_axis += 1;

    if ((outbuf[5] >> 6) & 1)
        accel_z_axis += 2;
    if ((outbuf[5] >> 7) & 1)
        accel_z_axis += 1;

    Serial.print (i,DEC);
    Serial.print ("\t");

    Serial.print ("X: ");
    Serial.print (joy_x_axis, DEC);
    Serial.print ("\t");

    Serial.print ("Y: ");
    Serial.print (joy_y_axis, DEC);
    Serial.print ("\t");

    Serial.print ("AccX: ");
    Serial.print (accel_x_axis, DEC);
    Serial.print ("\t");

    Serial.print ("AccY: ");
    Serial.print (accel_y_axis, DEC);
    Serial.print ("\t");

    Serial.print ("AccZ: ");
    Serial.print (accel_z_axis, DEC);
    Serial.print ("\t");

    Serial.print (z_button, DEC);
    Serial.print (" ");
    Serial.print (c_button, DEC);
    Serial.print ("\r\n");
    i++;
}

char nunchuk_decode_byte (char x)
{
    x = (x ^ 0x17) + 0x17;
    return x;
}

void muovi (){
    float tilt = (700 - outbuf[3]*2*2);
    float tilt2 = outbuf[2]*2*2;

    tilt = (tilt);
    pulseWidth = (tilt * 5) + minPulse;

    tilt2 = (tilt2-288);
    pulseWidth2 = (tilt2 * 5) + minPulse2;

    pwbuff[pwbuffpos] = pulseWidth;
    pwbuff2[pwbuffpos2] = pulseWidth2;
   
    if( ++pwbuffpos == pwbuffsize ) pwbuffpos = 0;
    if( ++pwbuffpos2 == pwbuffsize ) pwbuffpos2 = 0;


    pulseWidth=0;
    pulseWidth2=0;

    for( int p=0; p<pwbuffsize; p++ ){
        pulseWidth += pwbuff[p];
        pulseWidth2 += pwbuff2[p];
    }

    pulseWidth /= pwbuffsize;
    pulseWidth2 /= pwbuffsize;

}

Thanks heaps mate!

Yes it is possible........however your code could do with a bit of trimming.

See this post Wiieasy rider of mine, it uses the nunchuck and two servos (one for direction and one for speed)

And read this comment here for Sending Wii variables and here too (gives a bit more info re the process)

Here too for multiple variable TXing & Rxing with code examples.

It is also possible to use the WiiMotion controller too.