building xbee network: part 2

On June 17, 2012 by sebastien.lelong

During last part we’ve seen how to setup XBee API mode on both coordinator and router. We’ve also written two simple python programs used to test communication between modules, one sending information, another displaying what it receives. No specific hardware part involved except USB-to-serial modules.

In this second part, we’ll replace the sending python program with a Jaluino Bee board, involving usage of jalvé Xbee API library (Jaluino-Xbee => PC-Xbee). We’ll then switch the role: Jaluino will receive data (Jaluino-Xbee <= PC-XBee).

Sending data using Jaluino-XBee

Starting from previous tutorial part, keep the receiving python program setup. We’ll use a Jaluino board to send data. First update your SVN repository to get last sources, including a Jalv2 XBee API library and several samples.

We’ll use the sending (TX) sample. Using XBee module requires a serial carrier, we’ll use the first module available on Jaluino board. Default XBee baudrate is 9600.

const serial_hw_baudrate = 9_600
include serial_hardware
serial_hw_init()

So, XBee module is plugged on Jaluino board, thus connected to this serial module (though on Jaluino Bee v2.1 board, there’s a solder jumper you can use to route XBee module to the second serial module). We can now setup XBee library.

alias xbee_carrier is serial_hw_data
const byte XBEE_PAYLOAD_SIZE = 2
include xbee_api
xbee_init()

We declare what will be carrier using an alias directly pointing to the first serial module. We then declare the payload size, that is, the size of data we’re going to send through XBee. Well, we plan to send “AB”, so that’s size 2. There’s a limitation here: payload can’t be more than 100 bytes. This is due to the total frame size Xbee can handle. If you plan to send or receive more than 100 bytes, you’ll have to reconsider your communication protocal by introducing a splitting mode or something like that.

We can now start to forge a XBee request, containing the data we want to send. In my setup, XBee module we’re trying to talk to will be the Coordinator (connected to a PC through USB-to-serial). We declare a xbee_address64 record and fill in the form…

-- define which XBee will receive the message
-- Dest. Xbee is connected to my PC, it's a coordinator
-- with firmware API AP=2. According to X-CTU tool:
-- SH: 13A200
-- SL: 40301109
-- 16bits address: 0
var xbee_address64 xbee_dest
xbee_dest.msb = 0x0013a200
xbee_dest.lsb = 0x40301109
var word xbee_net = 0xfffe

Gathering address information from X-CTU tool, SH (high) goes to MSB field, and SL (low) goes to lsb. (I’m still not sure 0xfffe is, according to some it’s a 16bits address, others says it’s a broadcast address and net address…it seems to be a constant. I’ve never been able to use it to address a XBee, I also think this is related to XBee module version).

XBee API library declares two imporant global variable: xbee_req ad xbee_res. These are request and response records. In our case we’ll fill xbee_req fields accordingly:

xbee_req.addr64 = xbee_dest
xbee_req.network = xbee_net
xbee_req.api_id = XBEE_ZB_TX_REQUEST
xbee_req.frame_id = 1
-- also set the following, else it's working
-- when PIC gets prog'd, not after a power down/up
xbee_req.broadcast_radius = 0
xbee_req.option = 0

Request will go the Coordinator, so addr64 is set to our record. api_id is typed as XBEE_ZB_TX_REQUEST using XBee series 2 modules. And again, there are still several obscure information, which I still couldn’t enlight, particularly broadcast_radius and option field, which have to be set like this (empirically speaking).

Since we’re always talking to the same XBee, these are constant information. Only the payload will now change. In a loop, we’re increasing values, set payload and send the request:

for 120 using i loop
      -- prepare payload
      xbee_req.payload[0] = i
      xbee_req.payload[1] = i + 1

      xbee_send()
end loop

Program this (you can get the tested HEX file, compiled to be run with PDFUSB bootloader), and now run the receive_samples.py sample on a console.you should get the following output on receiving python program:

See rf_data ? This is our incrementing payload… Congratulations, this is working fine.

Receiving data using Jaluino-XBee

Now let’s try on the receiving part. Sample is even simpler, there’s no address to declare since we’re now receiving data. The main part is:

   xbee_read_packet()

When calling this procedure, data will be read from serial (blocking call) and the other special global variable, xbee_res, will be set with several information. Let’s look at xbee_res declaration to better understand this:

-- Related to: XBee response
record xbee_response is
   byte api_id
   byte frame_id
   byte frame_data[XBEE_MAX_FRAME_DATA_SIZE]
   byte msb_length
   byte lsb_length
   byte checksum
   byte frame_length
   bit  complete
   byte error_code
   --
   byte payload_idx
end record

All these fields will be set, particularly frame_data containing, well, frame data… Frame can be decomposed into the 64bits source address, network and option fields, then the payload. To directly access payload information, we can use the pseudo-variable xbee_res_payload’get(), using the following construction (here, every byte read from XBee response’s payload is printed through 2nd serial):

   for XBEE_PAYLOAD_SIZE loop
       serial_hw2_data = xbee_res_payload
   end loop

If you’d want to specifically reply to the sending XBee, you can also access source address through frame_data fields (first 8 bytes).

To test this sample, now run the send_samples.py program on PC side. You should get the following output on PIC side:

In frame_data you’ll find the source address (0x0013A20040301109), and the last two byte, 41 or 42, corresponding to ASCII for “A” and “B”. payload field directly shows this. Another interesting field is error_code you could check to make sure response parsing went well (0 means ok, refer to xbee_api library for more).

Comments welcome on Jaluino forums.


Comments are closed.