arduino - xbee - mesh

First of all, this is my first post! I started fooling around with arduino and xbee a few long days ago and have to say I really like it.

I am trying to use 4 arduino with 4 xbee (1.0) modules to communicate amongst each other and use the rssi to determine the distances between them.

I found that the xbee's need to be in API mode 1 (or 2) to be able to 'read' the rssi values.

currently I have two xbee's switching between api mode 1 and 0 to read or send data.

I dont know how to send data (and receive it on the other xbee / arduino) when it is in API mode 1.

Can anyone tell me if it is possible to determine the received signal strength in API mode 1 without having to switch to API mode 0 to send a message to the other xbee?

currently on arduino1:
api mode 0 send message
switch to api mode 1
wait for message
if message received
switch to api mode 0 and send message
loop that

same on arduino2

That works, but is terribly slow!

I hope this all makes sense and someone can help me out? Thank you very much in advance!

I think XBee's send a rather large string of numbers when in that mode. You would have to parse it somehow. I have done that from an XBee to MAX/MSP but never from XBee to XBee. I am having problems with XBee to XBee to Arduino as well.

Well, the problem is that if I put the Xbee's in API mode 1 :

Serial.println("+++");
Serial.println("ATAP1");
Serial.println("ATCN");

I somehow cant send anyting out ? or receive nothing on the other xbee? At least not by a normal Serial.println("something");

While having the xbee in API mode 0, Serial.println("something"); gives me an excellent signal on the other xbee..

I have never sent a string over an xbee in APi mode 1 only sensor data. Did you check trough a terminal like zTerm to see if anything at all is being sent? I have had dead xbees before. Also are you using series 1 or series 2?

I am using xbee's series 1.

I have a small program in processing when i work on a mac to see what is being send. On a pc i use x-ctu to see what is being send around.

I also do get data, but somehow i cant figure out how to get the rssi (bit 6) out of a package send in api mode 1 while i can get it out quite simple if it was send in api mode 0..

some code:

a function i use on arduino to read incoming data and get the rssi and address out of it:

void read_func(){
 // digitalWrite(statusLed,HIGH);
 if (Serial.available() > 13) {   //checks to make sure that we have received at least one frame worth of bytes
  int inByte = Serial.read();    //reads the incoming API string
  if (inByte == 0x7E ) {          // (first byte)looks for tilda (ox7E) place holder?marks the beginning of the string
   for (int i=0;i<4;i++) {
    int junk = Serial.read();  // (next four bytes)  reads and discards the next four bytes that we?re not going to use
   }
   address = Serial.read();       // the sixth byte is the low part of the address (ONLY USE ONE BYTE ADDRESSES!)
   RSSI = Serial.read();          // the seventh byte is the RSSI value
   /*
   for (int i=0;i<7;i++) {
    int junk = Serial.read();     //reads and discards the last six bytes of the API string. We dont need them. Whats in them? beats the crap outta me.
   }
   */
   Serial.flush();
   handleRx(address, RSSI);
  }
 }  
 //digitalWrite(statusLed,LOW);
}

The RSSI is the seventh bit (but the 6th in the array). Also series one cannot due true mesh networking but you can fake it good enough.

I would have the Arduino println the data to see exactly what it is receiving. It could be reading the incoming data incorrectly. Sometimes the Arduino is too fast other times to slow. You could try to put
while (Serial.available() == 0);
in between your reads to make sure it is not reading empty data from the serial port.

I would recommend checking out Tom Igoe's Making Thing Talk Book. He has a program in Processing on page 274 that parses the data from a XBee. I have similar code posted somewhere.

The previous bits will be important later because they tell you which Xbee is sending the data. I can post exactly what the bits are if you would like.

Yes!! I have a solution for you jarn0.

I currently have a bunch of Xbee-Arduino modules talking to each other and they are able to determine the distance between them via RSSI values. (Keep in mind that RSSI is not intended to determine proximity, so the RSSI values don't really give an accurate representation of distance.)

I have been experimenting with RSSI to determine proximity for a while: Bare - Start Bootstrap Template

I too have had problems getting RSSI values in the API mode, so I figured out a solution staying exclusively in Transparent mode.

You said:

currently I have two xbee's switching between api mode 1 and 0 to read or send data.

Just to clarify, I assume what you mean when you refer to api mode 0 and 1 is transparent mode and command mode (the mode that you must send "+++" in order to get access to the Xbee parameters. I may be wrong, I am also new to the world of Xbees.)

So this was my problem:
While in Transparent mode you must get into Command mode in order to get RSSI values. (Sidenote, in command mode you can do a ATDB command to get RSSI values, so you don't have to deal with the string of unwanted junk that the ATND command gives you.) But there is big problem with switching from Transparent mode Command mode: #1 It is slow, and #2 the Xbees can not send or receive serial data while in Command mode. In my case, I needed to send a constant stream of sensor data while occasionally polling RSSI values.

But, weeee, there is a solution!! I found a work-around that enables me to collect a constant stream of serial data AND collect RSSI data WITHOUT going into Command mode!!

It's called: PIN 6 XBEE!! (PWM0/RSSI) yay!!

Now in order to use Pin 6 to collect RSSI data, you must change some parameters on the Xbee first.

In command mode, if you type "ATP0", you will get the default "0" which indicates pin 6 is disabled. To change pin 6 to output RSSI, you will need to type "ATP01" (page 31 of the Xbee manual).

Now that the pin is in RSSI mode, you need to change the RSSI PWM Timer parameter.

If you type ATRP, you will notice that the default is 0x28 (40d). Checking page 32 of the Xbee manual, you will notice that this value has a multiplier of 100ms, so 40 = 4 seconds. Much to slow for what I want to do. I experimented around with this parameter finally setting this parameter to 10 (1000ms).

If you hook up your Xbee circuit and connect an oscilloscope to ground and Pin 6 Xbee and send data to it, you will see Pin 6 start putting out a pulse as you send data to the Xbee. This pulse represents RSSI.

Now playing with the proximity between the Xbees' you will see in the PWM frequency changing in the oscilloscope. Bringing a Xbee closer to the one outputting the RSSI, you will notice that that the pulse width will change accordingly.

Now if you connect Xbee Pin 6 to one of your digital pins on the Arduino, you can use the pulseIn function to determine the pulse width. This width corresponds to signal strength.

pulseIn reference: http://arduino.cc/en/Reference/PulseIn

If one wanted to get all of the Xbee modules (Series 1) to communicate with each other, this like is really helpful: http://www.arduino.cc/en/Main/ArduinoXbeeShield

Set the DL to OxFFFF in all of the modules and they all will receive data sent out by any one individual Xbee. (You don't even need the API mode to do this.)

I have this working with many Xbee-Arduino modules now.

Hope this is helpful.

Thank you very much for your reply muse.

Mayby you have noticed, maybe not, but this topic was quite old actually. I already found a way of using multiple xbee modules sending and receiving data and reading RSSI values meanwhile.

I did it purely by software without using the pin you are referring to.

If you or anyone else might be interested in it, just reply here and I am happy to give more details.

For now I cannot use my right (good) hand, so sorry for this short post :slight_smile:

I would like to know more. Please post as much as possible.

Dear skogberg,

I've read your email and your post, I will try to post some more info later today, but I'm a little busy. If i wont make it today it will be tomorrow or the day after.

cheers,

Jarno

Allright, here it is.

First of all this is what I made: ballding on Vimeo

The basics: Arduino, Xbee 1.0, Rgb Leds, Resistors, Battery, Mobile phone shake 'things' for extra feedback, Power supply (for recharging).

Based on the RSSI values of Xbee transmitters the distance between two balls is measured. Based on this the speed two balls have going towards eachother the color changes. The color depends on the color of the ball itself as well. Two blue balls become blue (pretty fast); two red balls become red (slower); one red and one blue ball becomes purple (hardest thing to do).

This installation was build to show differences in building and maintaining relationships in China and Western countries.

the stuff you want to know:

I use arduino and xbee v1.0 to measure the distances. I dont really use a mesh network because I just couldn't figure that out on xBee v1.0 shields.
I use a sort of 'receive and wait for 3 signals -> then send' program.
Doing it like this gives me a distance of all the balls between each other at least every 1/2 second. This was actually good enough for me.

some codesnippets:

The init:

void initXbee(){
  // clear the serial port so no buggy data will be there
  Serial.flush();
  // delay needed for.. I dont have a f*ckin clue..
  delay(1200);
  // put xbee in command mode
  Serial.print("+++");
 
  // a check could be build in:
/*
  char thisByte = 0;
  while (thisByte != '\r'){ // wait for the xbee to respond, being in command mode
    if (Serial.available() > 0){
      thisByte = Serial.read();
    }
  }
*/
  // but that is not really needed in my opinion
  // and I just use a delay
  delay(500);
  // set the low part of the address to 0 and the high part to FFFF => broadcast mode
  Serial.print("ATDH0,DLFFFF,");
  delay(10);
  // set the xbee's own address
  Serial.print("MY1,"); // of 4
  delay(10);
  // set the network id, choose a strange key
  // in this case 8 = lucky number in china
  Serial.print("ID8888,");
  delay(10);
  // set the api mode to 1
  // 0 = no rssi
  // 1 = rssi
  // 2 = rssi with escaping
  Serial.print("AP1,");
  delay(10);
  // set the rssi value
  // I think this is only usefull if you use the analog pin on the xbee itself to read the rssi ** after finishing this project i read something different about this, cant remember where **
  // see the xbee manual for more details
  Serial.print("RP40,");
  delay(10);
  // set the boudrate to 9600
  // this will give the highest speed with no data buffering on the xbee
  // see the xbee manual for more details
  Serial.print("BD3,");
  delay(10);
  // exit command mode
  Serial.print("CN");
  // wait for a while
//  delay(1200);
}

to receive a signal from other xbee's

void rxSignal(){
  //delay(5000);
  digitalWrite(rxPin,HIGH);
  int packetLength = checkHeader(100);
  // Serial.print("packetlength: ");
  // Serial.println(packetLength);
  // 0x81 == 129 == (u met een dakje)
  if (packetLength > 0 && getIdentifier(0x81)){
    byte addrMSB = Serial.read();
    byte addrLSB = Serial.read();
    int address = (addrMSB << 8) + addrLSB;
    byte RSSI = Serial.read();
    //Serial.print("RSSI: ");
    //Serial.println(RSSI,DEC);
    byte options = Serial.read();
    long startTime = millis();
    for (int i = 0; i < (packetLength - 5); i++){
      while(((millis() - startTime) < 500) && Serial.available() < 1);
      if(Serial.available() > 0){
        char dataIn = Serial.read();
        //int getal = (dataIn,HEX);
        // Serial.println(getal);
        // Serial.println(dataIn,HEX);
      }
    }
    byte checksum = Serial.read();
    
    
    handleSignal(address,RSSI);
    
  }
  else {
    // Serial.println("BAD IDENTIFIER");
    //txSignal();
    // resetLoop();
  }
  digitalWrite(rxPin,LOW);
}

the check header function to check if a received packet has a start bit (0x7E)

int checkHeader(int timeout){
  long startTime = millis();
  int length = 0;
  int inByte = 0;
  while (((millis() - startTime) < timeout) && (inByte != 0x7E)){
    if (Serial.available() > 0){
      inByte = Serial.read();
      //Serial.println(inByte);
    }
  }
  if (inByte == 0x7E){
    while (Serial.available() < 2);
    int lengthMSB = Serial.read();
    int lengthLSB = Serial.read();
    //Serial.print("msb: ");
    // Serial.println(lengthMSB);
    //Serial.print("lsb: ");
    //Serial.println(lengthLSB);
    //length = (lengthMSB << 8) + lengthLSB;
    delay(10); 
    length = lengthLSB;  
  }
  while ((millis() - startTime < timeout) && Serial.available() < length + 1 && Serial.available() < 20) // wait
  if (Serial.available() < length && Serial.available() < 20){
    length = -1;
  }
  return length;
}

function to see if the identifier is correct (dont know why anymore :slight_smile: see footnote)

boolean getIdentifier(byte wanted){
  long startTime = millis();
  byte apiIdentifier = 254;
  //Serial.print("wanted: ");
  //Serial.println(wanted);
  while (Serial.available() < 1 && (millis() - startTime) < 500){
    //  Serial.println("waiting");
  }
  if (Serial.available() > 0){
    apiIdentifier = Serial.read();
   // Serial.print("api ident: ");
   // Serial.println(apiIdentifier);
  }
  else {
    //Serial.println("no data");
  }
  if (apiIdentifier == wanted){
    return true;
  }
  else{
    return false;
  }
}

well, you can do whatever you want with the address and the rssi..

void handleSignal(int address, int rssi){}

well, it took me a while to figure out how to send and receive data without leaving API mode 1. First i tried switching between API 1 and API 0. That takes a lot of time so I had to figure out a way to send in API1 mode.
This is how I send (broadcast) a signal:

void txSignal(){
  digitalWrite(txPin,HIGH);
  Serial.flush();
  delay(100);
  Serial.print(0x7E,BYTE);
  Serial.print(0x00,BYTE);
  Serial.print(0x06,BYTE);
  Serial.print(0x01,BYTE);
  Serial.print(0x00,BYTE);
  Serial.print(0xFF,BYTE);
  Serial.print(0xFF,BYTE);
  Serial.print(0x01,BYTE);
  Serial.print(0x28,BYTE);
  Serial.print(0xD7,BYTE);
  Serial.flush();
  delay(20);
  digitalWrite(txPin,LOW);
  Serial.println(" ");
}

Well, with these functions as the base I got some more code to have the balls communicate in the right way. Like checking if 3 balls are received before sending and some reset if it takes to long before all the signals are received and a global reset if something strange fails or the arduino reboots. In my case a reboot happened picking the ball up from the loader because i had to switch the battery. After a switch a ball generally is back in the routine within a second.
I also used some code to make sure the 4 ball routine changed into a three or two ball routine in case of a 'fail' of one ball for a longer period. (When the ball is on a charger, it doesn't send)

I hope this is usefull, if there are more questions, just reply here.

cheers


I re-used some code, the checkheader and getIdentifier functions, but since I somehow erased my favourites I cant find it anymore. If you find your code here and feel in some way offended I did not mention your name or whatsoever, please dont be mad, just contact me.

Hello Jano!

You got mail :wink:

Hello,

I've read your email and you are asking me to post the remaining code for the routine with four balls and the battery charger and stuff.

Offcourse I am willing to help you, but, I've intentionally left some room there for your own interpretation and programming skills. I know my own code is not flawless and I am pretty sure there is a better way of doing it. I was kind of hoping you would find it out..

So, if you need any more specific help on anything I am really glad to help, but try something out yourself first :wink:

And how are things going with your blog?

Cheers,

Hello!

Sorry, I haven't checked out this thread in a few days.

The blog can be read at www.emoodies.wordpress.com.

We haven't got our components yet (our lab managers was a bit slow about ordering them) and are still stuck with compulsory design exercises, document writing, concept presentations and so on.

I was just trying to make up some time since I believed those routines could be of use.

We'll definitely try stuff on our own but no one in our group has worked with XBee modules before so I was just trying to gather as much usable information as possible since our main challenge probably will be to design the personalities of the eMoodies and their physical appearance.

I'll contact when we start working with the hardware if we are completely stuck or have come up with some interesting solutions.

:wink:

How do you guys go from reading the RSSI value to getting some sort of distance measurement from it?

My group and I just managed to set up a connection but we didn't see any difference in the value if we had our two XBees 3 or 15 meters apart. it varied between 4 and 54 (sort of).

We used muse207's way of getting the RSSI value.

Hello guys

I got two more emails with some questions about xbee and arduino.

thothef asking:
i understood from u that we can send data from on xbee api=0 to another xbee api=1
Well, I send data in API = 1 and receive it in API = 1. I remember while doing my project I had terrible trouble sending between api=0 and api=1, so you might not want to that..

thothef asking:
All modules operating within the same network should contain the same firmware version.
True, you can do this (on a pc) with for example: http://www.digi.com/support/kbase/kbaseresultdetl.jsp?kb=125 software

thothef asking:
my first qustion is how can i confirm the connection between one xbee in api=0 and other api=1 .
I dont know, I guess connect it to arduino and use some code to check if you receive anything :slight_smile:

thothef asking:
the important qustion is how to set the xbee sender & xbee receiver ,i ment about the parameter shoud be set.
none, the xbee is always sender and receiver. If you want to use it as a sender, just use the void txSignal(){} function I gave you above to send in API 1 mode.
If you want to use it only as a receiver, just use a loop where you keep waiting for data.

Danilo asking:
Please can you explain the meaning of
digitalWrite(txPin,HIGH);
and
digitalWrite(txPin,LOW);
these lines set the level of txpin on arduino, i know, but why these commands are so important for the code to
run fine?? I try to remove those lines and xbee don't send the correct api packet.
I tell you this because i'm trying to send at commands in api format from pc to an unchipped arduino board
via serial port and using X-CTU everything works fine but using java code for write byte on serial port
seem that XBEE module don't receive the command

Well, to be honest, I dont know (not without looking back into datasheets that is).
But, cant you use your java code to pull up the tx port before you send a byte out?

Assuming you have a Xbee connected to an arduino, receiving data wireless from your computer, maybe you can remove the Xbee and connect the RX of your arduino directly to the TX of your computer?
Probably you will have to connect your GND and V++ as well, but make sure that wont kill your arduino!
Doing this will give you the opportunity to check the data your java program is sending..

good luck!

For future questions, please just ask them here?
I know skogberg is really into this as well and more people are. If you ask your questions here the change that they will get a good (and fast) answer are a little bigger than when you email them to me.. :wink:

Thanks a lot Jarn0... I solved the problem. My pc didn't receive response from XBEE because I had to set up a correct timeout in java code to wait the responses on serial port. Now everything works fine!! I can do node discover from pc, I can send request to nodes for sensor data, and thanks to your txsignal() and rxsignal() now I implement static multi-hop routing using XBEE Series 1 module.
Thanks very much!!!

Sorry,just noticed the ASK THEM HERE part!!

I am trying to do the following.I want to have one arduino-xbee and one pc-xbee.I want to program the arduino-xbee to get the rssi from the pc-xbee and then send a message to the pc-xbee which contains the rssi.

I am having problem with the first part.In the thread I have seen that you have overcame this problem but I didnt understand how you managed it.Can you give me a few tips and the configuration settings(api-transparent mode?) in order to achieve that?And some code snippets would help!

Hi geek85! I worked on Arduino-xbee some months ago, now I'm working on another project but I can give you some explanations about what I can remember. So you must set Arduino-xbee and PC-xbee in API operation mode. Then you must use pc-xbee to send a packet with a generic payload (for example the character "A") to the arduino-xbee. Now you must study the structure of the frame that xbee chip send to microcontroller on Arduino when it receives the packet. The frame structure is on the manual of xbee. In this frame structure there are some fields that contain RSSI measurement. Once you have found the exact field in the frame you must extract RSSI and use it as you prefer. I hope I have been clear in my explanation!