Go Down

Topic: How to measure XBee signal strength? (Read 30376 times) previous topic - next topic

Khamey

I have looked for about a week now and can't figure out how to get any form of signal strength indication. I basically need to press a button from one Arduino and return the signal strength in any useable fashion so that I can map it to 3 LEDs. Good, average, and poor. I have tried the pulseIn function along with sending AT commands. I can't find a straight forward guide on how to get API mode working to pull the RSSI value from that packet strand. I am using two XBee Pro S2B. Any help on how to do this would be greatly appreciated.

oric_dan

Did you see this section in the datasheet?
Quote
RSSI Indicators
It is possible to measure the received signal strength on a device using the DB command.
DB returns the RSSI value (measured in -dBm) of the last received packet. However, this
number can be misleading. The DB value only indicates the received signal strength of the
last hop. If a transmission spans multiple hops, the DB value provides no indication of the
overall transmission path, or the quality of the worst link - it only indicates the quality of
the last link and should be used sparingly.

On the S1 modules, you just send
Code: [Select]
+++
ATDB

and it sends back the RSSI value.

JChristensen


On the S1 modules, you just send
Code: [Select]
+++
ATDB

and it sends back the RSSI value.


Ditto for the S2 modules. Also works in API mode of course.

Khamey

#3
Feb 27, 2013, 04:16 pm Last Edit: Feb 27, 2013, 05:38 pm by Khamey Reason: 1
How does this work? I can do this easily in the X-CTU terminal. I type +++ and it replies OK then I type ATDB, hit enter, and it replies with a hex number. This is not happening in the Arduino terminal. Am I allowed to put this in the loop section of the the code? I don't mind doing it this way, but I can't get any code to work trying to enter the +++ mode.

Edit: To be clear, I open the serial monitor of the Arduino and in the top line type +++ and hit send and I get no response no matter what I do. In fact it sends over to the other terminal on XCTU.

JChristensen


How does this work? I can do this easily in the X-CTU terminal. I type +++ and it replies OK then I type ATDB, hit enter, and it replies with a hex number. This is not happening in the Arduino terminal. Am I allowed to put this in the loop section of the the code? I don't mind doing it this way, but I can't get any code to work trying to enter the +++ mode.

Edit: To be clear, I open the serial monitor of the Arduino and in the top line type +++ and hit send and I get no response no matter what I do. In fact it sends over to the other terminal on XCTU.


How are things connected? Are the XBee and Arduino both connected? If so, there's an issue. Serial comm is a two-device arrangement, not three (PC, Arduino, XBee). Probably the TX signals from both the PC and the XBee are connected to the Arduino's RX pin, and the Arduino's TX pin is connected to both the PC's RX and the XBee's RX. So typing on the serial monitor will go to the XBee's TX pin, where it will not see it.

Khamey

That made a lot of sense what you pointed out. Basically at some button press I want to be able to send a packet, get a ping back, and then display the signal strength of that ping. I have the XBee connected to pins 2 and 3 of the Arduino through software serial. What you're saying is that when I type +++ into the serial monitor of the arduino that goes into my char variable straight to the Tx pin and the Rx pin is the on that needs to see it?

JChristensen


That made a lot of sense what you pointed out. Basically at some button press I want to be able to send a packet, get a ping back, and then display the signal strength of that ping. I have the XBee connected to pins 2 and 3 of the Arduino through software serial. What you're saying is that when I type +++ into the serial monitor of the arduino that goes into my char variable straight to the Tx pin and the Rx pin is the on that needs to see it?


Well if the XBee is on 2 and 3, the hardware serial interface is pins 0 and 1, this is what the serial monitor connects to. So with that arrangement, the XBee isn't even in the picture. Characters entered via the serial monitor are presented on the Arduino's pin 0. When the Arduino transmits to the serial monitor, it does so on pin 1.

Here is an API-mode function I use to get the RSS. The XBee is connected to the hardware serial interface. I've truncated the two switch statements in loop() to the bare minimum, it compiles but will need to be fleshed out for your particular application. I know that the latest version of the XBee library allows use of software serial, but I have not tried this, I've always used the hardware serial interface.

Code: [Select]
#include <XBee.h>                  //http://code.google.com/p/xbee-arduino/
#include <Streaming.h>             //http://arduiniana.org/libraries/streaming/

//XBee variables
XBee xbee = XBee();                //XBee object
ZBRxResponse rx = ZBRxResponse();  //XBee receive response

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

void loop(void)
{
    xbee.readPacket();

    if (xbee.getResponse().isAvailable()) {

        switch (xbee.getResponse().getApiId()) {           //what kind of packet did we get?
   
        case ZB_RX_RESPONSE:                               //rx data packet
            xbee.getResponse().getZBRxResponse(rx);        //get the received data
            switch (rx.getOption()) {
            case ZB_PACKET_ACKNOWLEDGED:
                Serial << "Packet received, RSS = -" << _DEC(rss()) << " DB" << endl;
                break;
            }
        }
    }
}

/*-----------------------------------------------------------------------*
* returns received signal strength value for the last RF data packet.   *
*-----------------------------------------------------------------------*/
uint8_t rss() {

    uint8_t atCmd[] = {'D', 'B'}, respLen, *resp, dBm;
    AtCommandRequest atCmdReq;
    AtCommandResponse atResp;

    atCmdReq = AtCommandRequest(atCmd);

    xbee.send(atCmdReq);
    if (xbee.readPacket(10)) {
        if (xbee.getResponse().getApiId() == AT_COMMAND_RESPONSE) {
            xbee.getResponse().getAtCommandResponse(atResp);
            if (atResp.isOk()) {
                respLen = atResp.getValueLength();
                if (respLen == 1) {
                    resp = atResp.getValue();
                    dBm = resp[0];
                    return dBm;
                }
                else {
                    Serial << "RSS LEN ERR" << endl;    //unexpected length
                }
            }
            else {
                Serial << "RSS ERR" << endl;            //status not ok
            }
        }
        else {
            Serial << "RSS UNEXP RESP" << endl;         //expecting AT_COMMAND_RESPONSE, got something else
        }
    }
    else {
        Serial << "RSS NO RESP" << endl;                //timed out
    }
}

Khamey

#7
Feb 27, 2013, 06:13 pm Last Edit: Feb 27, 2013, 06:18 pm by Khamey Reason: 1
I appreciate the thoughtful response, but I am not in API mode currently. This is something I will look into eventually but AT has been the easiest for me to set up and get a functioning program. The way I see it, is getting API to a working state is at least another 20 hours of work on my end to get to the same point I am at now. Really all I want to do is press a button, notice the button is pressed, send the XBee into command mode, send ATDB through the Arduino and then get that hex number. I will look into your API comments when I have more time. Is there anyone who has experience reading the RSSI value as a PWM?

Edit: Jack if you have some or know of easy to follow API mode tutorials for XBee Pro S2B I would gladly take a look at them. It seems that the information is just really hard to find and took me about 20 hours to get the two connected basically by tinkering and finding bits and pieces around the internet.

JChristensen

#8
Feb 27, 2013, 07:11 pm Last Edit: Feb 27, 2013, 07:15 pm by Jack Christensen Reason: 1
There are good API examples that come with the XBee library. I won't kid you, there is a learning curve, but it looks the worst from the foot of the hill and it pays off big time once you're up and through it. Start simple and slow. Seriously the examples are good. Just send "Hello world" or whatever. Be sure to get the doc files for the library. The library is extensive, there is an object model to learn. That's how I learned though, mostly from the examples that come with the library and a fair amount of time in the doc files, which I continue to refer to. Oh and don't forget the XBee product manual, I always have that near.

I'm the first to admit that I am a huge API-mode bigot, but once you're there, AT mode just seems super clunky. Having to send +++ then wait etc. etc. seems sooo inefficient. Being able to just code the destination address into a packet and send it is indispensable for multi-node networks. With AT mode, it would again require getting into command mode, changing the DH and DL parameters, etc. etc. Ugh!

I've used pulseIn() to measure the PWM signal, and it works, but again it seems like the hard way to do it. Have to dedicate an MCU pin and so forth. Seems much more straightforward to just ask the XBee and have it respond with the number!

OK I'm on a roll now. Sorry about that. Have fun, good luck!

oric_dan


How does this work? I can do this easily in the X-CTU terminal. I type +++ and it replies OK then I type ATDB, hit enter, and it replies with a hex number. This is not happening in the Arduino terminal. Am I allowed to put this in the loop section of the the code? I don't mind doing it this way, but I can't get any code to work trying to enter the +++ mode.

Edit: To be clear, I open the serial monitor of the Arduino and in the top line type +++ and hit send and I get no response no matter what I do. In fact it sends over to the other terminal on XCTU.


I **never** use the Arduino IDE Serial Monitor for most RS232 tasks, because you have to
press Enter before it sends the data from the keyboard. However, every other Terminal
Emulator should work with direct comms to the XBee modules. Certainly XCTU will.

oric_dan


That made a lot of sense what you pointed out. Basically at some button press I want to be able to send a packet, get a ping back, and then display the signal strength of that ping. I have the XBee connected to pins 2 and 3 of the Arduino through software serial. What you're saying is that when I type +++ into the serial monitor of the arduino that goes into my char variable straight to the Tx pin and the Rx pin is the on that needs to see it?

This is another problem that I've mentioned on 4 or 5 threads in the just the past week or so.
Basically trying to use an XBee shield on a UNO or other board with only 1 h.w. UART and
SoftSerial is about as easy as eating worms. I've never had any luck at all using SoftSerial, and
almost all of the avialable XBee shields have major issues with very poor design. Maybe Jack's
suggestions will work, but just getting past the h.w. setup issue is a big PITN.

Khamey

I have a working program and hardware for my XBee Pro S2Bs using one connected through USB explorer operating the X-CTU terminal and one connected to an Arduino UNO running a loop. I can send and receive data fine from both the laptop and the Arduino. Basically the last goal I have is to get some sort of RSS. It is literally the last thing I need to do. I don't disagree API is better and much more elegant, but it seems much more difficult and I am in a little bit of a time constraint. I really wish I had series 1 seeing as all I wanted to do was point to point. Setting up point to point with the supplies available was hard enough and I'm just trying to put the last piece of the puzzle in. It doesn't have to be elegant and it doesn't need to be flawless this is just a proof of concept that I will have time later to  refine where I will learn API mode and change all the code to that.

Jack do you remember how you did the pusleIn to get the pulse from the RSSI pin? It seems like its only on or off for me and it only returns 0's in the serial monitor. There is one line of code on log.linmena something like that that has zero details. I need to know which pin to hook into what variables to declare. Seriously tried everything I know and I don't get anything other than zeroes. Maybe I could be implementing my code wrong?


oric_dan

Quote
one connected to an Arduino UNO running a loop.

This makes it a lot easier, if you're not trying to do s.w. dev and XBee comms
simultaneously. Hopefully, your shield has 5V-to-3.3V level-shifters.

I've worked with XBees for 8 or 9 years now, and never needed to use the API,
and only ever used the AT commands.

All you have to do is, inside your loop, once a message is received from the host
node, rather than replying immediately, simply send +++ and ATDB out the serial
port and the XBee will interpret this as a command and reply with the RSSI signal.
Then read it using Serial.available() and Serial.read(), and transmit the data to the
host. Simple. Make sure the host delays a bit to give the remote time to do the op.

JChristensen


Jack do you remember how you did the pusleIn to get the pulse from the RSSI pin?


It was this simple. Note this was a S1 XBee, check the S2 product manual, the PWM period is different IIRC:

Code: [Select]
#define RSSI_PIN 2 //connect to the XBee RSSI pin
#define PWM_PERIOD 64 //XBee RSSI PWM period in ┬Ás per the XBee 802.15.4 Product Manual
unsigned long pulseWidth; //the XBee RSSI pulse width reading from pulseIn
pulseWidth = pulseIn(RSSI_PIN, LOW, PWM_PERIOD); //read the rssi pulse width, give up after 64ms

JChristensen


This is another problem that I've mentioned on 4 or 5 threads in the just the past week or so.
Basically trying to use an XBee shield on a UNO or other board with only 1 h.w. UART and
SoftSerial is about as easy as eating worms. I've never had any luck at all using SoftSerial, and
almost all of the avialable XBee shields have major issues with very poor design. Maybe Jack's
suggestions will work, but just getting past the h.w. setup issue is a big PITN.


I haven't tried an XBee shield, but we do seem to see our share of issues with them here on the forum.

For prototyping, AFI's adapter boards work great for me, just plugged into a breadboard. Hook up power, ground, RX and TX and it's good. To upload a new sketch, I pull the jumper from the XBee to the Arduino RX pin. On custom boards, I implement the same concept with a three-pin header and a shorting block. Like I said, this is all just using HW serial.

Go Up