Home/Support/Support Forum/How can I retrieve the analog sample sent by an xbee module in C code ?

How can I retrieve the analog sample sent by an xbee module in C code ?

0 votes
Hi,

I configured a xbee module to send samples (AD and GPIO) to a programmable coordinator, each second.

The destination endpoint is E8 and the cluster ID is 11 How do I use these informations to catch the analog value with help from the firmware lib?

I wrote a simple code to toggle a led each time the processor executes xbee_transparent_rx function but it never toggles... I seems to stay stucking in the main loop. I think that only interrupt can make the processor executing this function when it is doing the infinite loop, but there is nowhere I find a call for this function!

How can I enter this function when receiving samples from the other device? Is this function I have to enter in at all?

Thanks!
asked Jul 19, 2016 in XBee Programmable Development by herrmattoon New to the Community (10 points)

Please log in or register to answer this question.

2 Answers

0 votes
Hi,

Any idea? ...
answered Jul 20, 2016 by herrmattoon New to the Community (10 points)
0 votes
The xbee_transparent_rx function only receives frames of the "Receive Packet" type (0x90). To receive a "Data Sample Rx Indicator" frame (0x92, the one that your end device has been configured to send) you will need to create a custom routine. The easiest way to do this is to use the pre-existing function _xbee_frame_load(&xdev) which is called by xbee_dev_tick(&xdev) which is in turn called by sys_xbee_tick(). This function will poll the serial buffer for new frames. All you need to do is create a duplicate version of that function that will handle your own frames. Here is a copy of the function with comments at the spot where you will call your custom frame handler. Once you've made this function periodically call it in your program to receive frames.


/**
@internal
@brief
Check XBee's serial buffer for complete frames and pass them
off to the dispatcher.

Should only be called after \a xbee has been initialized by calling
xbee_dev_init(). Typically called by xbee_dev_tick().

@param[in] xbee XBee device to read from.

@retval 0 No new frames waiting.
@retval >0 Number of frames processed.
@retval <0 Error.

@see xbee_dev_init(), _xbee_frame_dispatch()
*/
_xbee_device_debug
int _xbee_frame_load( xbee_dev_t *xbee)
{
// Use xbee_serial API to load multiple bytes at a time.

// Based on state, do one of the following:

// 1) Waiting for start of frame:
// Scan through serial buffer until 0x7e byte is found.
// Advance to next state.

// 2) Waiting for length:
// Wait until 2 bytes in serial buffer, read into xbee->rx.bytes_in_frame.

// 3) Waiting for (<length> + 1) bytes of data:
// Read as many bytes as possible from the serial buffer and into the
// xbee->rx.frame_data[]. Once all bytes have been read, calculate and
// verify checksum and then hand off to dispatcher.

uint8_t ch;
uint16_t length;
int retval;
int bytes_left, read;
uint_fast8_t dispatched;
xbee_serial_t *serport;

if (xbee == NULL || xbee_ser_invalid( (serport = &xbee->serport) ))
{
#ifdef XBEE_DEVICE_VERBOSE
printf( "%s: return -EINVAL (xbee is %p)\n", __FUNCTION__, xbee);
#endif
return -EINVAL;
}

dispatched = 0; // counter to keep track of frames processed

for (;;)
{
switch (xbee->rx.state)
{
case XBEE_RX_STATE_WAITSTART: // waiting for initial 0x7E
/*
It may seem inefficient to read one byte at a time while looking
for the 0x7E start byte, but in reality we almost always read it
in on the first attempt (i.e., the buffer should be empty or will
start with 0x7E).
*/
do {
retval = xbee_ser_read( serport, &ch, 1);
if (retval != 1)
{
return dispatched;
}
} while (ch != 0x7E);
#ifdef XBEE_DEVICE_VERBOSE
printf( "%s: got start-of-frame\n", __FUNCTION__);
#endif
xbee->rx.state = XBEE_RX_STATE_LENGTH_MSB;
// fall through to next state

case XBEE_RX_STATE_LENGTH_MSB:
// try to read a character from the serial port
if (xbee_ser_read( serport, &ch, 1) == 0)
{
return dispatched;
}
if (ch == 0x7E)
{
// MSB of length can never be 0x7E, consider it to be the new
// start-of-frame character and recheck for the length.
#ifdef XBEE_DEVICE_VERBOSE
printf( "%s: ignoring duplicate start-of-frame (0x7E)\n",
__FUNCTION__);
#endif
break;
}
// set MSB of frame length
xbee->rx.bytes_in_frame = ch << 8;
xbee->rx.state = XBEE_RX_STATE_LENGTH_LSB;
// fall through to trying to read LSB of length
case XBEE_RX_STATE_LENGTH_LSB:
// try to read a character from the serial port
if (xbee_ser_read( serport, &ch, 1) == 0)
{
return dispatched;
}

// set LSB of frame length, make local copy for range check
length = (xbee->rx.bytes_in_frame += ch);
if (length > XBEE_MAX_FRAME_LEN || length < 2)
{
// this isn't a valid frame, go back to looking for start marker
#ifdef XBEE_DEVICE_VERBOSE
printf( "%s: read bad frame length (%u ! [2 .. %u])\n",
__FUNCTION__, length, XBEE_MAX_FRAME_LEN);
#endif
if (ch == 0x7E)
{
// Handle case of 0x7E 0xXX 0x7E where second 0x7E is actual
// start of frame.
xbee->rx.state = XBEE_RX_STATE_LENGTH_MSB;
}
else
{
xbee->rx.state = XBEE_RX_STATE_WAITSTART;
}
break;
}
#ifdef XBEE_DEVICE_VERBOSE
printf( "%s: got length %" PRIu16 "\n", __FUNCTION__, length);
#endif
xbee->rx.state = XBEE_RX_STATE_RXFRAME;
xbee->rx.bytes_read = 0;
// fall through to next state

case XBEE_RX_STATE_RXFRAME: // receiving frame & trailing checksum
bytes_left = xbee->rx.bytes_in_frame - xbee->rx.bytes_read + 1;
read = xbee_ser_read( serport,
xbee->rx.frame_data + xbee->rx.bytes_read, bytes_left);
if (read != bytes_left)
{
// Not enough bytes to finish reading current frame, record
// number of bytes read and return.
if (read > 0)
{
xbee->rx.bytes_read += read;
}
return dispatched;
}

// ready to load more frames on next pass
xbee->rx.state = XBEE_RX_STATE_WAITSTART;

if (_xbee_checksum( xbee->rx.frame_data,
xbee->rx.bytes_in_frame + 1, 0xFF))
{
// checksum failed, throw out the frame
#ifdef XBEE_DEVICE_VERBOSE
printf( "%s: checksum failed\n", __FUNCTION__);
hex_dump( xbee->rx.frame_data, xbee->rx.bytes_in_frame + 1,
HEX_DUMP_FLAG_OFFSET);
#endif

/* At this point, we *could* look through the frame data for
another start-of-frame (0x7E) marker, including considering
the LSB of the length field. We shouldn't have to though --
assuming a good serial connection, we should stay in sync
with XBee frames and not have to work too hard at resyncing.

Also, we only sync to a select range of 3-byte sequences --
0x7E followed by two-byte length of 0 to about 300.
*/

break;
}
else
{
// frame is ready for dispatch
++dispatched;
#ifdef XBEE_DEVICE_VERBOSE
printf( "%s: dispatch frame #%d\n", __FUNCTION__,
dispatched);
#endif

/*
* PLACE YOUR CUSTOM FRAME HANDLER HERE
* you can pull the custom frame data out of
*/ xbee ->rx.frame_data
//_xbee_frame_dispatch( xbee, //xbee->rx.frame_data,
xbee->rx.bytes_in_frame);

if (dispatched == XBEE_DEV_MAX_DISPATCH_PER_TICK)
{
return dispatched;
}
}
break;

default:
#ifdef XBEE_DEVICE_VERBOSE
printf( "%s: invalid state %d\n", __FUNCTION__,
xbee->rx.state);
#endif
xbee->rx.state = XBEE_RX_STATE_WAITSTART;
}
}
}
answered Jul 20, 2017 by robo1340 New to the Community (1 point)
...