Resolved : XBee question

20 Dec 2009 . Edited: 27 Dec 2009

Hello,

I have mbed n°1 with an RFID reader and XBee n°1. When reading an RFID, I send it thru XBee to mbed n°2. It works perfectly but only once. It seems that the receiving code I wrote needs some reset to clean the Xbee status because even if I send the RFID value once, the Xbee n°2 is saying the ID is still coming thru indefinitely... the xbee.readable() is allways true.

I am sure this is very basic but I do not find any clue in the Serial lib. Can some one bring me some light ?

Here is the sending code :

 

while (1) {

int id = rfid.read();

if (id) {

xbee1.printf("%d/n",id);

id = 0;

}

}

 

Receiving code :

 

while (1) {

if (xbee2.readable()) {

xbee2.scanf("%d", &id);

Nokialcd.printf("RFID is %d",id);

} else {

Nokialcd.printf("Nothing");

}

}

 

Thaks in advance !

20 Dec 2009 . Edited: 20 Dec 2009

You could activate the reset pin on the xbee everytime to clear.

It takes 200 ns for the xbee to reset.

rst1 = 0; //Set reset pin to 0
wait_ms(1);//Wait at least one millisecond
rst1 = 1;//Set reset pin to 1
wait_ms(1);//Wait another millisecond

Or

You could try replacing the while(1) to while(xbee2.readable()) so that it only checks when there is a code being sent.

20 Dec 2009 . Edited: 20 Dec 2009

Hi Vlad,

 

I tried that too, modifying the revceive code like this :

 

while (1) {

if (xbee2.readable()) {

xbee2.scanf("%d", &id);

Nokialcd.printf("RFID is %d",id);

rst2 = 0; //Set reset pin to 0
wait_ms(1);//Wait at least one millisecond
rst2 = 1;//Set reset pin to 1
wait_ms(1);//Wait another millisecond

} else {

Nokialcd.printf("Nothing");

}

}

 

But got no change, the xbee2.readable() is still true. In fact, if I remove the XBee n°2 from the board,  xbee2.readable()  is still true !!!

20 Dec 2009

For my xbee experiments I have been using getc and putc commands. Maybe try storing the value in a char array, then printing it to the screen, then deleting it, that way you know when all your characters are delivered. When new values come it simply just overwrite the array and print the new value.

20 Dec 2009

After several more tests, it seems the the scanf does not clear the Xbee or mbed buffer thus keeping the serial readable() function to true. Note sure which buffer yet, may be mbed as I can turn off the Xbee without changing the readable() value.

If I cannot find a solution I will have to do a char array but that's going to take some time.

20 Dec 2009 . Edited: 20 Dec 2009

Hi Stephane,

I'd check how many items scanf thinks it is reading.

Looking at your code, you send "%d\n", but only read "%d". I'd therefore guess it works the first time as it'd see a number, but then repeatedly fail (scan no elements) as \n isn't a number, but the input would remain readable as you'd never read the rest of the buffer.

Simon

20 Dec 2009

Ok,

 

Now it works. I thought that the buffer was not empty so after two tests, I discovered that adding twice Xbee.getc() I would clean up the buffer so working receive code is :

Receiving code :

 

while (1) {

if (xbee2.readable()) {

xbee2.scanf("%d", &id);

xbee2.getc();

xbee2.getc();

Nokialcd.printf("RFID is %d",id);

} else {

Nokialcd.printf("Nothing");

}

}

It is not very clean but it does the job. Any idea why ?

20 Dec 2009

The double getc is because you are listening to two serial monitors, one on the mbed and one on the computer. When I was usng an arduino and an mbed the same thing happened to me.

20 Dec 2009

And to justify the two getc's (rather than the one that would be the workaround based on my previous explaination), that'd be because you are sending "/n" i.e. two characters, rather than "\n" i.e. one newline character.

Simon

20 Dec 2009 . Edited: 20 Dec 2009

Hello Simon,

If I remove the /n in the send, the receive doesn't work, so adding the /n was my workaround and adding twice getc() was a workaround for my workaround ;-)

Without the /n, the readable() is true but the mbed get stuck on the Xbee.scanf() as if waiting for something to finish the scan and nothing happens anymore.

 

Final test :

I added /n also in the scanf and now it works without the two getc.

So :

no /n in serial printf and scanf, it is stuck on first read

with /n in printf and scanf, it works smoothly

Good night !

24 Dec 2009

Stephanie,

I think what Simon is saying is that you are sending "/n" which is not the newline character.  All you've done is mixed up the direction on your slash (it matters!).  The newline character is actually '\n' (one character) and what you're sending is interpreted as '/' and 'n' (two characters).

Ryan

24 Dec 2009

Yes... I know I inverted the \ ... that's what happen we you stop using a language for 20 years ;-)

What I do not understand is why should I have to add something in the scanf and printf to get the correct result. If I do not, the scanf is stuck.

25 Dec 2009

The reason that it fails with just the scanf() is that you are only removing an integer from the buffer.  The scanf() will only read exactly what you tell it to from the input buffer, and you only told it to get a %d.  Since you sent the integer plus "/n" you have two characters left in the buffer ('/' and 'n').  The two getc()'s remove these two characters and empty the buffer so that xbee2.readable() returns false.

This code should work and be more elegant:

 

Sending code :

while (1) {

int id = rfid.read();

if (id) {

xbee1.printf("%d\n",id);

id = 0;

}

}

 

Receiving code :

while (1) {

if (xbee2.readable()) {

xbee2.scanf("%d %*c", &id);

Nokialcd.printf("RFID is %d",id);

} else {

Nokialcd.printf("Nothing");

}

}

 

The "%*c" in the scanf() tells it to read a character but not store it.  So the "%d" reads and stores the integer and then the "%*c" removes the '\n' from the input buffer.  Let me know if this works out.

27 Dec 2009 . Edited: 27 Dec 2009

I tryed your code but it does not clear the input buffer completely. To have the couple printf/scanf working, I need to add something the the code :

 

  • xbee1.printf("%d",id);
  • xbee2.scanf("%d",&id);

does not work but :

  • xbee1.printf("%dANYTHING",id);
  • xbee2.scanf("%dANYTHING",&id);

works fine, with ANYTHING being any char or word or whatever... but ANYTHING cannot be empty. Could this comes from the library (Serial in mbed lib) ?

27 Dec 2009

Hi Stephane,

  • xbee1.printf(%dANYTHING",id);
  • xbee2.scanf(%dANYTHING",id);
works fine, with ANYTHING being any char or word or whatever... but ANYTHING cannot be empty. Could this comes from the library (Serial in mbed lib) ?

The behaviour is exactly as I'd expect, so I wouldn't be looking for a problem in the libraries. You've *almost* answered your own question, so I'm going to let you work it out :)

Here is a hint; think about what scanf has to do to complete your requested call. Perhaps work through it on paper. I think you'll then be hit by the 'doh' moment and see why this behaviour is exactly expected (and correct). Then perhaps you can explain it to everyone else - you may be the first, but won't be the last!

Simon

27 Dec 2009

You are teasing me Simon ;-)

I have not been hit by the 'doh' moment yet but I have seen that my copy and paste of the code was wrong (missing " and &) in the scanf line so I edited the post. I wish I had my K&R on hand, but I will do a web search to find some hint.

27 Dec 2009 . Edited: 27 Dec 2009

Ok, I just didn't want to give you the answer when you'd done so much good work narrowing it down!

So, close your eyes and imagine you are scanf. And i've just told you to read a decimal number (%d) from the serial port. What is your logic?

You wait eagarly for a character to come in....

Ah, here's one! A '2' just arrived. So the answer is 2!

Or is it? What if the next character to arrive is a 4? Would the answer still be 2? Or 24?

So the underlying problem you have in your design is you have devised a communication protocol with variable length encoding (a plain decimal number) with no delimeter (e.g. \n) so it is impossible to know when something ends and the next starts. You are seeing a "hang" because the scanf has no choice but to wait for the next character to see if it is a number. Either no character will ever come if you only sent it once, or it will come but despite being the start of the next number, it doesn't know that is what you intended so has to assume it is still part of the first (either way; hang!). 

So the standard solutions to solve this may be:

  • Use a delimiter (e.g. comma, new line, etc)
  • Use a fixed length code (e.g. print out the number to always contain a certain number of zero padded digits; printf("%06d", value))

Hope this makes it clear on why it works like this, and some possible solutions.

Simon

btw, I think a good solution would be:

xbee1.printf("%d\n",id);
xbee2.scanf("%d\n",&id); 

as a new line is a natural way to seperate elements as used in csv. Then for example, you could start sending more data per packet:

xbee1.printf("%d,%d\n",x, y);
xbee2.scanf("%d,%d\n",&x, &y); 

and also be able to read it on a terminal, store it in a file, or open in excel easily.

27 Dec 2009 . Edited: 27 Dec 2009

Thanks,

In fact I was thinking something like that was going on but I concidered I was wrong because I was thinking numbers as 2 or 24. I thought that %d was indicating to send or to receive an int so 32 bits as I was using a Serial device and not a screen / keyboard. So sending 32 bits with the printf and expecting 32 bits with the scanf should have done the job. I think my logic was too low level, that was my mistake. In fact I did not know if these two functions were talking binaries or at a higher level, like chars to describe the number.

Thanks again for the teach !

24 Oct 2011

Anyone use API command to write some program for xbee?Recently i am trying to write a program to lighting up the light through xbee.but i dont have any idea about it.anyone do the similar thing before?need help!!!!!!!!

Thanks in advance!!