Go Down

Topic: How to Measure packet delivery delay & End-End Delay Using Arduino & Xbee S2 (Read 1 time) previous topic - next topic

Hello. I am working on a simple wireless sensor network project but i don't know how to measure packet delivery time and end to end delay time using Arduino and Xbee. I would really appreciate if someone could show me the codes as how can i do this. I will be sending a packet from Xbee S2 on Arduino to a remote Xbee S2 and measuring the round trip time and delay...

Assistance will be highly appreciated.

PaulS

Quote
I will be sending a packet from Xbee S2 on Arduino to a remote Xbee S2 and measuring the round trip time and delay...

What do you need help with? Recording when you start to send the information is easy enough. Recording when the complete response has been received is easy enough. So, you have round trip time. Delay comes in so many places that you will have an incredibly difficult time measuring that.

It takes time to buffer the data in the Arduino's serial buffer. It takes time for the interrupts to shift the data out to the radio. The radio needs to collect the data and convert it to radio waves. Obviously, that is not an instantaneous process. The radio waves take time to travel. On the receiving end, it takes time to reverse the process, make some decisions, and generate a response.

That responses needs to undergo the same process to get back to the sender.

How much of that time do you consider delay? Exactly what are you trying to measure? For what purpose? You don't be able to determine distance between sender and receiver, if that is your intent.

I have prepared a code for sending and receiving from Arduinos. The Master arduino sends Hello World while the slave arduino listens and replies with "ACK". Could you please advice if this method is correct for calculating total time of packet delivery with ACk.

Please advice.
Thanks in advance.

Master Arduino(Transmitter with Xbee)


unsigned long startTime;
unsigned long RoundTripTime;

void setup() {

  Serial.begin(9600);
}


void loop()
{
 
//startTime = micros();
Serial.print("Hello World");
startTime = micros();
 
while(!Serial.available()){}
   char bdata;
   String data = "";
 
while(Serial.available() > 0)
{
   bdata = Serial.read();
   data += bdata;
   delayMicroseconds(1050);


if(data == "ACK")
{
     
     RoundTripTime = micros() - startTime;
     //Serial.println("Total time: ");
     Serial.println(RoundTripTime);
}

delay(2000); // prevents overwhelming the serial port
}



Slave Arduino(Receiver Xbee)



void setup()
{
  Serial.begin(9600);
}

void loop()
{
  // listen out for the letter "H", and send a "K" if we get one.
  while(!Serial.available()){}
 
  char bdata;
  String data = "";
 
  while(Serial.available() > 0)
  {
   bdata = Serial.read();
   data += bdata;
   //delay(2);
   delayMicroseconds(1050);
  }
 
  //Serial.println(data);
 
  if(data == "Hello World")
  //{
    Serial.print("ACK");
   
  //delay(1000);
}

PaulS

Quote
Could you please advice if this method is correct for calculating total time of packet delivery with ACk.

No. That is crap.

Code: [Select]
Serial.print("Hello World");
startTime = micros();

The data has been put in the outgoing buffer when Serial.print() returns. It has NOT been sent. So, startTime is meaningless.

Code: [Select]
while(Serial.available() > 0)
{
   bdata = Serial.read();
   data += bdata;
   delayMicroseconds(1050);

WTF is that delay() in there for? There is serial data to read. Read it. Quit dilly-dallying around.

And, get rid of the String class. If you can't manage to read "ACK" without it, get a book on C and learn about strings.

I would appreciate if you could provide the correct method or code to do that please. Also if you could just restructure the given code in the way it supposed to work.

Will be a great help.

PaulS

With 1.0 and later, the Serial.flush() blocks until the last character in the buffer has been grabbed for sending (not sent). There is a way to determine when that character has actually been sent, but that would simply remove a constant amount of time from your measurement.

Since I can't see the point of what you are trying to measure, I'm not going to worry about that last character.

Once the last flush() method returns, then record the time.

Wait for there to be serial data AND for the received data to be "ACK". Then, record the end time.

Code: [Select]
char buff[10];
byte index = 0;
bool gotACK = false;

void setup()
{
   buff[0] = '\0';
}

void loop()
{
   // send some data

   while(Serial.available() > 0 && !gotACK)
   {
      char letter = Serial.read();
      if(index < 9)
      {
          buff[index++] = letter;
          buff[index] = '\0';

          if(strcmp(buff, "ACK") == 0)
          {
              gotACK = true;
              break;
          }
      }
   }

   if(gotACK)
   {
      stopTime = micros();
      // Do whatever...

      buff[0] = '\0';
      index = 0;
      gotACK = false;
   }
}

Thanks PaulS for your prompt feedback. All i am trying to measure is how long its takes to send Hello World and receive ACK in return. ACK indicates that the remote xbee has actually got the packet.

Thanks once again for your time.

Dear PaulS
I have adopted your code it seems that there is still some hiccups.The program receives "ACK" but is not able to read the whole packet at once without giving some delay in the code. In the 1st loop it reads "A" then in the second loops "CK" to make the complete buffer. That's why i have introduced some delay. 
What shall i do to improve this?????   I want to send Hello World then wait for ACK from remote device and calculate the time it takes for this process.

Please correct me if I am wrong since this is the learning phase for me.

//******************************************************************************************
char buff[10];
byte index = 0;
bool gotACK = false;
unsigned long startTime;
unsigned long stopTime;
unsigned long RTT;
void setup()
{
  Serial.begin(9600);
  buff[0] = '\0';
}

void loop()
{
   // send some data
   startTime = micros();
   Serial.print("Hello World");
   
   while(!Serial.available()){}

   while(Serial.available() > 0 && !gotACK)
   {
     
      char letter = Serial.read();
      delayMicroseconds(1030);
      if(index < 9)
      {
          buff[index++] = letter;
          buff[index] = '\0';
         
          if(strcmp(buff, "ACK") == 0)
          {
              gotACK = true;
              break;
          }
      }
   }

   if(gotACK)
   {
      stopTime = micros();
      // Do whatever...
      RTT = stopTime- startTime;
      Serial.println(RTT);
      buff[0] = '\0';
      index = 0;
      gotACK = false;
   }

   delay(500);
}

   
Please assist me.......... =(

PaulS

Quote
The program receives "ACK" but is not able to read the whole packet at once without giving some delay in the code.

That is because serial data transmission is ssslllooowww. On any one iteration through loop, there will not necessarily be a while packet to read.

Quote
In the 1st loop it reads "A" then in the second loops "CK" to make the complete buffer.

That is what it is supposed to do.

Quote
That's why i have introduced some delay.

Wrong.

Quote
What shall i do to improve this?????

Develop some realistic expectations. Serial data transmission is slow. Expect that. There is NOTHING you can do to make it faster except increase the baud rate, up to the maximum supported.

Quote
I want to send Hello World then wait for ACK from remote device and calculate the time it takes for this process.

You are doing that. What difference does it make if you get A at 1:30, C and 2:15, and K at 4:30 versus getting ACK at 4:30?

Quote
Please assist me..........

I can't. The program is doing what you programmed it to do. That you do not understand how serial data transmission works and/or have unrealistic expectations is not something I can help you with.

Go Up