send array of integers via xBee s1

Hi,
I have some problems sending 4-5 data via xbee.
I'm using arduino mega 2560, arduino diecimila, 2 xbee s1 and I want to control a RC car using those chips. the data I'm trying to send are: status (car on automatic mode or RC mode, values are 0 or 1), FW/BW ( car moving forward/backward, values from 0 to 255, 125-135 is not moving), direction (richt left, values from 0 to 255, which represent the angle of the wheels), default speed (which is the speed of the car when moving on automatic mode).
Until now I've had lot of troubles, because I don't really know how to send an array trough xbee and every time I write a new code it doesn't work. do someone an help me please? I haven't found anything yet and I'm quite desperate :S
thanks
propilot

the data I'm trying to send are: status (car on automatic mode or RC mode, values are 0 or 1), FW/BW ( car moving forward/backward, values from 0 to 255, 125-135 is not moving), direction (richt left, values from 0 to 255, which represent the angle of the wheels), default speed (which is the speed of the car when moving on automatic mode).

Do you want to send this as ASCII data or binary data? ASCII data is easy to send, easy to receive, and easy to parse. The drawback is that it can be slow doing all that.

Sending data in binary is fast, but error detection/correction is much more difficult.

Until now I've had lot of troubles, because I don't really know how to send an array trough xbee

Whether the data is in discrete variables or in an array is irrelevant.

and every time I write a new code it doesn't work.

Post the code. Explain what it does. Explain how that differs from what you want. We can help you fix it.

do someone an help me please?

I'm trying.

the code of the car is ctrl_robot_....1_7_2, the one of the ground station is ctrl_xbee_...
short explanation for the car code:
float ping(): read the distance from the objects (used in automatic mode only)
void resetdirezione(angolatura): set and move the wheels to the specified angle
void direzione():decides which is the best direction (R or L)
--> int leggiseriale(): this is where the problem should be: this function has to read the data coming from the xbee and separate them in one array so that i can use the numbers easily
//void cercacasa(): unused at the moment (should seek IR and find home)
void destra() and void sinistra(): turn the wheels right or left (instead of them now i use resetdirezione(angle))
setup():...
void loop():read the data from the xbee and set the mode: if spia==0 the car moves on automatic mode (with HC-SR04 sensor), else it should use the numbers it gets from xbee to move)
short explanation for the ground station code:
i read the values from a playstation controller (just from 2 potentiometers and one button), than i send them: sz=car mode, sx=FW/BW,sy=R/L,200= default speed (for automatic mode)
if u need more explanation i will give you every info you need :slight_smile:
ps.the code, since leggiseriale()gives me back always 0, so automatic mode, works perfectly, the problme is that i want to use also the other mode
thank you
propilot

ctrl_robot_HC_SR04_test_serialmov_v1_7_2.ino (9.75 KB)

and sorry but I'm not really good with arduino, specially with serial and with xbee
I'm a noob and this is my first big project :slight_smile:

ctrl_xbee_usbcom_v1_3.ino (1.05 KB)

float ping()//questa funzione misura la distanza attraverso il sensore a ultrasuoni HC-SR04 viene usata sia durante la marcia sia durante la scelta della direzione da prendere
{
  long durata,distanza; //dichiarazione variabili per la funzione
  distanza=0.034*durata/2; 
  return distanza;
}

distanza is NOT a float. Make the return type and the value returned match.

  servo1.write(40); //la prima direzione è sinistra a 45°

40 does not equal 45.

long distL,distR;
  distL=ping(); //viene campionata la distanza a destra

ping() currently returns a float. Why are you storing it in a long?

  servo1.write(130); //la seconda è fatta a destra a 135°

130 does not equal 135.

Get rid of incorrect comments, or fix them.

  if(distR<40&&distL<40)

Use the space key!

    Serial3.flush();

A sure sign that you don't understand serial communication.

Having just the receiver code is not enough. We need to see what the sender is sending. You seem to expect to read an integer value calling Serial3.read(). You will read one byte/character using SerialN.read().

  if(Serial3.available()>4)
  {
    Serial.print("incomingdata");
    while(Serial3.read()!=char(253)){Serial.read();}
    for(int i=0;i<4;i++)
    {
      serialcom[i]=Serial3.read();
      //Serial.print(Serial3.read());
    }

If there are 5 or more characters to read, read and throw away some number of them. Then, read 4 more. That won't work. You need to read and throw away characters until the 253 arrives, then wait until there are 4 more characters/bytes. Then, read the bytes/characters.

ok now I'm writing another program...I'm working with strings I'll post it when I'm finished. By the way: i know my comments are quite bad,but it's because you don't have the image of my robot...the problem is that the angles that I write aren't the same as the one of the servo (there is a ~5° difference) :slight_smile:
Thank you for the problem with long-float, I hadn't noticed, I'll fix it now.
For the problem with the sending code i've attached it to my third comment (it was with the second one but somenthing hasn't worked)
And for the last problem:I had changed this part of my code but i wanted not to save those changes, but when i've closed arduino i might have saved them by mistake, sorry :slight_smile:

Maybe is better just to start with a new code, so it'll be easier for you to help me: I have had a new idea:I "pack" a string with all the data,i send it trough the xbees and than unpack it.
the idea was a string like that: "ST;z=***x=***y=***END", where *** can be numers from 0 to 255. I packed it succesfully and seems to work. now I have to unpack it. the two programs are attached

ctrl_xbee_usbcom_v1_2.ino (1.05 KB)

ctrl_xbee_usbcom_send.ino (731 Bytes)

the idea was a string like that: "ST;z=***x=***y=***END", where *** can be numers from 0 to 255. I packed it succesfully and seems to work. now I have to unpack it. the two programs are attached

The z=, x=, and y= parts of the message are unnecessary. Just use commas. That saves three bytes. The ST; and END can be single bytes. I like < and >, myself.

Parsing is easy, after you have collected the data into an array. The following code shows how to do that.

#define SOP '<'
#define EOP '>'

bool started = false;
bool ended = false;

char inData[80];
byte index;

void setup()
{
   Serial.begin(57600);
   // Other stuff...
}

void loop()
{
  // Read all serial data available, as fast as possible
  while(Serial.available() > 0)
  {
    char inChar = Serial.read();
    if(inChar == SOP)
    {
       index = 0;
       inData[index] = '\0';
       started = true;
       ended = false;
    }
    else if(inChar == EOP)
    {
       ended = true;
       break;
    }
    else
    {
      if(index < 79)
      {
        inData[index] = inChar;
        index++;
        inData[index] = '\0';
      }
    }
  }

  // We are here either because all pending serial
  // data has been read OR because an end of
  // packet marker arrived. Which is it?
  if(started && ended)
  {
    // The end of packet marker arrived. Process the packet

    // Reset for the next packet
    started = false;
    ended = false;
    index = 0;
    inData[index] = '\0';
  }
}

Use strtok() with inData as the input and comma as the delimiter to get the z value as a string, and use atoi() on the token to get the integer value. Then, call strtok() again with NULL and comma as the arguments to get the x value as a string, and again to get the y value as a string. Use atoi() to convert to numbers.

thank you so much, I was really panicking :slight_smile: sorry for the bad code and bad comments :S next time I'll be more careful with them!
I'll try to complete the code and let you know if it worked :slight_smile:

Strange, when using this code the compiler gives me an error on the if and else if statement (expected primary expression before '=' token) but i double checked the whole code and I didn't found anything :S

Strange, when using this code the compiler gives me an error on the if and else if statement (expected primary expression before '=' token) but i double checked the whole code and I didn't found anything

Post your code, then.

The code was the one you send me, but i fixed the problem, it was simply an error with #define (I've written #Define x=2 as I added you part to my code, then I've seen my huge mistake).
Now, you said me I do not understand Serial communication, it's right, as I wrote Serial.flush() I was trying to clear the buffer, so that the data will be the newest possible. How does I clear the buffer?
Thank you for your help!

Clearing the buffer is generally not a good idea. The old flush() method did that by throwing away random amounts of unread data. I can't see how that is a good idea, unless you are resting code that re-syncs with a sender.

If that is not the goal, then every character sent was sent with the expectation that it would be important, and, therefore, read.

Why would you not want to read that data, if you sent it?

If you don't want the Arduino to have to read the data, don't send it.

I need to have always the more recent data sent, so that the car has the latest command i gave her, If the buffer fills quicker than arduino reading it's data I would have always an encreasing delay from my commands and what the robot does, isn't it?

Now as I'm writing about this I've thought:I could add a part of code that sends an "ok" when it's ready to recive, so the ground station sends it's data and the car recive only those one, leaving the buffer clear when I don't need data and ready to recive as I have to use them. would that work?

My first idea was: ground station continues sending data, car reads the latest sent. I clear the buffer so that the data aren't too old
Now: car needs data, send a byte to the G.station, which sends back the array of data needed. No useless communication, no buffer filling up with data i don't need ,as you said, REALLY the latest data availale.
Right?

If the buffer fills quicker than arduino reading it's data I would have always an encreasing delay from my commands and what the robot does, isn't it?

Yes. So, don't let that happen. Get rid of any delay()s, so that you spent most of your time checking to see if there is anything to do, rather than doing nothing.

I have a little question: as I use the serial.read() function, does it need some time to delete the readen data or is it immediate? I've had some trouble because as I send something like 1,2,3 with the code you gave me I receive 1111,,,,2222,,,,3333 and I'm wondering if it's a problem with some delay() I should use. I simply read the data and put them in one array, should I use some delay to give my board the time do read and then clear the data?

does it need some time to delete the readen data or is it immediate?

It happens before the read() method returns.

I've had some trouble because as I send something like 1,2,3 with the code you gave me I receive 1111,,,,2222,,,,3333

What are you sending from? It looks to me like the problem is on the sending end.

and I'm wondering if it's a problem with some delay() I should use.

Let me see if I can express this in a way that you can understand.
N
delay(3)
o
delay(3)
i
delay(3)
s
delay(3)
n
delay(3)
e
delay(3)
e
delay(3)
d
delay(3)
e
delay(3)
d

Period. Anywhere.

I send a string from the other arduino. It's like c=<1,123,123,200> and in the code I wrote Serial.print(c). So in the end do I have to give some delay somewhere? Or should I send the data I want not as a string?

I send a string from the other arduino. It's like c=<1,123,123,200> and in the code I wrote Serial.print(c). So in the end do I have to give some delay somewhere? Or should I send the data I want not as a string?

How about C) post your code.

the sending code:

#include <SoftwareSerial.h>

const int x=2;
const int y=1;
const int z=0;
int sx=0;
int sy=0;
int sz=0;
String datapac="";
SoftwareSerial mySerial(10, 11);

void setup()
{
  Serial.begin(9600);
  mySerial.begin(9600);
  pinMode(x,INPUT);
  pinMode(y,INPUT);
  pinMode(z,INPUT);
  pinMode(10, INPUT);
  pinMode(11, OUTPUT);
}

void loop()
{
  sx=analogRead(x);
  sy=analogRead(y);
  sz=analogRead(z);
  sx=map(sx,0,1023,0,255);
  sy=map(sy,0,1023,0,255);
  sz=map(sz,0,1023,0,1);
  delay(10);
  datapac += "<";
  datapac += String(sz);
  datapac += ",";
  datapac += String(sx);
  datapac += ",";
  datapac += String(sy);
  datapac += ",";
  datapac += String(200);
  datapac += ">";
  /*if(Serial.available()>0)
  {*/
    Serial.print(datapac);
    mySerial.print(datapac);
  /*}*/
  delay(20);
  datapac="";
}

the reading/control code:
attached to the post.

ctrl_robot_HC_SR04_test_serialmov_v1_7_4.ino (11.5 KB)

String datapac="";
  datapac += "<";
  datapac += String(sz);
  datapac += ",";
  datapac += String(sx);
  datapac += ",";
  datapac += String(sy);
  datapac += ",";
  datapac += String(200);
  datapac += ">";

Why? All those Strings are unnecessary.