Send RSSI to coordinator

Hi, guys, I wrote a simple program to send the RSSI from a router to coordinator. All the ZigBee modules are DIGI Xbee. However, it doesn’t work. In fact, I can receive nothing. Can anybody help me?

/******************************************************************
*
* Xbee API mode code summer 2012
*
******************************************************************/
/*
variables types on Arduino:
byte - 1 byte; short OR int - 2 bytes; long - 4 bytes
*/

/****** GLOBAL VEARIABLES ******/
byte inquiry_data[1] = {99};//array will look like--> {1st byte, 2nd byte, ...,'\0'} //last one is null char
byte length = sizeof(inquiry_data);
byte rssi_value[1];
byte ID_count = 0x01;
char ATcommand [] = "DB";


/****** FUNCTION PROTOTYPES ******/
void XbeeTransmitRequest(byte payload[], byte arraylength, byte reply_switch); //sends data to the coordinator;
byte XbeeATcommand(char ATcommand[]);


/****** SETUP RUNS ONCE ******/
void setup() {
Serial.begin(9600);
}


/****** MAIN ******/
void loop() {
  
  XbeeTransmitRequest(inquiry_data, length, 1); //this function call would be integrated into our main program
                                                //data is the data array; DATALENGTH is # elements in the array
  rssi_value[0] = XbeeRSSI();
  XbeeTransmitRequest(rssi_value, 1, 0);  
  delay(700);
}


/****** XbeeTransmitRequest FUNCTION: SENDS A BYTE ARRAY TO COORDINATOR ******/

void XbeeTransmitRequest(byte payload[], byte arraylength, byte reply_switch) { 
  long datasum=0;//for checksum
  int frame_length = 1+1+8+2+1+1+arraylength;
  //1 BYTE - START BYTE
  Serial.write((byte)0x7E); 
  
  //2 BYTES - LENGTH
  Serial.write((byte)0x00); // high part of length (always zero because max payload <=92 bytes)
  Serial.write((byte)(frame_length & 0xFF)); // low part of length (the number of bytes that follow, not including checksum)
  
  //1 BYTE - FRAME TYPE 
  Serial.write((byte)0x10); // 0x10 is transmit request frame; 0x17 is a remote AT command
  
  //1 BYTE - FRAME ID
  if(reply_switch == 0){
    Serial.write((byte)0x00); // frame id set to zero for no reply
  } else {
    Serial.write((byte)0x01);
  } 
  //8 BYTES - 64 bit ADDR OF RECIPIENT, or use 0x0000 0000 0000 FFFF for broadcast, 
  //or 0x0000 0000 0000 0000 for coordinator
  Serial.write((byte)0x00);Serial.write((byte)0x00);
  Serial.write((byte)0x00);Serial.write((byte)0x00);
  Serial.write((byte)0x00);Serial.write((byte)0x00);
  Serial.write((byte)0x00);Serial.write((byte)0x00); 
  
  //2 BYTES - 16 bit ADDR OF RECIPIENT or 0xFFFE if unknown (can be discovered if know 64 bit addr; each xbee can only remember 10 pairs)
  Serial.write((byte)0xFF);Serial.write((byte)0xFE);
  
  //1 BYTE - BROADCAST RADIUS (# HOPS)
  Serial.write((byte)0x00); //0 for no limit
  
  //1 BYTE - OPTIONS; 
  //0x00 do nothing; 0X01 disable retries/route repair; 
  //0x20 enable APS encryption; 0x40 use extended transmission
  Serial.write((byte)0x00);
  
  //MAXIMUM 84 BYTES - DATA;
  short i=0;
  for(i=0;i<arraylength;i++){ 
    Serial.write(payload[i]);
    datasum = datasum + payload[i];
  }
  
  //1 BYTE - CHECKSUM (all bytes after length bytes)
  long sum = 0x10 + 0xFF + 0xFE + datasum + reply_switch;
  Serial.write(byte((0xFF - sum) & 0xFF)); // calculate the proper checksum
  // serial port (if this function is not implemented properly)
}


/**** XbeeRSSI FUNCTION: GET THE RSSI VALUE ***********/

byte XbeeRSSI(void) { 
  byte RSSI_value = 0x00;
  int frame_length = 1+1+2;
  
  //1 BYTE - START BYTE
  Serial.write((byte)0x7E); 
  
  //2 BYTES - LENGTH
  Serial.write((byte)0x00); // high part of length (we know it's 0 here)
  Serial.write((byte)(frame_length & 0xFF)); // low part of length (the number of bytes that follow, not including checksum)
  
  //1 BYTE - FRAME TYPE
  Serial.write((byte)0x08); //indicate it's an AT command
  
  //1 BYTE - FRAME ID
  Serial.write((byte)0x01); // frame id set to zero for no reply
  
  //2 BYTES - THE AT COMMAND
  Serial.write((byte)'D'); 
  Serial.write((byte)'B');
  
  //1 BYTE - CHECKSUM (all bytes after length bytes)
  byte sum = 0x08 + 0x01 + byte('D') + byte('B');
  Serial.write(byte((0xFF - sum) & 0xFF)); // calculate the proper checksum
  
  delay(100);
  
  while(Serial.available() < 9){
    if(Serial.available() >= 9) {
     //available() gets # of bytes available for reading from the serial port. 
    if(Serial.read()==0x7E){
      Serial.read();//frame length high
      Serial.read();//frame length low
      Serial.read();//frame ID
      Serial.read();//AT command part 1
      Serial.read();//AT command part 2
      Serial.read();//Command status
      RSSI_value = Serial.read();//RSSI data
      Serial.read();//checksum
      return RSSI_value;
     }
    }
  }
  return 0xEE;`  
}
while(Serial.available() < 9){
    if(Serial.available() >= 9) {
     //available() gets # of bytes available for reading from the serial port. 
    if(Serial.read()==0x7E){
      Serial.read();//frame length high
      Serial.read();//frame length low
      Serial.read();//frame ID
      Serial.read();//AT command part 1
      Serial.read();//AT command part 2
      Serial.read();//Command status
      RSSI_value = Serial.read();//RSSI data
      Serial.read();//checksum
      return RSSI_value;
     }
    }

The while statement will evaluate how many bytes of serial data are waiting to be read. The body of the statement will not be executed unless there are fewer than 9 bytes.

Inside the body, you do nothing unless there are at least 9 bytes available to be read.

However, it doesn’t work.

I’m not surprised.

First, thank you for your reply.

And second, YES! What I do is to use a AT command frame to request RSSI, I want to get a AT command response. The response frame will take 9 bytes. I just wait for 9 bytes, and then I begin to read.

I think this procedure will be fine. Why it doesn't work?

I think this procedure will be fine.

I think is won’t. Ignoring for a minute what should happen in the if statement, you have this, to which I have added comments:

while(Serial.available() < 9){
// You get here when Serial.available returns 0, 1, 2, 3, 4, 5, 6, 7, or 8, but NOT when it returns 9 or more
    if(Serial.available() >= 9) {
      // The if test is ALWAYS false since the only values that cause if to be available are less then 9
    }
|

Thank you.

I know what you mean and I know there maybe a dangerous loop. However, the AT command response should send back and it should have 9 bytes. If I don't use this loop or if, how can I get the RSSI?

If I don’t use this loop or if, how can I get the RSSI?

Separate the two things you are trying to do. First, wait for there to be 9 bytes to read. Then, read them.

while(Serial.available() < 9)
{
   // Do nothing
}
if(Serial.available() >= 9) // Not really necessary, since this test won't be performed unless there are
{
   // Read the 9 bytes
}

I see! OK, alright, I revise it. However, unfortunately, it still doesn't work. Now I don't know why.

tfpeach: I see! OK, alright, I revise it. However, unfortunately, it still doesn't work. Now I don't know why.

Then post the new version.

OK? the code is shown as below. I have tested the sending part. They are fine. So I am sure the problem should be in the RSSI calculation part.

/******************************************************************
*
* Xbee API mode code summer 2012
*
******************************************************************/
/*
variables types on Arduino:
byte - 1 byte; short OR int - 2 bytes; long - 4 bytes
*/

/****** GLOBAL VEARIABLES ******/
byte inquiry_data[1] = {99};//array will look like--> {1st byte, 2nd byte, ...,'\0'} //last one is null char
byte length = sizeof(inquiry_data);
byte rssi_value[1];
byte ID_count = 0x01;
char ATcommand [] = "DB";


/****** FUNCTION PROTOTYPES ******/
void XbeeTransmitRequest(byte payload[], byte arraylength, byte reply_switch); //sends data to the coordinator;
byte XbeeATcommand(char ATcommand[]);


/****** SETUP RUNS ONCE ******/
void setup() {
Serial.begin(9600);
}


/****** MAIN ******/
void loop() {
  
  XbeeTransmitRequest(inquiry_data, length, 1); //this function call would be integrated into our main program
                                                //data is the data array; DATALENGTH is # elements in the array
  delay(500);
  //rssi_value[0] = XbeeRSSI();
  //XbeeTransmitRequest(rssi_value, 1, 0);  
  delay(500);
}


/****** XbeeTransmitRequest FUNCTION: SENDS A BYTE ARRAY TO COORDINATOR ******/

void XbeeTransmitRequest(byte payload[], byte arraylength, byte reply_switch) { 
  long datasum=0;//for checksum
  int frame_length = 1+1+8+2+1+1+arraylength;
  //1 BYTE - START BYTE
  Serial.write((byte)0x7E); 
  
  //2 BYTES - LENGTH
  Serial.write((byte)0x00); // high part of length (always zero because max payload <=92 bytes)
  Serial.write((byte)(frame_length & 0xFF)); // low part of length (the number of bytes that follow, not including checksum)
  
  //1 BYTE - FRAME TYPE 
  Serial.write((byte)0x10); // 0x10 is transmit request frame; 0x17 is a remote AT command
  
  //1 BYTE - FRAME ID
  if(reply_switch == 0){
    Serial.write((byte)0x00); // frame id set to zero for no reply
  } else {
    Serial.write((byte)0x01);
  } 
  //8 BYTES - 64 bit ADDR OF RECIPIENT, or use 0x0000 0000 0000 FFFF for broadcast, 
  //or 0x0000 0000 0000 0000 for coordinator
  Serial.write((byte)0x00);Serial.write((byte)0x00);
  Serial.write((byte)0x00);Serial.write((byte)0x00);
  Serial.write((byte)0x00);Serial.write((byte)0x00);
  Serial.write((byte)0x00);Serial.write((byte)0x00); 
  
  //2 BYTES - 16 bit ADDR OF RECIPIENT or 0xFFFE if unknown (can be discovered if know 64 bit addr; each xbee can only remember 10 pairs)
  Serial.write((byte)0xFF);Serial.write((byte)0xFE);
  
  //1 BYTE - BROADCAST RADIUS (# HOPS)
  Serial.write((byte)0x00); //0 for no limit
  
  //1 BYTE - OPTIONS; 
  //0x00 do nothing; 0X01 disable retries/route repair; 
  //0x20 enable APS encryption; 0x40 use extended transmission
  Serial.write((byte)0x00);
  
  //MAXIMUM 84 BYTES - DATA;
  short i=0;
  for(i=0;i<arraylength;i++){ 
    Serial.write(payload[i]);
    datasum = datasum + payload[i];
  }
  
  //1 BYTE - CHECKSUM (all bytes after length bytes)
  long sum = 0x10 + 0xFF + 0xFE + datasum + reply_switch;
  Serial.write(byte((0xFF - sum) & 0xFF)); // calculate the proper checksum
  // serial port (if this function is not implemented properly)
}


/**** XbeeRSSI FUNCTION: GET THE RSSI VALUE ***********/

byte XbeeRSSI(void) { 
  byte RSSI_value = 0x00;
  int frame_length = 1+1+2;
  
  //1 BYTE - START BYTE
  Serial.write((byte)0x7E); 
  
  //2 BYTES - LENGTH
  Serial.write((byte)0x00); // high part of length (we know it's 0 here)
  Serial.write((byte)(frame_length & 0xFF)); // low part of length (the number of bytes that follow, not including checksum)
  
  //1 BYTE - FRAME TYPE
  Serial.write((byte)0x08); //indicate it's an AT command
  
  //1 BYTE - FRAME ID
  Serial.write((byte)0x01); // frame id set to zero for no reply
  
  //2 BYTES - THE AT COMMAND
  Serial.write((byte)'D'); 
  Serial.write((byte)'B');
  
  //1 BYTE - CHECKSUM (all bytes after length bytes)
  byte sum = 0x08 + 0x01 + byte('D') + byte('B');
  Serial.write(byte((0xFF - sum) & 0xFF)); // calculate the proper checksum
  
  delay(500);
  
  while(Serial.available() < 9){
  }
  if(Serial.available() >= 9) {
     //available() gets # of bytes available for reading from the serial port. 
    if(Serial.read()==0x7E){
      Serial.read();//frame length high
      Serial.read();//frame length low
      Serial.read();//frame ID
      Serial.read();//AT command part 1
      Serial.read();//AT command part 2
      Serial.read();//Command status
      RSSI_value = Serial.read();//RSSI data
      Serial.read();//checksum
      return RSSI_value;
    }
  }
  return 0xEE; 
}

o I am sure the problem should be in the RSSI calculation part.

It could be. All we know about the problem, though, is "it still doesn't work. Now I don't know why.". You have to help us out here.

Are you getting to the code that gets the RSSI value?

  //rssi_value[0] = XbeeRSSI();

It hardly looks like it.

If you are, is that RSSI value reasonable?

byte rssi_value[1];

A one element array. How useful. Not! Why is rssi_value an array?

Yes, you get the point. You can see the sending code. We design that it has a array argument. So, it can be used other places. Now we just use it to send a byte RSSI value. That's why I write a only one element array.

But I think this will not affect the result.I can tell you what I did.

First, in the "loop" function, I only wrote one sentence which is the sending function call. You can see I send a "99" to the coordinator. And then I received it in the end of coordinator. That proves this part correct.

Second, I added a sentence in the "loop" which is the equation to calculate the RSSI and assign it to the element in the array. At this step, the coordinator received nothing. This means it succeeded in running the first sentence, but failed in the second.

Third, I took the suggestion to revise the "while" to redo the second step. However it still failed. This means there is no 9 bytes response frame sent back, or in other words, after I send the AT command to the router, I can only get something which is less then 9 bytes. Because, it will never jump out the "while" loop.

I don't know why I can not get 9 bytes AT command response.

How are your XBees connected to your Arduinos? Getting the XBee off the serial port is going to be necessary to allow you to debug your code.

Second, I added a sentence in the "loop" which is the equation to calculate the RSSI and assign it to the element in the array. At this step, the coordinator received nothing. This means it succeeded in running the first sentence, but failed in the second.

The "sentence" in the "loop" to calculate the RSSI value is commented out. That means it doesn't get executed.

The second request to transmit data is also commented out. You have, therefore, drawn an incorrect conclusion here.

Oh, sorry to confuse you. Yes, they are commented out. Because this is a testing version. In the original one, they are executed. Since they don't work, I comment the last two out. Then I find the first one works well. Once I add the second one, it doesn't work.

Once I add the second one, it doesn't work.

It doesn't work doesn't tell us anything useful. The code does something. You expect it to do something. All we know is that those two somethings are not the same thing. But, we have no idea what either something is.

What are you expecting to do with the RSSI value if you end up being successful at getting/transmitting it?

Why do you need to transmit the value of one unit's RSSI value to the other? You should be able to get RSSI from either device. Sending the value of RSSI on one to the other doesn't make sense to me.

Now, this is just a test. Right, It means nothing, however, I want to achieve this goal.

Yes, the second sentence will do something. But, I just want to know why I can not get the AT command response. It's supposed to have one. Just curious.

At first, I think it may need sometime to response, so I use a delay(1000). But, I can still not get it. The manual only says after receiving the command query, it will return a RSSI value, but it doesn't tell any details about the procedure or show us the program. I just write this test program on my opinion. Now it doesn't work, so I want to know if I misunderstand something.

By the way, thank you all same for your help, though the problem is gonna drive me mad.

Does anyone else know how to get the RSSI value?