Get no reponse from Xbee

Hello everyone,
i am writing a small c program in Kubuntu system to communicate with Xbee. The prog is very simple, just open the serial port device file(ex:ttyS0, which is connected to Xbee development board),write a AT command string(ex: ‘atnd\r’ to search all the nodes nearby), and read the answer after then. Everything goes well if i put all of them together(including sub methods: send_PacketFrame(), receive_PacketFrame(), other sub function. and the main() function) in a single file. But when i tried to put these sub methods in a shared library file whose name is ended by .so, and create a seperate file for main(), in some of the sub function, the Xbee never answer the request and wait till the timeout(like the following example). i tested the basic function(such like send_PacketFrame(), receive_PacketFrame(), they work), and i’ve tested also a method who tried to get the temperature value from a remote device in API mode, it works too for me. But some command like ‘atnd\r’, ‘at\r’, Xbee never reponse.

i was really confused. because there are so few steps, i don’t understand where the problem is. Is there anyone who can help me out of this, i struggle with it for a long time, that really makes me nervous. A lots of thanks.

i list some of my code in the following :
int get_xbee_nodes(char *str)
{
char AT[5]={‘a’,‘t’,‘n’,‘d’,‘\r’};
int i;
int nbytes=1;
int length=0;
char *ptrFrame;

send_PacketFrame(AT,5);//send AT string, 5 is the length of str

while(nbytes>0)
{
nbytes=receive_Packet(ptrFrame,255);//read 255 bytes from serial port, ptrFrame pointer to the beginning of result string, nbytes indicates the result length
ptrFrame=strndup(ptrFrame, nbytes);
strcat(str, ptrFrame);
length=length+nbytes;
}
//because each time it returns just 8 bytes, i write a loop here to get an entire reponse

return 0;
}

i also tried adding some time repos: sleep(1) between send and receive function, it didn’t work either.

Hmm. I think there are a few problems here.

  1. Your loop reads characters from the serial buffer, and exits when an attempted read doesn’t return any characters. Trouble is, the loop will take very little time to execute, so you’re likely to find there are no characters in the buffer simply because the next one hasn’t arrived yet. That will cause the loop to exit before it should. In this case, you’re using the ND command as the example. With ND, the XBee has to send out a broadcast transmission and then wait for other nodes to respond, so there will be very considerable time lags during which the serial buffer remains empty.

I’m making assumptions here about how your receive_Packet function operates, but I can’t imagine how it would avoid the above problem unless it has a long timeout built into it.

  1. This also bears on how receive_Packet is defined. The first time round the loop, you’re passing it the ptrFrame parameter which is at that stage an uninitialised variable. If the function assumes it’s being given the address of a buffer, it’ll put any returned characters into a random memory location - likely with dire results.

  2. You’re then calling strndup and strcat to move the received data around. Those functions both expect to work with zero-terminated strings, which is not what you’ve got. I think I can see what the idea is, though: use strndup to copy the number of bytes you have, and because it will then add a zero byte, strcat will do what you expect of it.

The problem then is that strndup returns a pointer to a new chunk of memory obtained from malloc(3), which will contain the bytes copied from the serial buffer. You then use strcat to copy the same bytes to the end of that memory chunk, which will cause an overflow and overwrite the memory beyond that allocated.

So to summarise: I suspect the loop will only ever run once, because the XBee won’t yet have returned any bytes. And if it does run more than that, memory corruption will be the result. Oh, and strndup’s use of malloc guarantees a memory leak into the bargain.

If I can make a few suggestions:

  1. Try a very simple AT command (eg VR) instead of ND, until you get this part working.
  2. Don’t exit the loop if there’s no data this time round. Look for the terminating ‘\r’ instead, and exit on that. If you then want to use the ND command, you’ll have to be prepared for multiple response lines with a blank line indicating the end of the transmission.
  3. Make ptrFrame an array of char instead of a pointer to char, and collect the response in there.

Hope that helps a bit.

thanks johnf,
that helped.
i think my mainly problem is the segmentation failed.Right now i made all my pointers point to the char typed array, and keep the other part unchanged,and then i got my response from xbee.

as far as my loop, i think it doesn’t have issus, because when i send a AT command, itself has a timeout, during this time, the prog keep the serial port open, and wait the response.

i have a new question about getting the Xbee response.

the method which allows to get the response from serial port(nbytes=receive_Packet(ptrFrame,255))as i mentioned above, in my case here each time it can only return back 8 bytes, so, to get a complete reply, a loop ‘while’ is needed here.

But in my another test, i used the same method, it can return back all the response at one time(about 31 bytes), it’s very weird, i did both test in the same Xbee module, why can’t this test return back all the response? Is there any way to get the complete reply from Xbee without loop?

There are some points here:
So far I saw this is for a simple test that you send data and then you receive the response. So to fix this I would simple make a delay (between the send output and read input) so that you give some time to receive the data in the serial buffer.
Now in my personal opinion, to make this work in a more generic way you will need to use threads and/or events. One continuous thread that reads the input or using events you wait for the “inputdata” event and then check the length and read it.

Yes, you’re quite right.

One example of the need for threads or events (I use events) is the modem status packet, which the XBee can decide to send at any time. So you have to be continuously listening, and you have to be able to decode and interpret that packet even if you were expecting something else.

Another example is if you want periodic sampling of input lines. After you set that up, you’ll receive line sample packets at whatever interval you set, and again you have to be able to catch these whenever they arrive.