Xbee PRO S3B in API mode, inconsistent communication.

Hello everyone,

I'm currently developing a system for rapidly exchanging information from a datalogger system (a MEGA with sensors) to an XBee Pro-900 S3B, receiving on another Xbee Pro-900 S3B. The receiver at this point can be either another MEGA or a laptop and XCTU. I have tried the TX/RX lines for this, and run into problems with flow control and the Xbee's locking up. Since the end-application will be in a place where manual resets are difficult, I would prefer to avoid that, and so am attempting to use both Xbees in API mode.

Some starting points:

  • I have checked that both 64-bit addresses are correct, and have verified that my test platform can send and receive small data packets successfully.
  • I have verifed (using the XCTU frames generator) that the data packets my MEGA is attempting to send to its Xbee are of the correct format, addresses, and checksum.

My test setup consists of:

PC -> usb -> MEGA -> Xbee1 -----> Xbee2 -> PC/XCTU

The MEGA is sending a 100 byte test packet with the appropriate header info and checksum, and then waits for a 'sucessful' transmit status from Xbee2 before proceeding with the next package of data.

My problem is that the larger data chunks going from Xbee1 to Xbee2 never show up in the XCTU console, and any frames sent from Xbee2 to Xbee1 will either:

  • Not be received at all
  • Get a "successful" status from Xbee1, but the ATTN pin on Xbee1 never triggers
  • Get a successful status from Xbee1 and trigger the ATTN pin on Xbee1

In the beginning of my receive program, I have a loop that looks for the start byte (0x7E) for 300 attempts before kicking out:

while ((val != 0x7E) && (kickOut <= 300)) { // Find the start byte
digitalWrite(SS_PIN, LOW); // if no start byte is found
//delay(1);
val = SPI.transfer(0); // within 300 tries, then abort
digitalWrite(SS_PIN, HIGH); // the while loop

#ifdef DEBUG
usb.println(val,HEX);
#endif

kickOut++;
}

The debug code catches all of the message, but misses the starting byte by just a few bits (there is always a value where the 7E should be, its just not 7E, like its being cut off. I have tried everything there to catch those front bits, but can't get it to work. Since I'm trying to stay quick and low memory, I would prefer to catch the 7E byte properly, as all of my packet parsing runs from that point. Any suggestions on that?

My 2nd problem is that, although my debug code prints the right package data frame from Xbee1 to Xbee2 (it has a correct address, correct length, correct checksum), I cannot get Xbee2 to notice it. If i load a previous sketch with the exact same header and checksum method with a smaller package, then it works just fine.

I've tried 2 different methods:

  • Separate uint_8 arrays that make up the whole packet (header, identifier, dataframe, checksum), open SPI bus, assert SS pin, run several for loops that transfer each array.
  • Lump all of the arrays into a single sendBuffer, open SPI bus, single for-loop that transfers each uint_8 element.

Neither seem to work, even if I drop the SPI clock to 500kHz (the xbee can supposedly handle 2.5MHz).
I've gotten mixed info on the xbee depending on what version it is.

  • Is there a maximum number of bytes the xbee can send at once in API mode?
  • Is there a maximum "flow rate" of data that I can push to the xbee in API mode, or is it handled by a limited package size or limited by the SPI frequency? Should I be worried about buffer overflow and lockup like I was using Serial to Xbee?
  • Are there any other potential pitfalls that I missed that cause similar problems?

Any help would be greatly appreciated.

    val = SPI.transfer(0);                                      // within 300 tries, then abort

What are you transferring the data to? Not the XBee, that's for sure.

       #ifdef DEBUG
      usb.println(val,HEX);
    #endif

What class is usb an instance of?

My understanding is that reading data from an SPI slave device goes like this:

uint8_t derp;

derp = SPI.transfer(0);

where a zero is "transferred" to the device, because it'll ignore anything that doesn't begin with a 0x7E, and will assign whatever is in the SPI receive register to the variable. Is that not the case here?

val = SPI.transfer(0);                                      // within 300 tries, then abort

my intent was to have the uint8_t val assigned the contents of the SPI receive register for each loop. The variable contents are used to drive a for-loop that continues looking for a 0x7E for 300 cycles.

#ifdef DEBUG
     usb.println(val,HEX);
#endif

My apologies, at the beginning of my code I #define Serial as usb...to save keystrokes and to help me keep up with the various serial outputs of the MEGA.

where a zero is "transferred" to the device

To what device? The XBee is NOT an SPI device. Unless you have some non-standard XBee, in which case you need to provide a link to it.

Once again, my apologies. I didn't realize that SPI was not a standard xbee interface. I've only worked with this type of xbee.

I'm using an Xbee Pro 900HP (S3B)

https://www.digi.com/products/embedded-systems/rf-modules/sub-1-ghz-modules/xbee-pro-900hp