0
\$\begingroup\$

Following the python-Xbee library and an example, I am trying to communicate between 2 XBees

Using XBee S2C Setup: Coordinator API=2, running the code in python @ Mac Router AT mode, running python code @ Mac

Below data sending code runs in API mode at coordinator

#!/usr/bin/python


#this code runs on the xbee coordinator that is set to API mode 2

import serial
from xbee import ZigBee
from xbee.helpers.dispatch import Dispatch
import time

PORT = '/dev/tty.usbserial-A104IC2U'
BAUD_RATE = 9600

UNKNOWN = '\xff\xfe' 
WHERE = '\x00\x13\xA2\x00\x40\xF7\x0A\x50'
dataString='Hello\n'

# Open serial port
ser = serial.Serial(PORT, BAUD_RATE)

zb = ZigBee(ser)

#sends data to xbee address
def sendData(address, datatosend):
    zb.send('tx', dest_addr_long = address, dest_addr = UNKNOWN, data = datatosend)


#test data sending method
while True:
    try:
        sendData(WHERE, dataString)
    except KeyboardInterrupt:
        break


zb.halt()
ser.close()

And in the router (AT mode) I run below code

#!/usr/bin/python

import serial

#router port
PORT = '/dev/tty.usbserial-A104IAUX'
BAUD_RATE = 9600
ser = serial.Serial(PORT, BAUD_RATE)

#myaddress - its the router
ack='0013A20040F70A50'

while True:
    incoming = ser.readline().strip()
    if incoming != '0013A20040F70A50':
        print '%s' % incoming
        ser.write('%s' % ack)

ser.close()

This works fine and I see the output 'Hello' on the router side python terminal at Mac. Now I also need to receive data in the coordinator side. So I do this in the coordinator code - after sending, it also reads the serial and prints data

while True:
    try:
        sendData(WHERE, dataString)
        incoming = ser.readline().strip() #added to receive serial data at coordinator
        print '%s' % incoming
    except KeyboardInterrupt:
        break

But as soon as I add those two lines, the communication stops. Is this because coordinator is in API mode and can't receive in serial? And I have to write the receive code for API mode? Any suggestion?

\$\endgroup\$
1
\$\begingroup\$

It could be because read() and readline() are blocking methods, when no timeout is set. Initialize the serial instance like this:

ser = serial.Serial(PORT, BAUD_RATE, timeout=1)

for a 1-second timeout. This means any read() calls will wait for 1 second max before returning with whatever has been read so far. You seem to be writing '0013A20040F70A50' to the coordinator, which contains no newline characters; since your read() is blocking, I expect your program will wait till a newline comes in through the serial port (which never happens) before returning. From the pyserial docs:

Be careful when using readline(). Do specify a timeout when opening the serial port otherwise it could block forever if no newline character is received.

So you should either add a timeout like I already explained, or you continue with your blocking mode but ensure you add a new line character to whatever you send to the coordinator. In the first case, you risk reading nothing at all, since you arent even checking if anything has arrived, before reading. You can fix this with:

while not ser.inWaiting():
    pass
incoming = ser.readline()

This will wait till the first character comes in and then attempt to read a line, within 1 second i.e. the timeout value. This can be problematic if your entire line is so long that it doesnt arrive within a second. You can try interCharTimeout instead; it's one of the properties of a serial object.

ser = serial.Serial(PORT, BAUD_RATE, interCharTimeout=0.5)

This should set the maximum allowed time between received bytes to 500ms; if it exceeds this, the read() or readline() will return. I havent tried this before though, just something I've seen in the docs.

Of course, you could just leave everything in blocking mode as is, and simply ensure that you always send a newline character with your packets.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.