Wireless Communication between two Aduinos using Clone 3DR Radios

Hi All,

I have a project that I am working on at present that involves wireless serial communication using a cloned 3DR 915MHz radio set. I am experiencing a few issues with it and was hoping for some input from the community if possible.

[u]The Setup:[/u] Transmitter (Mobile station) - I have an old school joystick/pan that I am mapping the pots of with three analog pins of an Arduino Leonardo. I also have a 3DR radio air module connected to the Leonardo.

Receiver (Ground Station) - I have an Arduino Uno connected to a 3DR radio air module that receives the data transmitted by the Ground Station.

A link to the actual radio set.

[u]The Goal:[/u] The three pots from the joystick simulate roll, pitch and yaw. I map these pots and write the values to an array. I then send the data wirelessly to the Ground Station and store that in an array ready for processing by the rest of the sketch.

[u]The Code:[/u]

Mobile Station (Leonardo):


int RPYPin[3];        // Array to store connection pins
float arrRPY[3];     // Array to store roll, pitch & yaw values

void setup()
  // Defining analog pins
  RPYPin[0] = 0;
  RPYPin[1] = 1;
  RPYPin[2] = 2;

  // Opening up serial port

  // Delay to open serial window manually

void loop() {
  // Roll pin mapping
  arrRPY[0] = analogRead(RPYPin[0]); 
  arrRPY[0] = map(arrRPY[0], 0, 1023, -10.00, 10.00);
  // Pitch pin mapping
  arrRPY[1] = analogRead(RPYPin[1]);
  arrRPY[1] = map(arrRPY[1], 0, 1023, -10.00, 10.00);
  // Yaw pin mapping
  arrRPY[2] = analogRead(RPYPin[2]);
  arrRPY[2] = map(arrRPY[2], 0, 1023, -10.00, 10.00);

  // Print data serially (Wireless)
  // Print data serially (USB port)


Ground Station (UNO)

float arrRPY[3];

void getRPY() {     // Get roll, pitch & yaw function
  byte byteRead;   // Read first byte of the incoming transmission
  boolean startByte = false;   // Boolean opperator
  while (Serial.available() > 0) {  // While there is serial data being trasmitted
    byteRead = Serial.read();  // Read first byte received
    Serial.println(byteRead);   // Visual check for myself to see what it is
    while (byteRead >= 60 || byteRead <= 60) {  // 60 is ASCII code for <, which is my identifier
      byteRead = Serial.read();   // read next byte until it is 60 (<)
      Serial.println(byteRead);    // Visual check for myself
    if (byteRead == 60) {  // If 60 (<) is detected
      startByte = true;       // Change boolean operator value
    if (startByte = true) {             // If startByte is detected use Serial.parseFloat() to detect the next floating 
      arrRPY[0] = Serial.parseFloat();  //point value in the serial communication and write the floating
      arrRPY[1] = Serial.parseFloat();  // point value to the storage array.
      arrRPY[2] = Serial.parseFloat();
  Serial.print(arrRPY[0]); Serial.print(" | "); Serial.print(arrRPY[1]); Serial.print(" | "); Serial.println(arrRPY[2]);  // Visual check to see what has been written to the array.

[u]My Findings[/u] I have two air modules (No USB connector) and one ground station module (USB connector). If I run the joystick module independently from the computer with its own power and I use the ground station module in my computer and I open up the serial terminal with the correct baud rates I get flawless results. I can see the values being stored in the array change as I move the joy stick. The same result when I use the second air module with a FTDI/TTL tool. So this tells me that the radios are paired correctly.

Now, when I bring the Ground Station into the mix is when things go wrong. The two air module pair well and I can see that they are communicating because the communication LED's are flashing. From what I can see, I have the data being written into the storage array but it is not being constisent, see attached a screen shot of the serial terminal output. When it does write data to the array, it is in the correct form, ie. 0.00 | 0.00 | 0.00. But if I move the joystick it remains this, thus I am losing something somewhere.

Mobile Station serial terminal screen grab: So this is what is being transmitted. Notice the changing values due to moving the joystick.

Ground Station serial terminal screen grab: This is evidently what is being written to the array and then it stops. Notice that the ASCII values after the initial 0.00 | 0.00 | 0.00 coincide with what I am listening for, but somehow it is getting a bit confused! Also, the initial values should coincide with the first screen grab, but they don't.

And then another screen grab from the serial terminal from the Ground Station: This is with a two second delay to the Mobile Station sketch, so the 255/null character makes sense, but as for the rest... Can't figure it out!

[u]My Suspicions:[/u] I have a feeling that the two culprits are either my receiving loop or that the transmission is simply too fast. Having said that, if I put a two second delay on the joystick reading sketch and I still don't get values that are changing as I move the joystick. Or could it be my general approach to wireless serial transmission?

Any help or assistance would be much appreciated and if you have any questions, please don't hesitate to ask.

Thanks everyone,


Morning Ladies and Gents,

Last night I played around with the baud rate of the the system and reconfigured the modules and the code to 9600. After I did this the readings on the ground side became stable, no random ASCII code numbers that weren't being deciphered.

Now my problem is that when I move the joy stick, it doesn't update the values in my ground station array. Hmmm! :disappointed_relieved:

Any thoughts?



Now that you have made some progress, perhaps you can restate the problem (so I don't have to read all of your long original post - I presume much of it is no longer relevant).


Hi Robyn,

Thanks for the reply, I really appreciate it!

I have modified my receiving code a bit, here it is:

// Get roll, pitch & yaw from joystick
void getRPY() {
  byte byteRead;
  boolean checkByte = false;
  while (Serial.available() > 0) {
    byteRead = Serial.read();
    while (byteRead > 60 || byteRead < 60) {  // 60 = start byte ASCII code for '<'
      byteRead = Serial.read();
    if (byteRead == 60) {  // 60 = start byte ASCII code for '<'
      checkByte = true;
    while (checkByte = true) {
      arrRPY[0] = Serial.parseFloat();
      arrRPY[1] = Serial.parseFloat();
      arrRPY[2] = Serial.parseFloat();
      byteRead = Serial.read();
    if (byteRead == 62) {  // 62 = end byte ASCII code for '>'
      checkByte = false;
  Serial.print(" <"); Serial.print(arrRPY[0]); Serial.print(" | "); Serial.print(arrRPY[1]); Serial.print(" | "); Serial.print(arrRPY[2]); Serial.println("> "); 

And this is the result I am getting when I open up the serial terminal:

| 0.òâ‚rª‚bj‚r²b‚rŠŠòâ‚rª‚bj‚r²b‚rŠšòâ‚rª‚bj‚r²b‚rŠšòâ‚rª‚bj‚r²bÿK“iªbj‚r¢Âb‚rŠšòâj¢rª¢bj‚r²Êb‚rŠšòâj¢rÂÊbj‚rÊšb‚rŠŠòâjªr’¢bjŠr’Šb‚rŠšòâjªr²’bjŠršºb‚rŠšòâjªrʪbjŠr¢ºb‚rŠšòâj²r’ªbjŠrÂÊb‚rŠŠòâj²r²šbj’r‚Šb‚rŠŠòâjºr‚‚bj’rŠºb‚rŠšòâjºrª‚bj’r’²b‚rŠŠòâjºrÊ¢bj’rª‚b‚rþ13><-8.43,-2.78,0.13><-8.86,-3.06,0.13><-9.11,-3.67,0.11><-9.09,-3.58,0.13><-9.11,-3.74,0.13><-9.11,-4.12,0.13><-9.11,-4.35,0.11><-9.11,-4.73,0.13><-9.14,-5.34,0.11><-9.14,-5.08,0.11><-9.14,-5.27,0.11><-9.14,-5.55,0.11><-9.16,-5.99,0.13><-9.14,-6.35,0.13><-9.11,-6.79,0.11><-9.00,-7.19,0.11><-8.79,-7.59,0.11><-8.55,-7.96,0.11><-8.32,-8.32,0.11><-7.99,-8.60,0.11><-7.78,-8.93,0.11><-7.61,-9.28,0.11><-7.45,-9.47,0.11><-7.24,-9.63,0.11><-6.96,-10.19,0.11><-6.70,-10.48,0.11><-6.35,-10.76,0.11><-5.83,-10.85,0.11><-5.17,-10.90,0.11><-4.47,-10.90,0.11><-3.55,-10.90,0.11><-2.71,-10.87,0.11><-1.96,-10.80,0.11><-1.23,-10.64,0.11><-0.60,-10.50,0.11><-0.34,-10.45,0.11><-0.15,-10.38,0.11><-0.04,-10.38,0.11><0.06,-10.22,0.11><0.32,-10.08,0.11><0.55,-10.03,0.11><0.81,-10.08,0.11><0.93,-9.26,0.11><1.07,-9.77,0.11><1.26,-9.65,0.13><1.54,-9.16,0.11><1.89,-7.66,0.11><2.26,-8.55,0.11><2.69,-6.53,0.11><3.13,-7.78,0.13><3.60,-7.38,0.11><4.02,-5.95,0.11><4.33,-6.30,0.11><4.66,-5.88,0.13><4.89,-5.17,0.11><5.01,-4.40,0.11><5.01,-4.23,0.11><5.01,-3.70,0.13><5.01,-2.52,0.13><5.03,-2.40,0.11><5.06,-2.05,0.11><5.06,-2.29,0.11><5.03,-1.56,0.11><4.99,-1.70,0.11><4.82,-1.35,0.11><4.63,-0.74,0.11><4.26,-0.79,0.13><3.77,-0.36,0.11><3.25,0.08,0.13><2.69,0.20,0.11><2.03,0.34,0.13><1.18,0.36,0.13><0.46,0.36,0.11><-0.29,0.36,0.13><-0.74,0.62,0.13><-1.02,0.79,0.13><-1.16,0.81,0.13><-1.40,0.88,0.13><-1.72,1.07,0.11><-2.19,1.26,0.11><-2.94,1.30,0.13><-3.84,1.21,0.13><-4.61,1.33,0.13><-5.67,0.48,0.13><-6.82,0.72,0.13><-8.13,0.22,0.11><-9.37,-1.47,0.11><-10.31,-1.04,0.11><-10.45,-0.62,0.11><-10.43,-0.50,0.11><-10.43,-0.41,0.11><-10.45,-0.29,0.11><-10.62,-0.60,0.11><-10.78,-0.74,0.11><-10.85,-0.97,0.11><-10.90,-1.42,0.11><-10.90,-2.29,0.11><-10.90,-2.05,0.11><-10.85,-2.45,0.11><-10.76,-3.01,0.11><-10.48,-3.62,0.11><-9.98,-4.30,0.11><-9.63,-4.38,0.11><-9.28,-4.94,0.11><-8.83,-5.24,0.11><-8.57,-5.92,0.11><-8.27,-6.46,0.11><-8.04,-7.21,0.11><-7.78,-7.96,0.11><-7.64,-8.65,0.11><-7.47,-9.37,0.11><-7.05,-9.94,0.11><-6.74,-10.40,0.11><-6.28,-10.94,0.11><-5.62,-11.13,0.11><-4.68,-11.34,0.11><-3.67,-11.41,0.11><-2.55,-11.39,0.11><-1.54,-11.44,0.11><-0.67,-11.23,0.11><-0.18,-11.13,0.11><0.06,-11.37,0.11><0.15,-11.48,0.11><0.27,-11.55,0.11><0.46,-11.55,0.11><0.76,-11.58,0.11><1.18,-11.48,0.11><1.91,-10.97,0.11><2.69,-10.73,0.11><3.51,-10.97,0.11><4.35,-10.69,0.11><5.20,-10.03,0.11><6.02,-10.01,0.11><6.79,-9.44,0.11><7.43,-8.39,0.11><7.94,-7.68,0.11><8.32,-7.66,0.11><8.53,-7.66,0.11><8.60,-7.17,0.11><8.67,-7.31,0.13><8.79,-5.74,0.11><8.95,-5.57,0.11><9.02,-5.01,0.13><9.04,-5.22,0.11><9.04,-5.90,0.11><9.09,-5.45,0.11><9.26,-5.45,0.11><9.44,-5.50,0.11><9.44,-5.45,0.11><9.42,-4.89,0.11><9.44,-4.70,0.11><9.40,-3.93,0.11><9.40,-4.38,0.11><9.42,-4.09,0.11><9.47,-3.74,0.11><9.47,-3.34,0.11><9.51,-2.57,0.11><9.47,-1.07,0.11><9.51,-2.17,0.11><9.61,-2.22,0.11><9.65,-1.77,0.11><9.65,-1.11,0.11><9.65,-0.88,0.13><9.65,-0.72,0.11><9.61,-0.55,0.11><9.49,-0.57,0.13><9.49,-0.06,0.13><9.49,0.11,0.11><9.47,0.43,0.13><9.40,0.57,0.11><9.16,0.81,0.11><8.90,0.90,0.11><8.57,1.37,0.11><8.32,1.82,0.11><7.92,1.65,0.11><7.43,1.82,0.11><6.86,1.98,0.11><6.16,2.10,0.13><5.38,2.26,0.13><4.59,2.33,0.11><3.79,2.45,0.11><3.16,2.62,0.11><2.59,2.59,0.13><2.12,2.66,0.13><1.54,2.64,0.13><1.07,2.73,0.13><0.74,2.85,0.13><0.53,2.87,0.11><0.46,3.09,0.13><0.27,3.04,0.13><-0.15,3.30,0.11><-0.62,3.44,0.13><-1.11,3.41,0.13><-1.51,3.41,0.13><-1.98,3.51,0.13><-2.45,3.58,0.13><-3.18,3.46,0.13><-3.88,3.55,0.13><-4.56,3.51,0.13><-5.20,3.41,0.13><-5.83,2.22,0.13><-6.37,2.85,0.13><-7.05,1.28,0.11><-8.11,2.64,0.13><-8.95,2.26,0.13><-9.72,1.09,0.13><-9.89,1.35,0.13><-9.91,1.47,0.11><-9.98,0.55,0.13><-10.31,0.90,0.11><-10.55,0.43,0.13><-10.80,0.46,0.11><-10.90,0.50,0.13><-11.04,0.11,0.11><-11.11,-0.83,0.11><-11.32,-0.13,0.11><-11.37,0.08,0.13><-11.39,-0.13,0.11><-11.25,0.06,0.13><-10.94,-0.32,0.11><-10.43,-0.41,0.13><-9.84,-0.15,0.13><-9.30,-0.11,0.13><-8.88,-0.34,0.13><-8.50,-0.13,0.13><-7.73,-0.13,0.13><-6.72,-0.11,0.13><-5.29,-0.08,0.11><-3.32,0.01,0.13><-1.09,0.22,0.11><0.88,0.34,0.13><1.58,0.34,0.11><1.96,0.25,0.13><2.08,0.01,0.13><2.17,-0.57,0.13><2.40,-1.23,0.11><2.90,-1.77,0.11><3.86,-2.01,0.13><5.17,-2.05,0.11><6.77,-2.24,0.13><8.67,-2.40,0.11><10.17,-2.38,0.11><10.52,-2.22,0.11><10.36,-2.29,0.11><10.59,-2.24,0.11><10.64,-2.73,0.11><10.71,-3.77,0.11><10.83,-3.95,0.11><10.83,-4.02,0.11><10.83,-4.40,0.11><10.85,-4.63,0.11><10.87,-4.21,0.11><10.85,-4.61,0.11><10.90,-4.63,0.11><10.92,-4.61,0.11><10.92,-4.52,0.11><10.94,-4.42,0.11><10.92,-4.47,0.11><10.94,-4.56,0.11><10.92,-4.28,0.11><10.92,-4.45,0.11><10.90,-4.66,0.11><10.80,-4.66,0.11><10.83,-4.73,0.11><10.78,-3.67,0.11><10.57,-5.08,0.11><10.29,-5.41,0.11><10.05,-5.78,0.11><9.82,-6.16,0.11><9.70,-6.46,0.11><9.58,-6.77,0.11><9.35,-7.24,0.11><9.09,-7.61,0.11><8.88,-7.71,0.11><8.43,-7.92,0.11><8.18,-8.25,0.11><7.73,-9.54,0.11><7.40,-9.94,0.11><7.10,-10.36,0.11><6.89,-10.69,0.11><6.63,-10.80,0.11><6.56,-10.90,0.11><6.51,-10.94,0.11><6.42,-11.09,0.11><6.21,-10.59,0.11><5.71,-11.65,0.11><5.22,-11.86,0.11><4.68,-11.86,0.11><4.30,-11.91,0.11><3.86,-11.93,0.11><3.46,-11.91,0.11><2.94,-11.98,0.11><2.38,-11.93,0.11><1.77,-11.95,0.11><1.16,-11.88,0.11><0.93,-11.95,0.11><0.81,-11.98,0.11><0.57,-11.98,0.11><0.29,-11.98,0.11><-0.04,-11.95,0.11><-0.53,-11.93,0.11><-0.86,-11.93,0.11><-1.35,-11.86,0.11><-1.77,-11.79,0.11><-2.22,-11.62,0.11><-2.66,-11.46,0.11><-3.20,-11.11,0.11><-3.62,-11.04,0.11><-4.14,-10.59,0.11><-4.33,-9.87,0.11><-4.35,-9.42,0.11><-4.35,-8.90,0.11><-4.30,-7.96,0.11><-4.30,-7.43,0.11><-4.28,-6.46,0.11><-4.26,-5.69,0.11><-4.12,-4.94,0.11><-3.86,-4.12,0.11><-3.51,-3.41,0.11><-2.97,-2.50,0.11><-2.24,-1.89,0.11><-1.42,-1.28,0.11><-0.53,-0.81,0.11><0.25,-0.29,0.11><0.50,0.08,0.11><0.48,0.15,0.11><0.39,0.15,0.11><0.32,0.08,0.11><0.29,-0.06,0.11><0.32,-0.15,0.11><0.34,-0.20,0.11><0.34,-0.34,0.11><0.34,-0.46,0.11><0.34,-0.57,0.11><0.34,-0.65,0.11><0.34,-0.55,0.11><0.34,-0.53,0.11><0.34,-0.65,0.11><0.34,-0.65,0.11><0.34,-0.65,0.11><0.34,-0.62,0.11><0.34,-0.62,0.11>
 <0.00 | 0.00 | 0.00> 
 <0.00 | 0.00 | 0.00> 
 <0.00 | 0.00 | 0.00> 
 <0.00 | 0.00 | 0.00> 
 <0.00 | 0.00 | 0.00> 
 <0.00 | 0.00 | 0.00> 
 <0.00 | 0.00 | 0.00> 
 <0.00 | 0.00 | 0.00> 
 <0.00 | 0.00 | 0.00> 
 <0.00 | 0.00 | 0.00> 
 <0.00 | 0.00 | 0.00> 
 <0.00 | 0.00 | 0.00> 
 <0.00 | 0.00 | 0.00> 
 <0.00 | 0.00 | 0.00> 
 <0.00 | 0.00 | 0.00> 
 <0.00 | 0.00 | 0.00> 
 <0.00 | 0.00 | 0.00> 
 <0.00 | 0.00 | 0.00>

If you look at the serial data from before it starts to conform to the <0.00 | 0.00 | 0.00> format, one sees that I am transmitting the correct data. But my code is not interpreting it correctly. I cannot see the errors of my way and I was wondering if you could shed some light there if possible. It is almost as if it is skipping all my true false checks and conditions.

Thanks for the help!


Below is some test joystick servo code with a dead band and a slight delay for testing to prevent unneeded transmissions that overrun buffers and such. The arduino can produce a data spew that can outrun the ability to transmit and receive the data. Servos are not needed to see the output in the serial monitor.

//zoomkat multi pot/servo test 3-23-13
//includes dead band for testing and limit servo hunting
//view output using the serial monitor

Servo myservo1;  //declare servos
Servo myservo2;
Servo myservo3;
Servo myservo4;
Servo myservo5;

int potpin1 = 0;  //analog input pin A0
int potpin2 = 1;
int potpin3 = 2;
int potpin4 = 3;
int potpin5 = 4;

int newval1, oldval1;  //pot input values
int newval2, oldval2;
int newval3, oldval3;
int newval4, oldval4;
int newval5, oldval5;

void setup() 
  Serial.println("testing multi pot servo");  

void loop()
  newval1 = analogRead(potpin1);           
  newval1 = map(newval1, 0, 1023, 0, 179); 
  if (newval1 < (oldval1-2) || newval1 > (oldval1+2)){ //dead band 
    myservo1.write(newval1); //position the servo
    Serial.print(newval1); //print the new value for testing 
    oldval1=newval1; //set the current old value

  newval2 = analogRead(potpin2);
  newval2 = map(newval2, 0, 1023, 0, 179);
  if (newval2 < (oldval2-2) || newval2 > (oldval2+2)){  

  newval3 = analogRead(potpin3);           
  newval3 = map(newval3, 0, 1023, 0, 179); 
  if (newval1 < (oldval1-2) || newval3 > (oldval3+2)){  

  newval4 = analogRead(potpin4);           
  newval4 = map(newval4, 0, 1023, 0, 179); 
  if (newval1 < (oldval1-2) || newval4 > (oldval4+2)){  

  newval5 = analogRead(potpin5);           
  newval5 = map(newval5, 0, 1023, 0, 179); 
  if (newval1 < (oldval5-2) || newval5 > (oldval5+2)){  
  delay(50);  //to slow loop for testing, adjust as needed

Hi All,

I am coming back here for completion sake, I figured out how to serially communicate over 3DR wireless modules.

From what I could deduce, it was that my code had a logic issue with the loops ets.

Attached, please find the code. I hope this is useful to someone else!

// Code to receive serial floating point sensor data - Dylan Reynolds, Cape Town, South Africa
// I take no responsibility for accidents resulting in the use of this code. This is 
// merely a guideline and free for modification.
// - I was using this to transmit the roll pitch and yaw from and IMU to a ground station, I
//   am sure it can be adapted to applications such as GPS coordinates, temperature etc.
//  ________________________            _______________________
// |       TRANSMITTER      |          |        RECEIVER       |
// | Teensy 3.0 + MPU6050 + | -------> | Arduino Leonardo R3 + |
// | 3DR  915MHz Air Module | -------> | 3DR 915MHz Air Module |
// |________________________|          |_______________________|
// - Print serial data normally on the sending side as if you were going to send it serially
//   over the USB port (Serial1 for hardware pins on Leonardo etc.)
// - Use the following code on the receiving controller:

float arrRPY[3];                                   // Array to store the roll, pitch & yaw values

void setup() {                                     // Setup function that runs initially on MCU startup
  Serial.begin(57600);                             // Start serial usb connection
  Serial1.begin(57600);                            // Start hardware serial pins connection

void loop() {                                      // Loop function running continuously after MCU has been setup
  getRPY();                                        // Function storing roll, pitch & yaw in arrRPY array

void getRPY() {                                    // Function storing roll, pitch & yaw in arrRPY array
  byte byteRead;                                   // Serial comms transmits bytes, this stores the initially read byte from the serial stream

  while (Serial1.available() > 0) {                // While data is available in the serial buffer

    byteRead = Serial1.read();                     // Read the first byte in the serial buffer
    // Searching for the start byte "<" (ASCII = 60) 
    while (byteRead > 60 || byteRead < 60) {       // If the byte value is greater than or less that 60
      byteRead = Serial1.read();                   // keep reading the byte stream until 60 is found, ie. "<"
    if (byteRead == 60) {                          // If "<" found
      for (int i = 0 ; i <= 2 ; i++) {             // I expected 3 values, so I looped 3 times
        arrRPY[i] = Serial1.parseFloat();          // Write the parsed floating point value found in the serial stream to arrRPY
    // Check that the correct values are being written to the array by examining them in a serial terminal
    Serial.print("<"); Serial.print(arrRPY[0]); Serial.print(","); Serial.print(arrRPY[1]); Serial.print(","); Serial.print(arrRPY[2]); Serial.println(">");

Kind regards,


hello is possiblr to take bidirectional communication with 3dr modules?

PatoNaranjoEraso: hello is possiblr to take bidirectional communication with 3dr modules?

Thread is over 3 years old, I would suggest you start a new one.