Pages: [1]   Go Down
Author Topic: RF Communication Lag  (Read 1955 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello all!

I'm working on a project -- as the title suggests, it is an rf-operated blimp. We've gotten the hardware sorted out, but I'm experiencing a problem with the transmission between the remote and the receiver. (Just to clarify -- One way communication from a remote to the receiver on the gondola of the blimp.)

My problem is that there is a lag in the communication. As you can imagine, this delay (of about 2 or more seconds) impedes to function of any remote control device. However I'm not sure what to do about it. Sometimes the communication works mildly fine -- The lag is still noticeable, but blimp control would be operable. However, often it will just drop completely, and then spontaneously start working again.

The basic gondola setup is as follows:
One Arduino UNO powered by a 9v battery,
a single servo that is attached to a turning axel,
on which there are two regular high-speed, low torque motors.

On the remote, I have:
a single Arduino with
four push buttons and a potentiometer.

The remote makes a string of numbers depending on the status of the forms of input (buttons and potentiometer), and transmits it to the receiver, which translates the string and moves accordingly.

Like I said, it works, and when the reception is consistent, the delay is less noticeable. However, the connection is constantly dropping with no change or movement of the two parts. That is, each of the receiver and transmitter just sit stationary, the gondola not attached to anything.

I've experimented with antennas, and having a piece of wire propped for both ends makes matters worse -- There's basically no interface at all.  

I'm pretty sure this is a hardware problem, but I'll post my code anyway.

Code:
/* Blimp Transmitter
 * Features remote control of the blimp gondola via 4 buttons a potentiometer over
 * VirtualwWire.
 * Created 9 / 7 / 12
 */


#include <VirtualWire.h>

char *createControlString(int potentiometer, int left, int right) {
  char *tmp = "000000";
  char *pottmp = "0000";
  char *mtmp = "0";
  
  itoa(left, mtmp, 10);
  tmp[0] = mtmp[0];
  
  itoa(right, mtmp, 10);
  tmp[1] = mtmp[0];
  
  // Conversion from potentiometer reading to servo ms value
  potentiometer = (1.8 * potentiometer) + 544;
  
  // Convert potentiometer value to a string
  itoa(potentiometer, pottmp, 10);
  
  if (potentiometer >= 1000) {
    for (int i = 0; i < strlen(pottmp); i++)
      tmp[i + 2] = pottmp[i];
  }
  
  else if (potentiometer >= 100) {
    tmp[2] = '0';
    for (int i = 0; i < strlen(pottmp); i++)
      tmp[i + 3] = pottmp[i];
  }
  
  else if (potentiometer >= 10) {
    tmp[2] = '0';
    tmp[3] = '0';
    for (int i = 0; i < strlen(pottmp); i++)
      tmp[i + 4] = pottmp[i];
  }
      
  else if (potentiometer >= 0) {
    tmp[2] = '0';
    tmp[3] = '0';
    tmp[4] = '0';
    for (int i = 0; i < strlen(pottmp); i++)
      tmp[i + 5] = pottmp[i];
  }
  
  return tmp;
}

void setup()
{
  // I/O Setup
  Serial.begin(9600);
  pinMode(2, INPUT); // Button 4
  pinMode(3, INPUT); // Button 3
  pinMode(7, INPUT); // Button 2
  pinMode(8, INPUT); // Button 1
  pinMode(13, OUTPUT); // LED
  
  // VirtualWire Setup
  vw_setup(2000);
  vw_set_ptt_inverted(true);
  vw_set_tx_pin(11);
}

void loop()
{
  // Initialize and get readings
  int potval;
  int b[4];
  b[0] = digitalRead(8);
  b[1] = digitalRead(7);
  b[2] = digitalRead(3);
  b[3] = digitalRead(2);
  potval = analogRead(A0);
  
  int motorleft, motorright;
  
  // Left Motor switches
  if (!b[0] && !b[1])
    motorleft = 0; // Don't move left motor
  else if (b[0] && !b[1])
    motorleft = 1; // Move left motor forward
  else if (!b[0]&& b[1])
    motorleft = 2; // Move left motor backward
  else if (b[0] && b[1])
    motorleft = 0;  // Don't move motor
    
  // Right Motor Switches
  if (!b[2] && !b[3])
    motorright = 0;
  else if (b[2] && !b[3])
    motorright = 1;
  else if (!b[2]&& b[3])
    motorright = 2;
  else if (b[2] && b[3])
    motorright = 0;
  
  // Print readings
  /*for (int i = 0; i < 4; i++) {
    Serial.print("Button ");
    Serial.print(i);
    Serial.print(": ");
    Serial.print(b[i]);
    Serial.println();
  }*/
  
  // print motor settings
  Serial.print("Left: ");
  Serial.print(motorleft);
  Serial.print(" Right: ");
  Serial.print(motorright);
  Serial.println();
  
  // Print potentiomoter reading
  Serial.print("Potentometer: ");
  Serial.print(potval);
  Serial.println();
  
  // Main delay
  delay(200);
  
  // Create control string
  char *info = createControlString(potval, motorleft, motorright);
  Serial.println(info);
  
  // Transmit info
  digitalWrite(13, true); // Flash light to show we're transmitting
  vw_send((uint8_t *) info, strlen(info)); // Send message
  vw_wait_tx(); // Wait until message is sent
  digitalWrite(13, false);
}
  

Code:
/* Blimp transmitter code
 * ServoTimer2 is used to work with the virtualwire library.
 */
 
#include <VirtualWire.h>
#include <ServoTimer2.h>

ServoTimer2 angleServo;

void setup() {
  Serial.begin(9600);
  
  // Declare pins 7 through nine as output
  for (int i = 2; i < 6; i++)
    pinMode(i, OUTPUT);
  
  // Virtualwire Setup
  vw_set_ptt_inverted(true);
  vw_setup(2000);  // Bits per second
  vw_set_rx_pin(11); // Designate the pin the receiver's data pin
  vw_rx_start();  // Start the receiver PLL running
  
  // Servo
  angleServo.attach(10);
}

void loop() {
  // These two variables are used in the reception process
  uint8_t buf[VW_MAX_MESSAGE_LEN];
  uint8_t buflen = VW_MAX_MESSAGE_LEN;
  
  char *controlString = "000000";
  //int *control[3] = {0, 0, 0000};
  int leftmotor, rightmotor, servopos;
  
  if (vw_get_message(buf, &buflen))
  {
    //Serial.print("Got: ");
    
    /*for (int i = 0; i < buflen; i++) {
      Serial.print(buf[i]);
      Serial.print(" ");  
    }*/
    
    Serial.println();
    leftmotor = int(buf[0]) - '0';
    rightmotor = int(buf[1]) - '0';
    servopos = ((int(buf[2]) - '0') * 1000) + ((int(buf[3]) - '0') * 100) + ((int(buf[4]) - '0') * 10) + (int(buf[5]) - '0');
    
    /*Serial.print("Left: ");
    Serial.print(leftmotor);
    Serial.println();
    Serial.print("Right: ");
    Serial.print(rightmotor);
    Serial.println();
    Serial.print("Servo: ");
    Serial.print(servopos);
    Serial.println();*/
    
    if (leftmotor == 0) {
      digitalWrite(2, false);
      digitalWrite(3, false);
    }
    else if (leftmotor == 1) {
      digitalWrite(2, true);
      digitalWrite(3, false);
    }
    else if (leftmotor == 2) {
      digitalWrite(2, false);
      digitalWrite(3, true);
    }
      
    if (rightmotor == 0) {
      digitalWrite(4, false);
      digitalWrite(5, false);
    }
    else if (rightmotor == 1) {
      digitalWrite(4, true);
      digitalWrite(5, false);
    }
    else if (rightmotor == 2) {
      digitalWrite(4, false);
      digitalWrite(5, true);
    }
    
    
    //Serial.print(servopos);
    
    Serial.println(servopos);
    angleServo.write(servopos);
  }
}
Feel free to ask questions; I'll gladly clarify.

I fresh out of ideas what to do about this. The RF modules I'm using are the basic transmitter/receivers you can get from Sparkfun. They are each operating on the Arduino's 5V pin. Perhaps I should connect them straight to the 9V battery?

Thanks for your time!  
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 613
Posts: 49338
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
  itoa(potentiometer, pottmp, 10);
Why isn't pottmp an array, like it is supposed to be?

Code:
  itoa(left, mtmp, 10);
Why isn't mtmp an array, like it is supposed to be?

If left is ever more than a single digit value, you are hosed.

Code:
  itoa(right, mtmp, 10);
Same issues with right.

Code:
  return tmp;
Returning a pointer that to memory that is about to go out of scope is a bad idea.

Use a global array to hold the string, write to the string using sprintf() and don't return anything from this function. The code will be orders of magnitude simpler and safer.

On the other hand, you have 2 single byte sized values (motorleft and motorright) and one 2 byte sized value (potval) that you want to send. Converting these bytes to strings, sending the strings, and converting the strings back to bytes and ints is much slower than simply sending 4 bytes and using the data directly.

Code:
  byte info[4];
  info[0] = motorleft;
  info[1] = motorright;
  info[2] = highByte(potval);
  info[3] = lowByte(potval);
  vw_send((uint8_t *) info, 4); // Send message
  vw_wait_tx(); // Wait until message is sent

Code:
    leftmotor = buf[0];
    rightmotor = buf[1];
    servopos = buf[2] * 256 + buf[3];
Logged

Pages: [1]   Go Up
Jump to: