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 = i xbee_req.payload = i + 1 xbee_send()
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.