Shop OBEX P1 Docs P2 Docs Learn Events
Problem with XBee communications stalling after a while — Parallax Forums

Problem with XBee communications stalling after a while

JChrisJChris Posts: 58
edited 2014-10-22 06:49 in General Discussion
Hello,

I have an issue with the Xbee communication.
I exchange data between 2 Xbees in API mode that are connected to propeller boards (C3 boards) but I don't understand why the communication stops after a while.
For testing purpose I am running a repeat loop on both sender and receiver sides. So both propellers are sending and receiving simultaneously.
The protocol that I use for XBee is DigiMesh.

If anyone has a hint I would appreciate


My code is below:

CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000


XB_Rx = 0
XB_Tx = 1
XB_Baud = 9600


TX_PIN = 2
BAUD = 19_200






VAR

Byte dataSet[120],_RxData[105], DigOffset, Inputbyte, Stringptr[200], mot[105]
Long _SrcAddr16, _RxLen, _RxValue, MY_Addr,stack[200], _srcAddr64_upper, _srcAddr64_lower
Byte _RxFlag,_RxIdent, _RSSIDec, _RxOpt, _RxFrameID, _RxCmd[3], _Status, _FrameID, _API_Ready, _RSSI, _RxOptions
Byte dataIn[255], PacketOut[105], PacketPtr
long _RxADC[6], _RxDig, _RxBit[8], _Temp2
Byte srcAddy[8]
''Bytes needed for TxStatus packet
Byte _RxRetries,_RxDeliveryStatus,_RxDiscoveryStatus
''Bytes needed for normal Rx
Byte _RxChkSum


OBJ


XB : "FullDuplexSerial"
pst : "Parallax Serial Terminal"
ASCI


Pub main | ptr,a


pst.Start(115200)
XB.start(XB_Rx, XB_Tx, 0, XB_Baud)


mot[0]:= "d"
mot[1]:= "a"
mot[2]:= "m"
mot[3]:= "i"
mot[4]:= "e"
mot[5]:= "n"
mot[6]:= 0


Stringptr[0] := "d"
Stringptr[1] := "a"
Stringptr[2] := "m"
Stringptr[3] := "i"
Stringptr[4] := "e"
Stringptr[5] := "n"
Stringptr[6] := 0


repeat

XB.RxFlush
API_str($00000000, $0000FFFF, @stringptr)
pst.str(string("String Sent!"))

API_Rx
waitcnt(clkfreq*2+cnt)
API_Query(String("DB"))
pst.str(string("receive debut!"))


API_Rx
pst.Str(String(pst#NL, "RxIdent est:"))
pst.Hex(_RxIdent,2)


pst.Str(String(pst#NL,"le RSSI est", pst#NL))
pst.Dec(_RxValue)

if(stringCompareCS(@_RxData,@mot) == 0)

API_Str(_srcAddr64_upper, _srcAddr64_lower, @Stringptr)
waitcnt(clkfreq+cnt)
API_Rx
waitcnt(clkfreq+cnt)
API_Query(String("DB"))
coucou := dataIn
pst.Dec(coucou)
else
pst.str(string(pst#NL, "La comparaison n'est pas bonne", pst#NL))
waitcnt(clkfreq+cnt)






Pub API_Query (cmd)| Length, chars, csum
{{
Sends AT command in API mode to query a parameter value.
Should also be used to set network identifier.
Data is returned as an AT response as a string.
XB.API_Query(string("DL")) ' Query
XB.API_Rx ' accept response
myDL := XB.RxValue ' Get returned value
}}
dataSet[0] := $7E
Length := 4 ' API Ident + FrameID + AT cmd
dataSet[1] := Length >> 8 ' MSB
dataSet[2] := Length ' LSB
dataSet[3] := $08 ' API Ident for AT Command (non queue)
dataSet[4] := $01 ' Frame ID
dataSet[5] := byte[cmd]
dataSet[6] := byte[cmd + 1]
csum := $FF ' Calculate checksum
Repeat chars from 3 to 6
csum := csum - dataSet[chars]
dataSet[7] := csum
Repeat chars from 0 to 7 ' Send data
XB.tx(dataSet[chars])




Pub API_Str(addy64_upper, addy64_lower,donnee)| Length, chars, csum,ptr, stptr, i
{{
Transmit a string to a unit using API mode - 16 bit addressing
XB.API_Str(2,string("Hello number 2")) ' Send data to address 2
TX response of acknowledgement will be returned if FrameID not 0
XB.API_RX
If XB.Status == 0 '0 = Acc, 1 = No Ack


}}
' pst.Str(String(pst#NL))
' pst.str(donnee)
' i := 0
' pst.Str(String(pst#NL))
' Repeat (strsize(donnee))
' pst.Hex(donnee[i++],4)






ptr := 0
stptr := 0
dataSet[ptr++] := $7E
Length := strsize(donnee) + 14 ' API Ident + FrameID + API TX cmd +
' AddrHigh + AddrLow + Options
dataSet[ptr++] := Length >> 8 ' Length MSB
dataSet[ptr++] := Length ' Length LSB
dataSet[ptr++] := $10 ' API Ident for 16-bit TX
dataSet[ptr++] := $00 ' Frame ID
dataSet[ptr++] := addy64_upper >>24
dataSet[ptr++] := addy64_upper >>16
dataSet[ptr++] := addy64_upper >>8
dataSet[ptr++] := addy64_upper
dataSet[ptr++] := addy64_lower >>24
dataSet[ptr++] := addy64_lower >>16
dataSet[ptr++] := addy64_lower >>8
dataSet[ptr++] := addy64_lower
dataSet[ptr++] := $FF
dataSet[ptr++] := $FE
dataSet[ptr++] := $00
dataSet[ptr++] := $00 ' Options '$01 = disable ack,
' $04 = Broadcast PAN ID
Repeat strsize(donnee) ' Add string to packet
dataSet[ptr++] := byte[donnee++]
csum := $FF ' Calculate checksum
Repeat chars from 3 to ptr-1
csum := csum - dataSet[chars]
dataSet[ptr] := csum


i := 0
pst.Str(String(pst#NL))
Repeat ptr+1
pst.Hex(dataset[i++],2)
' pst.Str(String(pst#NL))
' pst.Str(String(dataSet[i++],pst#NL))


pst.Str(String(pst#NL))


Repeat chars from 0 to ptr
XB.tx(dataSet[chars]) ' Send bytes to XBee
pst.Str(String("message envoy

Comments

  • PublisonPublison Posts: 12,366
    edited 2014-09-29 13:29
    Looks like your trying to post some code.

    attachment.php?attachmentid=78421&d=1297987572


  • JChrisJChris Posts: 58
    edited 2014-09-29 15:04
    Hello,

    I have an issue with the Xbee communication.
    I exchange data between 2 Xbees in API mode that are connected to propeller boards (C3 boards) but I don't understand why the communication stops after a while.
    For testing purpose I am running a repeat loop on both sender and receiver sides. So both propellers are sending and receiving simultaneously.
    The protocol that I use for XBee is DigiMesh.

    If anyone has a hint I would appreciate


    My code is below:

    [code]
    CON
    _clkmode = xtal1 + pll16x
    _xinfreq = 5_000_000


    XB_Rx = 0
    XB_Tx = 1
    XB_Baud = 9600

    TX_PIN = 2
    BAUD = 19_200



    VAR
    Byte dataSet[120],_RxData[105], DigOffset, Inputbyte, Stringptr[200], mot[105]
    Long _SrcAddr16, _RxLen, _RxValue, MY_Addr,stack[200], _srcAddr64_upper, _srcAddr64_lower
    Byte _RxFlag,_RxIdent, _RSSIDec, _RxOpt, _RxFrameID, _RxCmd[3], _Status, _FrameID, _API_Ready, _RSSI, _RxOptions
    Byte dataIn[255], PacketOut[105], PacketPtr
    long _RxADC[6], _RxDig, _RxBit[8], _Temp2
    Byte srcAddy[8]
    ''Bytes needed for TxStatus packet
    Byte _RxRetries,_RxDeliveryStatus,_RxDiscoveryStatus
    ''Bytes needed for normal Rx
    Byte _RxChkSum

    OBJ


    XB : "FullDuplexSerial"
    pst : "Parallax Serial Terminal"


    Pub main | ptr,a

    pst.Start(115200)
    XB.start(XB_Rx, XB_Tx, 0, XB_Baud)

    mot[0]:= "d"
    mot[1]:= "a"
    mot[2]:= "m"
    mot[3]:= "i"
    mot[4]:= "e"
    mot[5]:= "n"
    mot[6]:= 0

    Stringptr[0] := "d"
    Stringptr[1] := "a"
    Stringptr[2] := "m"
    Stringptr[3] := "i"
    Stringptr[4] := "e"
    Stringptr[5] := "n"
    Stringptr[6] := 0


    repeat

    XB.RxFlush
    API_str($00000000, $0000FFFF, @stringptr)
    pst.str(string("String Sent!"))

    API_Rx
    waitcnt(clkfreq*2+cnt)
    API_Query(String("DB"))
    API_Rx
    pst.Str(String(pst#NL, "RxIdent est:"))
    pst.Hex(_RxIdent,2)
    pst.Str(String(pst#NL,"le RSSI est", pst#NL))
    pst.Dec(_RxValue)


    if(stringCompareCS(@_RxData,@mot) == 0)


    API_Str(_srcAddr64_upper, _srcAddr64_lower, @Stringptr)
    waitcnt(clkfreq+cnt)
    API_Rx

    else
    pst.str(string(pst#NL, "La comparaison n'est pas bonne", pst#NL))
    waitcnt(clkfreq+cnt)



    Pub API_Query (cmd)| Length, chars, csum
    {{
    Sends AT command in API mode to query a parameter value.
    Should also be used to set network identifier.
    Data is returned as an AT response as a string.
    XB.API_Query(string("DL")) ' Query
    XB.API_Rx ' accept response
    myDL := XB.RxValue ' Get returned value
    }}
    dataSet[0] := $7E
    Length := 4 ' API Ident + FrameID + AT cmd
    dataSet[1] := Length >> 8 ' MSB
    dataSet[2] := Length ' LSB
    dataSet[3] := $08 ' API Ident for AT Command (non queue)
    dataSet[4] := $01 ' Frame ID
    dataSet[5] := byte[cmd]
    dataSet[6] := byte[cmd + 1]
    csum := $FF ' Calculate checksum
    Repeat chars from 3 to 6
    csum := csum - dataSet[chars]
    dataSet[7] := csum
    Repeat chars from 0 to 7 ' Send data
    XB.tx(dataSet[chars])

    pst.Str(pst#NL)
    pst.Dec(dataSet[5])
    pst.Dec(dataSet[6])


    Pub API_Str(addy64_upper, addy64_lower,donnee)| Length, chars, csum,ptr, stptr, i
    {{
    Transmit a string to a unit using API mode - 16 bit addressing
    XB.API_Str(2,string("Hello number 2")) ' Send data to address 2
    TX response of acknowledgement will be returned if FrameID not 0
    XB.API_RX
    If XB.Status == 0 '0 = Acc, 1 = No Ack

    }}
    ' pst.Str(String(pst#NL))
    ' pst.str(donnee)
    ' i := 0
    ' pst.Str(String(pst#NL))
    ' Repeat (strsize(donnee))
    ' pst.Hex(donnee[i++],4)



    ptr := 0
    stptr := 0
    dataSet[ptr++] := $7E
    Length := strsize(donnee) + 14 ' API Ident + FrameID + API TX cmd +
    ' AddrHigh + AddrLow + Options
    dataSet[ptr++] := Length >> 8 ' Length MSB
    dataSet[ptr++] := Length ' Length LSB
    dataSet[ptr++] := $10 ' API Ident for 16-bit TX
    dataSet[ptr++] := $00 ' Frame ID
    dataSet[ptr++] := addy64_upper >>24
    dataSet[ptr++] := addy64_upper >>16
    dataSet[ptr++] := addy64_upper >>8
    dataSet[ptr++] := addy64_upper
    dataSet[ptr++] := addy64_lower >>24
    dataSet[ptr++] := addy64_lower >>16
    dataSet[ptr++] := addy64_lower >>8
    dataSet[ptr++] := addy64_lower
    dataSet[ptr++] := $FF
    dataSet[ptr++] := $FE
    dataSet[ptr++] := $00
    dataSet[ptr++] := $00 ' Options '$01 = disable ack,
    ' $04 = Broadcast PAN ID
    Repeat strsize(donnee) ' Add string to packet
    dataSet[ptr++] := byte[donnee++]
    csum := $FF ' Calculate checksum
    Repeat chars from 3 to ptr-1
    csum := csum - dataSet[chars]
    dataSet[ptr] := csum

    i := 0
    pst.Str(String(pst#NL))
    Repeat ptr+1
    pst.Hex(dataset[i++],2)
    ' pst.Str(String(pst#NL))
    ' pst.Str(String(dataSet[i++],pst#NL))

    pst.Str(String(pst#NL))

    Repeat chars from 0 to ptr
    XB.tx(dataSet[chars]) ' Send bytes to XBee
    pst.Str(String("message envoy
  • ElectrodudeElectrodude Posts: 1,663
    edited 2014-09-29 19:00
    Why did you gut the XBee object instead of just including it? It's a very well written object - why not just leave it all in one piece? It will make your code much more managable, and might even make debugging easier, as you'll be able to more easily track what's your code (and your bugs) and what's part of the XBee library (and its bugs, but I didn't trip over any). I would highly recommend including the XBee object in an OBJ block instead of just borrowing methods from it.

    Your problem is probably the XB.RxFlush at the beginning of your loop. Your code flushes the buffer, deleting the message that was in it, then sends some stuff, then waits forever for a message that never comes because it already came but you threw it out.

    You'll probably find this method useful. Add it to the XBee object:
    Pub API_RxCheck | char, pt ' added by AEM
    {{
      Wait for incoming packet until packet identifer found ($7E), or for empty buffer
      If empty buffer, return 0
      Otherwise, process packet and return 1
      XB.API_RXCheck
      Once data is received, the type of packet can be checked for processing:
      IF XB.RxData == $ 83 ' message string
          ...
      See RxPacket Now for more information
    }}
        _RxIdent := $FF
        dataSet[0] := 0
        repeat
          char := FDSerial.rxcheck
        while (char <> $7E) and char <> -1
    
        if char == $7E
          RxPacketNow
          return 1
    
        return 0
    
    It receives a message if there's already stuff in the buffer, but returns immediately if there isn't. You can use it so that your code doesn't just sit forever if it misses a message, so it can do something else (like resend the request) if no message comes.

    EDIT: got rid of FDSerial4P references
  • Tracy AllenTracy Allen Posts: 6,664
    edited 2014-09-29 21:12
    I think the XBee object would require modifications to support Digimesh. For example, Digimesh on series 3 XBees and also I think on series 1 require 64 bit addresses, and JChris has provided for that in his program. The XBee object uses 16 bit addresses for API mode.

    Electrodude, I see your nice API_rxcheck is calling FDSerial4P. Is that the 4 port object? I'd recommend that too, but it does require changes in the XBee object. And I'd recommend larger buffers.

    JChris, speaking of the serial port, fullduplexserial.spin has only 16 byte buffers. It is possible to overrun those buffers, unless you add support for flow control, or, what I recommend, increase the size of the receive buffer especially so that it can hold an entire 105 byte packet, or more. You said, For testing purpose I am running a repeat loop on both sender and receiver sides. So both propellers are sending and receiving simultaneously. The protocol that I use for XBee is DigiMesh.
    The simultaneous business sounds to me like asking for trouble. I haven't followed the logic of your program carefully, but if they are that intense with activity, may they are interfering with one another happenstance and going to retries. Each packet invokes an ack, or not, and retry. The number of retries is finite, and once used up, the packet is lost. It is possible to lose characters too if the small 16 byte receive buffer is overrun. Not sure how this would cause the lockup, but I'd recommend trying an orderly back and forth between the xbees.
  • JohnR2010JohnR2010 Posts: 431
    edited 2014-09-30 06:13
    I run a few xBee ZB SMTs in API mode to communicate with other ZigBee Home Automation devices and I had to use hardware flow control and the FullDuplexSerial4port object to get it to work reliably. Without flow control I would randomly mis packets and the check-sums wouldn't match in the API packet. The xBees would communicate for awhile but when the network got busy that is when I would see the problems.

    Here is a earlier post of driving an xBee ZB in API mode: http://forums.parallax.com/showthread.php/157233-Propeller-to-SmartThings-%28communicating-with-the-ZigBee-HA-public-profile%29

    I know you already have the chips but if you can make the jump over to Digi's ZigBee platform a huge world opens up to you.

    I implemented hardware flow control to the xBee by connecting CTS P12, and RTS P16 of xBee to available pins on my propeller. If you use the FullDuplexSerial4port object all you have to do is pass those pins when you start the object. You may also want to hook up a wire to the reset pin of the xBee while your at it. On the xBee ZB you have to reset the xBee when you want to leave the network and join a new one stuff like that.
  • ElectrodudeElectrodude Posts: 1,663
    edited 2014-10-01 16:01
    Electrodude, I see your nice API_rxcheck is calling FDSerial4P. Is that the 4 port object? I'd recommend that too, but it does require changes in the XBee object. And I'd recommend larger buffers.

    Thanks for finally giving me an excuse to post this: http://obex.parallax.com/object/763. The version of the 4 port serial driver (Duane Degn's) it comes with has 512 byte buffers, which should be big enough for JChris's problem.
  • Tracy AllenTracy Allen Posts: 6,664
    edited 2014-10-03 10:22
    Electrodude, thanks for posting that. I too have found that systems with XBees always! need more than one serial port.

    About pcFullDuplexSerial4FC512.spin. Duane and I subsequently had quite a bit of discussion about the 4-port object, and my edits became eventually fullDuplexSerial4port. The buffers sizes are individually configurable as CONstants. Your modified version of the XBee object does compile with that. I haven't exercised it with an XBee, but I'd expect it to be okay; in most respects it is functionally equivalent.

    Haven't heard yet if the OP has had success.
  • JChrisJChris Posts: 58
    edited 2014-10-22 06:49
    I tried to use FullDuplexSerial4portPlus_0v2 but it doesn't work. Only sending works but not the receiving. I don't understand why... If anyone can help me. it would be nice.

    [code]



    CON
    _clkmode = xtal1 + pll16x
    _xinfreq = 5_000_000


    port = 0
    XB_Rx = 0
    XB_Tx = 1
    XB_CTS = 2
    XB_RTS = 6
    XB_reset = 7
    XB_Baud = 9600


    TX_PIN = 2
    BAUD = 19_200






    VAR
    Byte dataSet[120],_RxData[105], DigOffset, Inputbyte, Stringptr[200], mot[105]
    Long _SrcAddr16, _RxLen, _RxValue, MY_Addr,stack[200], _srcAddr64_upper, _srcAddr64_lower
    Byte _RxFlag,_RxIdent, _RSSIDec, _RxOpt, _RxFrameID, _RxCmd[3], _Status, _FrameID, _API_Ready, _RSSI, _RxOptions
    Byte dataIn[255], PacketOut[105], PacketPtr
    long _RxADC[6], _RxDig, _RxBit[8], _Temp2
    Byte srcAddy[8]
    ''Bytes needed for TxStatus packet
    Byte _RxRetries,_RxDeliveryStatus,_RxDiscoveryStatus
    ''Bytes needed for normal Rx
    Byte _RxChkSum


    OBJ




    XB : "FullDuplexSerial4portPlus_0v2"
    pst : "Parallax Serial Terminal"




    Pub main | ptr,a


    pst.Start(115200)
    XB.Init
    XB.AddPort(port,XB_Rx, XB_Tx,XB_CTS,XB_RTS,XB_reset, 0, XB_Baud)


    mot[0]:= "d"
    mot[1]:= "a"
    mot[2]:= "m"
    mot[3]:= "i"
    mot[4]:= "e"
    mot[5]:= "n"
    mot[6]:= 0


    Stringptr[0] := "d"
    Stringptr[1] := "a"
    Stringptr[2] := "m"
    Stringptr[3] := "i"
    Stringptr[4] := "e"
    Stringptr[5] := "n"
    Stringptr[6] := 0




    repeat


    XB.rxflush(port)
    API_str($00000000, $0000FFFF, @stringptr)
    pst.str(string("String Sent!"))


    API_Rx
    waitcnt(clkfreq*2+cnt)
    API_Query(String("DB"))
    API_Rx
    pst.Str(String(pst#NL, "RxIdent est:"))
    pst.Hex(_RxIdent,2)
    pst.Str(String(pst#NL,"le RSSI est", pst#NL))
    pst.Dec(_RxValue)




    if(stringCompareCS(@_RxData,@mot) == 0)




    API_Str(_srcAddr64_upper, _srcAddr64_lower, @Stringptr)
    waitcnt(clkfreq+cnt)
    API_Rx


    else
    pst.str(string(pst#NL, "La comparaison n'est pas bonne", pst#NL))
    waitcnt(clkfreq+cnt)






    Pub API_Query (cmd)| Length, chars, csum
    {{
    Sends AT command in API mode to query a parameter value.
    Should also be used to set network identifier.
    Data is returned as an AT response as a string.
    XB.API_Query(string("DL")) ' Query
    XB.API_Rx ' accept response
    myDL := XB.RxValue ' Get returned value
    }}
    dataSet[0] := $7E
    Length := 4 ' API Ident + FrameID + AT cmd
    dataSet[1] := Length >> 8 ' MSB
    dataSet[2] := Length ' LSB
    dataSet[3] := $08 ' API Ident for AT Command (non queue)
    dataSet[4] := $01 ' Frame ID
    dataSet[5] := byte[cmd]
    dataSet[6] := byte[cmd + 1]
    csum := $FF ' Calculate checksum
    Repeat chars from 3 to 6
    csum := csum - dataSet[chars]
    dataSet[7] := csum
    Repeat chars from 0 to 7 ' Send data
    XB.tx(port,dataSet[chars])


    pst.Str(pst#NL)
    pst.Dec(dataSet[5])
    pst.Dec(dataSet[6])




    Pub API_Str(addy64_upper, addy64_lower,donnee)| Length, chars, csum,ptr, stptr, i
    {{
    Transmit a string to a unit using API mode - 16 bit addressing
    XB.API_Str(2,string("Hello number 2")) ' Send data to address 2
    TX response of acknowledgement will be returned if FrameID not 0
    XB.API_RX
    If XB.Status == 0 '0 = Acc, 1 = No Ack


    }}
    ' pst.Str(String(pst#NL))
    ' pst.str(donnee)
    ' i := 0
    ' pst.Str(String(pst#NL))
    ' Repeat (strsize(donnee))
    ' pst.Hex(donnee[i++],4)






    ptr := 0
    stptr := 0
    dataSet[ptr++] := $7E
    Length := strsize(donnee) + 14 ' API Ident + FrameID + API TX cmd +
    ' AddrHigh + AddrLow + Options
    dataSet[ptr++] := Length >> 8 ' Length MSB
    dataSet[ptr++] := Length ' Length LSB
    dataSet[ptr++] := $10 ' API Ident for 16-bit TX
    dataSet[ptr++] := $00 ' Frame ID
    dataSet[ptr++] := addy64_upper >>24
    dataSet[ptr++] := addy64_upper >>16
    dataSet[ptr++] := addy64_upper >>8
    dataSet[ptr++] := addy64_upper
    dataSet[ptr++] := addy64_lower >>24
    dataSet[ptr++] := addy64_lower >>16
    dataSet[ptr++] := addy64_lower >>8
    dataSet[ptr++] := addy64_lower
    dataSet[ptr++] := $FF
    dataSet[ptr++] := $FE
    dataSet[ptr++] := $00
    dataSet[ptr++] := $00 ' Options '$01 = disable ack,
    ' $04 = Broadcast PAN ID
    Repeat strsize(donnee) ' Add string to packet
    dataSet[ptr++] := byte[donnee++]
    csum := $FF ' Calculate checksum
    Repeat chars from 3 to ptr-1
    csum := csum - dataSet[chars]
    dataSet[ptr] := csum


    i := 0
    pst.Str(String(pst#NL))
    Repeat ptr+1
    pst.Hex(dataset[i++],2)
    ' pst.Str(String(pst#NL))
    ' pst.Str(String(dataSet[i++],pst#NL))


    pst.Str(String(pst#NL))


    Repeat chars from 0 to ptr
    XB.tx(port,dataSet[chars]) ' Send bytes to XBee
    pst.Str(String("message envoy
Sign In or Register to comment.