Shop OBEX P1 Docs P2 Docs Learn Events
Issues Controlling 10 Xbees with 1 Master Coordinator — Parallax Forums

Issues Controlling 10 Xbees with 1 Master Coordinator

dermotdermot Posts: 26
edited 2011-12-17 13:05 in Accessories
Hi,

I am using 10 Xbee Wireless Modules as end devices and one coordinator. Up to a maximum of 5 end devices can transmit simultaneous to the coordinator. This causes difficulty as only one end device data is been processed.

It is a point to multi-point communications.

An end device consists of 2 sensors and 4 lights, the coordinator controls the lights based on the sensor feedback. All data transmitted is decimal numbers (max. 2 digits transmitted)

The XBee parameters are configured using AT commands.
Parameter I have changed are (Channel, Personal Area Network ID's, MY_Address, Destination _Address and Random Delay slots (CSMA-MA).

The Propellor P8*32A is the microcontrollor been used. There is one microcontrollor connected to each XBee. Im using the standard XBee driver available on OBEX.

N.B. Transmissions take place in a fire and forget manner, there is no error checking.

It is my first time working with these wireless devices. Maybe there is some setup parameter I can adjust or configure to make a difference.

Comments

  • FranklinFranklin Posts: 4,747
    edited 2011-12-13 13:22
    You might be better off using the API mode.
  • dermotdermot Posts: 26
    edited 2011-12-16 15:55
    Is it possible to increase the buffer to enable more data be received successfully at the coordinator. This is partially important when more than one device transmits at the same time to the coordinator.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2011-12-17 00:09
    dermot,

    Yes, it's possible to increase the buffer of most serial objects.

    I have several variations of Tim Moore's four port serial driver. Several of the versions have 512 rx buffers.

    I use a variation similar to the driver in post #9 in many of my projects. With that driver, I just check for a new message each program loop instead of checking for individual bytes. The driver increments a counter each time it encounters an end of message character. If your messages use an end of message character, you might want to try it. Otherwise you might want to try the other 512 byte rx buffer driver in post #1.

    I have a project using multiple transmitters where I was concerned simultaneous transmissions would interfere with each other. I assigned a unique ID (stored in upper EEPROM) to each Propeller/transmitter unit. The Propellers would then take turns transmitting. They used the ID number to determine when it was their turn to transmit. It doesn't look like you need something like this now but I thought I'd mention it in case your concerned about the XBee transmissions interfering with one another (although I think XBee's may be smart enough to do this on their own (I don't know (yet))).

    What series are your XBees? It sounds like they're Zigbee Xbees.
  • Tracy AllenTracy Allen Posts: 6,664
    edited 2011-12-17 08:19
    Dermot, the term "coordinator" has a special meaning in XBee-speak. Maybe you are using the term loosely, as the device at the hub of your "peer to peer" network.

    In series 1 XBees, one device in the network can be anointed as the official coordinator by giving it the ATCE command. At network startup it can choose the channel (based on its scan to find a free one), and it can choose the PAN ID (also based on a scan so as not to interfere with existing networks). The end-point devices are allowed to "associate" with the coordinator through a song-and-dance, and the end-points find out the channel and PAN ID from their associated coordinator. It is a complicated process, and the series 2 XBees (ZB, Zigbee) make the coordinator obligatory. You don't need it, I think! That is just a terminology heads-up.

    I agree that larger buffers are the quickest way to better performance. You should be able to substitute a different serial object for full duplex serial in Martin Hebel's XBee object, so long as it has the same methods.

    One parameter to watch out for when you have multiple XBees sending to a hub is the packetization timeout, ATRO. The default is 3 character times, about 3 milliseconds at 9600 baud. If for some reason the transmitting Prop has a gap of time in sending bytes to the XBEE, the XBee will transmit more than one packet. That can be a real headache at the receiving end.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2011-12-17 10:33
    Looking at FullDuplexSerial, I think the rx buffer could be changed by changing three lines of code.

    The first change is in the VAR section.

    Original:
    VAR
      long  cog                     'cog flag/id
      long  rx_head                 '9 contiguous longs
      long  rx_tail
      long  tx_head
      long  tx_tail
      long  rx_pin
      long  tx_pin
      long  rxtx_mode
      long  bit_ticks
      long  buffer_ptr
                         
     [B] byte  rx_buffer[16][/B]           'transmit and receive buffers
      byte  tx_buffer[16]  
    
     
    

    Modified:
    VAR
      long  cog                     'cog flag/id
      long  rx_head                 '9 contiguous longs
      long  rx_tail
      long  tx_head
      long  tx_tail
      long  rx_pin
      long  tx_pin
      long  rxtx_mode
      long  bit_ticks
      long  buffer_ptr
                         
      [B]byte  rx_buffer[[COLOR=#ff0000]128[/COLOR]][/B]           'transmit and receive buffers
      byte  tx_buffer[16]  
    
     
    

    This will increaser the rx_buffer from 16 to 128. You can use any power of 2 for the buffer size (2, 4, 8, 16, 32, 64, 128, 256, 512).

    The second location to change is in the rxcheck method:
    PUB rxcheck : rxbyte
    '' Check if byte received (never waits)
    '' returns -1 if no byte received, $00..$FF if byte
      rxbyte--
      if rx_tail <> rx_head
        rxbyte := rx_buffer[rx_tail]
       [B]rx_tail := (rx_tail + 1) & $F
    [/B]
     
    

    Modified:
    PUB rxcheck : rxbyte
    '' Check if byte received (never waits)
    '' returns -1 if no byte received, $00..$FF if byte
      rxbyte--
      if rx_tail <> rx_head
        rxbyte := rx_buffer[rx_tail]
        [B]rx_tail := (rx_tail + 1) & [COLOR=#ff0000]$7F[/COLOR][/B][COLOR=#ff0000]
     
    [/COLOR]
    

    $7F is hexadecimal for 127. This number should be one less than the rx buffer size.

    The above code wraps rx_tail back to zero once it reaches the end of the buffer.

    We need to do the same thing with rx_head. rx_head is little harder to find since it's passed to the cog with the par register.

    The head (with the temp name of t2) is "anded" a little before the "transmit" section of code.
    rdlong  t2,par                'save received byte and inc head
                            add     t2,rxbuff
                            wrbyte  rxdata,t2
                            sub     t2,rxbuff
                            add     t2,#1
                            [B]and     t2,#$0F
    [/B]                     wrlong  t2,par
                            jmp     #receive              'byte done, receive next byte
    '
    '
    ' Transmit
    '
    transmit                jmpret  txcode,rxcode         'run a chunk of receive code, then return
    
    

    Change to:
    rdlong  t2,par                'save received byte and inc head
                            add     t2,rxbuff
                            wrbyte  rxdata,t2
                            sub     t2,rxbuff
                            add     t2,#1
                            [B]and     t2,#[COLOR=#ff0000]$7F
    [/COLOR][/B]                    wrlong  t2,par
                            jmp     #receive              'byte done, receive next byte
    '
    '
    ' Transmit
    '
    transmit                jmpret  txcode,rxcode         'run a chunk of receive code, then return
    
    

    I'm pretty sure that will change the rx buffer of FullDuplexSerial from 16 bytes to 128 bytes.

    Limiting the buffer sizes to powers of two makes it easy to wrap the head and tail back to zero with an and opperation. It wouldn't be too hard to modify the code to allow any buffer size; it would just make for a little longer and a little slower code.

    All the serial objects I've looked at don't test to see if the head is passing the tail. If the head does pass the tail, you lose all the data in the buffer.
  • Tracy AllenTracy Allen Posts: 6,664
    edited 2011-12-17 11:21
    Duane,

    I've seen and used the following code to make the buffer any size up to 511 bytes. The trick is the cmpsub instead of and for wrap:
    [COLOR=#ff0000]RXBUFSIZ   con 500[/COLOR]   ' can be any value up to 511 (not necessarily a power of 2
      '...
      byte  rx_buffer[[COLOR=#ff0000]RXBUFSIZ[/COLOR]]           'transmit and receive buffers
      '...
      rx_tail := (rx_tail + 1) [COLOR=#ff0000]// RXBUFSIZ[/COLOR]
      '...
      [COLOR=#ff0000]cmpsub     t2,#RXBUFSIZ  ' [/COLOR]in place of, and t2,#$0F
    
  • Duane DegnDuane Degn Posts: 10,588
    edited 2011-12-17 13:05
    Duane,

    I've seen and used the following code to make the buffer any size up to 511 bytes. The trick is the cmpsub instead of and for wrap:
    [COLOR=#ff0000]RXBUFSIZ   con 500[/COLOR]   ' can be any value up to 511 (not necessarily a power of 2
      '...
      byte  rx_buffer[[COLOR=#ff0000]RXBUFSIZ[/COLOR]]           'transmit and receive buffers
      '...
      rx_tail := (rx_tail + 1) [COLOR=#ff0000]// RXBUFSIZ[/COLOR]
      '...
      [COLOR=#ff0000]cmpsub     t2,#RXBUFSIZ  ' [/COLOR]in place of, and t2,#$0F
    

    That's a lot better than the code I had in mind. Now it seems silly to limit a buffer to powers of two (as PST does).

    Thanks.
Sign In or Register to comment.