Transmitting a String

by jpmk12 on Sat Jun 29, 2013 4:52 pm

Hello,

I am working on a Xbee project with a remote control to control the movements of a servo. When I have coolTerm open, I can see a successful send of a string and can see the other radio receiving the string.

When I hook up the xbees to my arduinos, I see just numbers. Like the post below. I assume this is because they are being transmitted in maybe hex?

111
114
70
111
114
70
111
114
119
70
111
114
66
97
99


Does anyone have some helpful hints for how to successfully send a string to one xbee and receive the string on another to trigger movement in a servo. Some of the code I am using is listed below. I would like to transmit the word "forward" from one Xbee to another.

Transmitter Code:
if(xValue > 500)
{
forward = 1;
mySerial.println("Forward");
}

Receiver Code:
void loop()
{
if (mySerial.available()) {

Serial.println((String)mySerial.read());

}

}


Thanks,

Justin
jpmk12
 
Posts: 14
Joined: Fri Nov 20, 2009 11:09 pm
Location: USA

Re: Transmitting a String

by adafruit_support_bill on Sun Jun 30, 2013 4:30 am

On the receiving side, use
Code: Select all | TOGGLE FULL SIZE
 Serial.write(mySerial.read());

http://arduino.cc/en/Serial/Write
User avatar
adafruit_support_bill
 
Posts: 28228
Joined: Sat Feb 07, 2009 9:11 am

Re: Transmitting a String

by jpmk12 on Sun Jun 30, 2013 2:54 pm

Thanks for the help. I am now able to read the string from the Xbee as text. I also have a method later that parses the text.

Code: Select all | TOGGLE FULL SIZE
  while(mySerial.available()) {
      character = mySerial.read();
      content.concat(character);
  }

  if (content != "") {
    content.trim();
    Serial.print(content);
  }



This grabs the code and trim it. I seem to have a new issue where the Xbee doesn't actually read and follow the command unless I hold down the button for a while, but I do see the commands being read on the serial window. I must have some kind of buffer issue.. This is making sending stop motion commands a little difficult. Any suggestions or links you are aware of that would help me work on my lag issue. The radio also seems to cause some noise on the servos im running causing some motion even when none is called. I have calibrated the servos for 0 movement using the potentiometer screws.

In continuing my trouble shooting, I tried sending mySerial.flush(); prior to sending the stop command but it seemed to have no effect. I may need this to be on the receiver side but its not practical to keep flushing the buffer.

Also, could the baud rate be affecting it? Im running 9600 right now and know nothing about wireless projects as this is my learning project. Can/should i try turning up the baud rate of my Xbees?

As always, thanks so much for the help.

Cheers,

Justin
jpmk12
 
Posts: 14
Joined: Fri Nov 20, 2009 11:09 pm
Location: USA

Re: Transmitting a String

by adafruit_support_bill on Sun Jun 30, 2013 5:08 pm

There are a lot of ways you can drop characters and/or cause jitter in the servo signal. But it is hard to draw any conclusions from just the small fragment of code you have posted.
User avatar
adafruit_support_bill
 
Posts: 28228
Joined: Sat Feb 07, 2009 9:11 am

Re: Transmitting a String

by jpmk12 on Sun Jun 30, 2013 6:06 pm

Im sure there are much better ways to accomplish this but below is my remote code:
Code: Select all | TOGGLE FULL SIZE

#include <Servo.h>
#include <SoftwareSerial.h>

SoftwareSerial mySerial =  SoftwareSerial(2, 3);


int xJoy = A5;    // select the input pin for the potentiometer
int xValue = 0;  // variable to store the value coming from the sensor

int yJoy = A4;    // select the input pin for the potentiometer
int yValue = 0;  // variable to store the value coming from the sensor



int int1 = 1;
Servo myservo;
int pos=0;

int stopCheck =1;

// the setup routine runs once when you press reset:
void setup() { 
  Serial.begin(115200); 
  pinMode(13, OUTPUT);
  mySerial.begin(115200);

}

// the loop routine runs over and over again forever:
void loop()
{
 
  xValue = analogRead(xJoy);
  yValue = analogRead(yJoy);
 
 
  while(((xValue < 500) && (xValue >400) && (yValue > 500) && (yValue < 520)))
  {
       xValue = analogRead(xJoy);
       yValue = analogRead(yJoy);
       if(stopCheck == 1)
       {
         mySerial.flush();
         mySerial.println("stop") ;
         Serial.println("Stop");
         stopCheck = 0;
       }
  }
 
 
  if(xValue > 500)
  {
    forward = 1;
    Serial.println("Going Forward");
    mySerial.println("Forward");
  }
  else { forward = 0; }
 
  if(xValue < 400)
  {
    backward = 1;
    Serial.println("Going Backward");
    mySerial.println("Backward");
  }
  else { backward = 0; }
 
 
  //Begin the Turn Portion
    if(yValue > 520)
  {
    left = 1;
    Serial.println("Going Left");
    mySerial.println("Left");
  }
  else { left = 0; }
 
 
 
  if(yValue < 500)
  {
    right = 1;
    Serial.println("Going Right");
    mySerial.println("Right");
  }
  else { right = 0; }

  stopCheck=1;
 
}



jpmk12
 
Posts: 14
Joined: Fri Nov 20, 2009 11:09 pm
Location: USA

Re: Transmitting a String

by adafruit_support_bill on Sun Jun 30, 2013 7:38 pm

I'd need to see the receive side also to be sure, but I suspect you are seeing buffer overruns.

When moving, your protocol is sending multi-character strings repeatedly - as fast as it can. But you only sent the stop command once. If the receive-side buffer gets overflowed by a zillion "Forward" commands, it may miss the lone "Stop" when it arrives.
User avatar
adafruit_support_bill
 
Posts: 28228
Joined: Sat Feb 07, 2009 9:11 am

Re: Transmitting a String

by jpmk12 on Sun Jun 30, 2013 7:58 pm

Thanks, I was afraid that it was something wrong with my implementation. I may need a re-write to figure out a way to only send the command when it is a change.

Here is my receiver code.
Code: Select all | TOGGLE FULL SIZE

#include <Servo.h>
#include <SoftwareSerial.h>
#include<string.h>

String content = "";
  char character;
 
 
SoftwareSerial mySerial =  SoftwareSerial(2, 3);
 
Servo right;  // create servo object to control a servo
Servo left;                // a maximum of eight servo objects can be created

 
String dir = "";
int pos;    // variable to store the servo position
int speed;

void setup()
{
  right.attach(4);  // attaches the servo on pin 9 to the servo object
  left.attach(8);  // attaches the servo on pin 9 to the servo object
  mySerial.begin(115200);
  Serial.begin(115200);

}
 
 
void loop()
{
  content = "";
  //if (mySerial.available()) {
     
     //The original version//////////////////////////////////////////
     //dir = ((String)Serial.write(mySerial.read()));
     //Serial.write(mySerial.read());
     //Serial.println(dir);
    ///////////////////////////////////////////////////////////////// 
 

  while(mySerial.available()) {
      character = mySerial.read();
      content.concat(character);
  }

  if (content != "") {
    content.trim();
    Serial.print(content);
    //Serial.print("");
    //if(content == "stop") { mySerial.flush(); }
  }

//} 
 
  if(content == "stop")
   {
     goStop();   
      Serial.println("Stop was called"); 
     content = "";   
   }
 
 
   if(content == "Forward")
   {
     goForward();   
      Serial.println("Got Forward");     
   }
  //goStop();

   if(dir == "Backward")
   {
     //goBackward();   
      Serial.println("Got Backward");     
   }
   
      if(dir == "Left")
   {
     //goLeft();   
      Serial.println("Got Left");     
   }
   
      if(dir == "Right")
   {
     //goRight();   
      Serial.println("Got Right");     
   }


} //end void loop



/*
 * stops the robot
 */
void goStop(){
 left.write(90);
 right.write(90);
 
}

/*
 * sends the robot forwards
 */
void goForward(){
   speed = 0;
  left.write(90 + speed);
 right.write(90 + speed);
}

/*
 * sends the robot backwards
 */
void goBackward(){
 left.write(90 - speed);
 right.write(90 + speed);
}
 
/*
 * sends the robot right
 */
void goRight(){
 left.write(90 + speed);
 right.write(90 + speed);
}

/*
 * sends the robot left
 */
void goLeft(){
 left.write(90 - speed);
 right.write(90 - speed);
}



I tried using flush to fix this but i think it will be a much bigger change.
jpmk12
 
Posts: 14
Joined: Fri Nov 20, 2009 11:09 pm
Location: USA

Re: Transmitting a String

by jpmk12 on Sun Jun 30, 2013 9:18 pm

Thanks so much for all your help. I was able to rewrite the conditions to only send when a new value was read. You were right. The buffer was just overloaded and not able to see the one stop command in the flood of others.It works fine now. Im going to clean up the code and then I will post the full receiver and transmitter code for anyone else who would like to do something similar.

Thanks for the great support!

Cheers,

Justin
jpmk12
 
Posts: 14
Joined: Fri Nov 20, 2009 11:09 pm
Location: USA

Re: Transmitting a String

by jpmk12 on Wed Jul 10, 2013 8:12 pm

I finally got around to cleaning the code up a little. I have posted it below so hopefully it will be helpful to someone else doing a similar project with remote controllers using Xbee. I also posted a walk through of my build on my blog. Feel free to suggest changes or improvements. Hope this helps!

Transmitter:
Code: Select all | TOGGLE FULL SIZE
// Software by JPMK12
// Designed for XILE.US
// This program is for a
// Remote Control Robot Unit

// Wiring:
// Control Knob: X and Y Analog Outs connected to Analog5 and Analog4 Respectively
// Xbee RX and TX connected to D3 and D2 Respectively

// Includes
#include <Servo.h>
#include <SoftwareSerial.h>

// These variables are the Serials and the Strings Untilized by them
SoftwareSerial mySerial =  SoftwareSerial(2, 3); // Controls the Xbee transmitter
String lastSent = "stop"; // The variable set nd passed from Remote to Robot

// Currently Unused - Sets a varible for passing later
int forward = 0;
int backward = 0;
int left = 0;
int right = 0;

// Inputs read in from Analog Control Knob
int xJoy = A5;    // Select the input pin for the X Axis
int xValue = 0;   // Variable to store the value coming from the X Axis
int yJoy = A4;    // select the input pin for the Y Axis
int yValue = 0;   // Variable to store the value coming from the sensor
////////////////////////////////////////int ledPin = 13;  // Used only for Testing

// Setup runs at boot to configure the remote
void setup()

    Serial.begin(9600); // This serial is for debugging on a Terminal 
    //Serial.println("Terminal Serial Initialized");
    mySerial.begin(9600); // This is the Serial for the Xbee Transmitter
    //mySerial.println("Xbee Terminal Initialized");
}

// This loop runs continuously Reading the Control Knob Output and Sending Control Signals
// through the Xbee Remote
void loop()
{
  //Read the X and Y Values from the Control Knob
  xValue = analogRead(xJoy);
  yValue = analogRead(yJoy);
 
 
  //Determines when the knob is in the center / (Stop) position
  while(((xValue < 500) && (xValue >400) && (yValue > 500) && (yValue < 520)))
  {
       //Read the X and Y
       xValue = analogRead(xJoy);
       yValue = analogRead(yJoy);
       // This prevents a flood of STOP messages by only sending it once
       // It will always be stop the first time
       if(lastSent != "stop")
       {
         mySerial.println("stop") ;
         Serial.println("Stop");
         lastSent = "stop";
       }
  }// End of the Stop Position Checker
 
  // Test for a forward signal
  if(xValue > 500)
  {
    //forward = 1;
    //This prevents the send flood of Forward Messages
    if(lastSent != "forward")
    {
      Serial.println("Going Forward");
      mySerial.println("Forward");
    }
    lastSent = "forward";
  }
  else { forward = 0; }
 
 
  // Test for a Reverse Signal
  if(xValue < 400)
  {
    backward = 1;
    //This prevents the send flood of Reverse Messages
    if(lastSent != "backward")
    {
      Serial.println("Going Backward");
      mySerial.println("Backward");
    }
    lastSent = "backward";
  }
  else { backward = 0; }
 
 
  //Begin the Left Turn Portion
  if(yValue > 520)
  {
    left = 1;
    //This prevents the send flood of Left Messages
    if(lastSent != "left")
    {
      Serial.println("Going Left");
      mySerial.println("Left");
    }
    lastSent = "left";
  }
  else { left = 0; }
 
 
  //Begin the Right Turn Reader
  if(yValue < 500)
  {
    right = 1;
    //This prevents the send flood of Right Messages
    if(lastSent != "right")
    {
      Serial.println("Going Right");
      mySerial.println("Right");
    }
    lastSent = "right";
  }
  else { right = 0; }

  /* These Lines are all for configuring the potetiometers
     Use the prints to determine your boundaries for the turns
  Serial.print("xJoy ");
  Serial.println(xValue);
  Serial.print("yJoy ");
  Serial.println(yValue);
  Serial.print("Initial ");
  Serial.println(int1);
  */
 
}// End of the Program



Receiver:
Code: Select all | TOGGLE FULL SIZE
// Software by JPMK12
// Designed for XILE.US
// This program is for a
// Remote Control Robot
// Wiring:
// Left Side of Servos - Pin 4
// Right Side of Servos - Pin 8
// Pins 2 and 3 are connected to TX and RX respectively


//Includes
#include <Servo.h>
#include <SoftwareSerial.h>
#include<string.h>

//This sectin are the strings received/transmitted
String content = "stop"; //The variable holding the transmitted Xbee data
char character; // No longer used
String dir = "";  // No longer used

//The Serial that receives transmitted Xbee signals 
SoftwareSerial mySerial =  SoftwareSerial(2, 3);

//Motor Control Variables
Servo right;  // create servo object to control a servo
Servo left;                // a maximum of eight servo objects can be created
int pos;    // variable to store the servo position
int speed = 100; // The speed used by the motors

//The setup function runs once and initializes all the variables for the program
void setup()
{
  left.attach(4);  // attaches the servo on pin 4 to the left side servos
  right.attach(8);  // attaches the servo on pin 8 to the right side servos
  mySerial.begin(9600); // The serial that receives the Xbee signals
  Serial.begin(9600); // The Xbee utilized for debugging

}
 
//This loop runs continuously listening for transmitted motion commands
void loop()
{

  // This while loop waits for a transmition from the Xbee to be received
  // Each charecter is read in and added to the existing string reconstructing
  // the word. It is then trimmed and passed to the conditionals.
  while(mySerial.available())
  {
      character = mySerial.read();
      content.concat(character);
  }

  // If the string received is not empty, trim the blank space and print the result
  if (content != "") {
    content.trim();
    Serial.println(content);
    //Serial.print(""); // Debug
    //if(content == "stop") { mySerial.flush(); } // Debug
  }


  // Stop Function
  if(content == "stop")
   {
     goStop();   
      Serial.println("Stop was called");  //Debug
     content = "";   
   }
 
    // Forward Check 
   if(content == "Forward")
   {
     goForward();   
      //Serial.println("Got Forward");   //Debug 
   }
 
   // reverse Check
   if(content == "Backward")
   {
     goBackward();   
      //Serial.println("Got Backward");    //Debug
   }
   
   //Left Turn Check
   if(content == "Left")
   {
     goLeft();   
      //Serial.println("Got Left");     
   }
   
   //Right Turn Check
   if(content == "Right")
   {
     goRight();   
      //Serial.println("Got Right");     //Debug
   }

   content = ""; // Clear Content at the end to listen for a new transmission

} //end void loop


/********************************
The set of functions below are
simple write to the servos to
cause motion based on which
function is called.
*********************************/



// Stop Function / Write a 90 to Stop the robot
// This is the first function you want to use
// to ensure your robot doesnt move without input.
// You may have to adjust the screws on the side of
// your servo to make them actually stop.
void goStop()
{
 left.write(90);
 right.write(90);
}

//Sends the robot forward
void goForward()
{
  left.write(90 + speed);
  right.write(90 - speed);
}

//Sends the robot in reverse
void goBackward()
{
 left.write(90 - speed);
 right.write(90 + speed);
}
 
//Turns the robot to the left
void goRight()
{
 left.write(90 + speed);
 right.write(90 + speed);
}

//Turns the robot to the right
void goLeft()
{
 left.write(90 - speed);
 right.write(90 - speed);
}


Cheers,

Justin
jpmk12
 
Posts: 14
Joined: Fri Nov 20, 2009 11:09 pm
Location: USA

Re: Transmitting a String

by adafruit_support_bill on Thu Jul 11, 2013 5:12 am

I also posted a walk through of my build on my blog.

Can you post a link? :)
User avatar
adafruit_support_bill
 
Posts: 28228
Joined: Sat Feb 07, 2009 9:11 am

Re: Transmitting a String

by jpmk12 on Thu Jul 11, 2013 7:13 am

Here is a link to the blog post. I am still updating it to make it more step by step. Next I plan on adding a control arm for simple tasks.

http://xile.us/2013/07/09/arduino-powered-remote-control-robot/

Hope someone finds it useful.

-Justin
jpmk12
 
Posts: 14
Joined: Fri Nov 20, 2009 11:09 pm
Location: USA

Re: Transmitting a String

by adafruit_support_bill on Thu Jul 11, 2013 3:54 pm

Nice looking project - good enough to blog: http://www.adafruit.com/blog/2013/07/11 ... rol-robot/
Thanks for posting! :D
User avatar
adafruit_support_bill
 
Posts: 28228
Joined: Sat Feb 07, 2009 9:11 am

Re: Transmitting a String

by jpmk12 on Thu Jul 11, 2013 10:13 pm

Thanks so much! :)
jpmk12
 
Posts: 14
Joined: Fri Nov 20, 2009 11:09 pm
Location: USA