XBEE two arduinos and two servos how to get more than 9 positions

Hi, I have been reading some tutorials and posts on here and now I am a bit stuck. I have code working from another post that allows two pots to control two servos independently between two arduinos using xbee shields.

From tutorials online it seems to be only allowing the servo to move 9 positions but I am wanting more say 180, I have tried modifying the map on both the rx and tx end by changing the 9 to 180 to get 180 positions but the servos don't do anything. Also I am running the servos of a separate battery 7.4v so I know this is not the problem.

Any help would be greatly appreciated.

thanks

// rx code

#include <Servo.h>

int servoPin_0 = 9;
int servoPin_1 = 3;

Servo Servo_1;
Servo Servo_2;

void setup()
{

//Start Serial
Serial.begin(9600);

Servo_1.attach(servoPin_0);
Servo_2.attach(servoPin_1);

delay(50);
}

void loop()
{

while( Serial.available() == 0);
int data_0 = Serial.read() -'0';

int pos_0 = map(data_0, 0, 9, 0, 180);
pos_0 = constrain(pos_0, 0, 180);
Serial.print(pos_0);
Servo_1.write(pos_0);

while(Serial.available()>0);
Serial.read();

while( Serial.available() == 0);
int data_1 = Serial.read() -'1';
int pos_1 = map(data_1, 0, 9, 0, 180);
pos_1 = constrain(pos_1, 0, 180);
Serial.print(pos_1);
Servo_2.write(pos_1);
while(Serial.available()>0);
Serial.read();

}

// tx code

int potPin_left = 0;
int potPin_right = 1;

void setup()
{
//Create Serial Object (9600 Baud)
Serial.begin(9600);
}

void loop()
{
int val_0 = map(analogRead(potPin_left), 0, 1023, 0, 9);
Serial.print(val_0);
delay(500);

int val_1 = map(analogRead(potPin_right), 0, 1023, 0, 9);
Serial.print(val_1);
delay(500);

}

Send6.ino (352 Bytes)

Rec6.ino (772 Bytes)

You need to change how you send data. Do not send a single digit for position. Send something like "<130, 160>" to send the first servo to position 130 and the second servo to postion 160.

Then use Robin2's Serial Input Basics process to read and parse the data.

Many thanks PaulS for your reply, can I just check this is what you are suggesting by sending the for the tx code? I thought the reason why only 10 positions are sent is that the arduino counts in hexadecimal so is more complex to process values that are say a1, is this correct?

// tx code

int potPin_0 = 0;
int potPin_1 = 1;

void setup()
{
//Create Serial Object (9600 Baud)
Serial.begin(9600);
}

void loop()
{
int val_0 = analogRead(potPin_0);
Serial.print(val_0);
delay(50);

int val_1 = analogRead(potPin_1);
Serial.print(val_1);
delay(50);

}

I'm just reading up on the Robin2's post and on the parse data, being new to arduino and xbee I think it may take some time to understand sending and receiving the data.

can I just check this is what you are suggesting by sending the for the tx code?

ThatsendsthedatainASCIIwithnodelimiters.Kindofhardtoread,isn'tit?

Ok I managed to get the serial print to go from 0 to 180 on both pots and monitored this on the serial monitor.

// tx code

int potPin_left = 0;
int potPin_right = 1;

void setup()
{
//Create Serial Object (9600 Baud)
Serial.begin(9600);
}

void loop()
{
int val_0 = map(analogRead(potPin_left), 0, 1023, 0, 180);
Serial.print(val_0);
delay(500);

int val_1 = map(analogRead(potPin_right), 0, 1023, 0, 180);
Serial.print(val_1);
delay(500);

}

Will read up on the rx side and give that ago.

 int val_0 = map(analogRead(potPin_left), 0, 1023, 0, 180);
  Serial.print(val_0);
  delay(500);
 
  int val_1 = map(analogRead(potPin_right), 0, 1023, 0, 180);
  Serial.print(val_1);
  delay(500);

If the 2 pots are somewhere near the center, this will result in "90909090" being written to the serial port.

Imagine how much easier that would be to parse if it was "<90, 90><90, 90>".

Imagine how EASY it would be to, in the immortal words of Captain Picard, "make it so!".

I'm a bit confused on how to do the <90,90> format, from looking at this it looks like a loop is needed to go through the data and separate it out.

I'm a bit confused on how to do the <90,90> format

On the sender? It's trivial.

On the receiver? Robin2's tutorial explains how.

from looking at this it looks like a loop is needed to go through the data and separate it out.

Why is that a problem?

I think I know, just serial print < at the start then , between the two value prints and > at the end then the loop part is in the reciving end to which starts at < then loops through to get out the data until >.

Ok got the tx bit to print in the format <90,90> as bellow and am reading up on the rx side, will upload code once I get it to work. Thanks PaulS for pointing me in the right direction, its all starting to make sense now.

// tx code

int potPin_left = 0;
int potPin_right = 1;

#define SOP '<' // Start of packet
#define EOP '>' // End of packet

void setup()
{
//Create Serial Object (9600 Baud)
Serial.begin(9600);
}

void loop()
{
Serial.print("<");

int val_0 = map(analogRead(potPin_left), 0, 1023, 0, 180);
Serial.print(val_0);
delay(0);

Serial.print(",");

int val_1 = map(analogRead(potPin_right), 0, 1023, 0, 180);
Serial.print(val_1);
delay(0);

Serial.print(">");

delay(500);

}

  delay(0);

WTF?

That was just me playing about with different things, it should not be there in the final one.

Hello dom, are you using xbee series 1 or 2? i am looking to do a similar project, but i have series 2 xbee

hmshector:
Hello dom, are you using xbee series 1 or 2? i am looking to do a similar project, but i have series 2 xbee

Hi, I am using serries one as from reading up on it serries one is a bit simpler to set up.

Hi, I have managed to send and recieve and parse the data into intergers which I checked by using the received data to multiply by a number and all works. The problem I have now is adding the servos, currently I have my code which has a loop in it but the servo code also has a loop. I can't put this into the current loop as it would not have recieved the data. Any surgestions on how to get around this problem. Sorry I can't upload my code atm but will do as soon as I can. I have been looking at running two loops but from other posts don't think this is possible. Thanks

The problem I have now is adding the servos, currently I have my code which has a loop in it but the servo code also has a loop

Are you talking about loop as in loop() or loop as in for loop?

You CAN receive serial data and control servos with that data, as long as you are aware of when you have enough data to control the servos.

Basically there is a void loop() which receives the incoming data but in my servo code that was used with pots there is another void loop() to control the servos. I attempted to use the schedule library which arduino recognises successfully but am getting an error saying,

Rec_servo.ino: In function 'void setup()':
Rec_servo:36: error: expected unqualified-id before '.' token
expected unqualified-id before '.' token

Is there a way to get around this without using two separate loops?

Here is the code. I know its a bit messy atm with renaming variable but will clean it all up once it works.

#include <VarSpeedServo.h>
#include <Scheduler.h>

VarSpeedServo myservo1;
VarSpeedServo myservo2;

const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars]; // temporary array for use when parsing

// variables to hold the parsed data
char messageFromPC[numChars] = {0};

int Data_1 = 0;
int Data_2 = 0;
int Data_3 = 0;

int val1; // variable to read the value from the analog pin
int val2;
int val3;
int val4;

boolean newData = false;

//============

void setup() {
Serial.begin(9600);
Serial.println("This demo expects 3 pieces of data - text, an integer and a floating point value");
Serial.println("Enter data in this style <HelloWorld, 12, 24.7> ");
Serial.println();

Scheduler.startLoop(loop1);
}

//============

void loop() {
recvWithStartEndMarkers();
if (newData == true) {
strcpy(tempChars, receivedChars);
// this temporary copy is necessary to protect the original data
// because strtok() used in parseData() replaces the commas with \0
parseData();
showParsedData();
newData = false;
}
}

//============

void recvWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;

while (Serial.available() > 0 && newData == false) {
rc = Serial.read();

if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}

else if (rc == startMarker) {
recvInProgress = true;
}
}
}

//============

void parseData() { // split the data into its parts

char * strtokIndx; // this is used by strtok() as an index

strtokIndx = strtok(tempChars,","); // get the first part - the string
strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC

strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
Data_1 = atoi(strtokIndx); // convert this part to an integer

strtokIndx = strtok(NULL, ","); //this continues where the previous call left off
Data_2 = atoi(strtokIndx); // convert this part to a int

strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
Data_3 = atoi(strtokIndx); // convert this part to an integer

}

void showParsedData() {
Serial.print("Data 1 ");
Serial.println(Data_1);

Serial.print("Data 2");
Serial.println(Data_2);

Serial.print("Data 3 ");
Serial.println(Data_3);
}

////////////////////////////////////////////////////////servos///////

void loop2()
{
/////////servospeed//////////
val4 = Data_3;
val4 = (val4/100);

//////Servo 1////////////////
val1 = Data_1;
myservo1.slowmove(val1, val4); // sets the servo position according to the scaled value
delay(1); // waits for the servo to get there

//////Servo 2////////////////

val2 = Data_2;
myservo2.slowmove(val2, val4);
delay(1);

yield();

}

I attempted to use the schedule library which arduino recognises successfully but am getting an error saying,

Well, I tried to use hair tonic to remove paint, and that didn't work.

    if (newData == true) {
        strcpy(tempChars, receivedChars);

You got a complete packet. Yeah.

        parseData();

So, this did something, presumably isolating the individual servo positions.

        showParsedData();

To the servos? If not, why the hell not?

I don't really understand what you mean, I thought it would be simpler to keep the servo part and reading part separate. I managed to get individual values for each pot received but just trying to implement it into the servo code which is everything bellow the /////////////////////servos///// line.

I have an idea, move myservo1.slowmove(val1, val4); into the void showParsedData() rather than creating another loop.