ROBIN - ROBot Independent Network, A Simple Network for RS485

ROBIN is a simple packet protocol conceived and discussed on the TheRoboticsClub Yahoo! Group in Sept. of 2003 and has been refined somewhat since then. The intent is to create a standard protocol that can be used to communicate between robot controllers and peripherals. Thus, vendors may be encouraged to offer sensors, motor controllers, cameras, etc, that speak the ROBIN protocol, and robot builders will benefit by being able to utilize the great features of RS485 without having to custom design all the components.

RS485 is an excellent communications protocol, providing high speed, multiple transceivers, and noise immunity on a simple, two wire bus. The problem with RS485 is that it stops at the hardware and doesn't say anything about what the actual data bytes and packets look like. Thus, folks that use RS485 must create their own communications protocol to talk to other devices on the bus. And as a result, it's nearly impossible for third party vendors to create products that speak RS485 because they cannot know in advance what data protocol the end user's RS485 protocol will be using.

The whole point of ROBIN is to define a standard packet format and a way of sharing the bus by multiple masters so that vendors can create devices that integrate with RS485 and end users can have a reasonable expectation that they can communicate with these devices to create something useful.

There's nothing particularly novel or earth shattering about ROBIN. It's primary purpose is to simply provide a reasonable protocol that is not too contraining, yet is simple enough to implement in a smallish microcontroller.

ROBIN utilizes RS232 bit encoding. The data length can be either 8 or 9 bits, but does not demand one or the other. Vendors should allow their devices to be configured to work with either. If 9-bit data lengths are used, the only data field which sets the 9th bit is the <dst> (destination node) field, which is the first byte of a packet. Some microcontrollers can optimize data reception in this mode, but not all support it.

ROBIN defines 1 packet format as follows:


  <preamble> <dst> <src> <flags> <len> <data> ... <data> <cksum>

The maximum packet length is 64 bytes which leaves a maximum of 59 bytes for the data payload area.

  • <preamble> : 0xaa 0x99, intended to help identify the beginning of a packet. Note that some hardware supports 9-bit data lengths, and in that case, setting the 9th bit on the <dst> field indicates the beginning of a packet. If 9-bit data is used, the <preamble> is redundent, however, 9-bit implemenations should be tolerant of the <preamble> even so. Because the ROBIN spec does not mandate 9-bit data widths, vendors who make devices for ROBIN should offer a jumper or other means to enable or disable 9-bit data lengths so that they may participate in ROBIN networks that use 8-bit data lengths (most standard PC hardware supports only 8-bit data lengths), or in networks where 9-bit data lengths are used.

  • <dst> : destination node id; two node id's are special:

    • 0x00 = default master address for a single master network

    • 0xfe = temporary address reserved for node configuration

    • 0xff = broadcast address

  • <src> : source node id

  • <flags> : packet flags, bit fields, that indicate whether an ACK should be returned in response or not, as well as a few bits that can be defined for use by the application itself. This format is:

    Bits: 7 6 5 4 3 2 1 0

    • bit 7 - application defined bit 2 - this bit is ignored by ROBIN and is free for application use

    • bit 6 - application defined bit 1 - this bit is ignored by ROBIN and is free for application use

    • bit 5 - reserved

    • bit 4 - CONFIG - this bit indicates that the packet contains a configuration command. A configuration command begins with a command byte and zero or more data bytes. Three command bytes are currently defined:

      • 0x01 - set the device nodeid. This is a 2-byte command, the second byte is the new nodeid.

      • 0x02 - set 8 or 9 bit mode. This is a 2-byte command, the second byte is as follows:

        • 0x08 - set 8 bit data mode

        • 0x09 - set 9 bit data mode

      • 0x03 - set baud rate. This command is followed by either 1 or 5 bytes as follows, depending on the value of the byte following the command byte:

        0x00next 4 bytes are the specified baud rate, LSB first
        0x012400 baud
        0x024800 baud
        0x039600 baud
        0x0419200 baud
        0x0538400 baud
        0x0657600 baud
        0x07115200 baud
        0x08230400 baud
        0x09460800 baud
        0x0a921600 baud

      • 0x04 - save changes. This command saves any changes that have been made to the configuration to non-volatile storate such as EEPROM. New changes will take effect upon the next reset.

      • 0x05 - apply changes. This command applies any changes that have been made to the configuration and the changes take effect immediately following the command-response packet. This command can be used to make the changes take effect without having to wait for a reset in the case that the changes were previously saved, but a reset has not occured.

      • 0x06 - sleep. This command puts the recipient node to sleep or have it enter a low-power state and stop performing it's primary task. For example, if the node is a motor controller, the node might disable it's h-bridge and minimize current consumption.

      • 0x07 - wake. This command undoes the sleep command and brings the recipient node back to attention.

      • 0x08 - halt. This command prepares a node for power-down and should be an indication for the node to save any state that it may need to save. The node then enters the sleep state, if implemented.

      • 0x09 - reset. This command causes the recipient node to reset and reboot.

      Every command received requires a 1 byte response. The value of the byte indicates whether the command was understood and accepted or not, as follows:

      • 0x00 - command accepted and understood

      • 0x01 - invalid parameter or command not possible. This would be the response if one commanded a node to run at 115200 baud, but the node could not actually run that fast.

      • 0x02 - command not understood. This is the response if the node does not understand the command presented, or the command is not implemented.

    • bit 3 - ID_REQ - id requested. When a packet is received with this bit set, the recipient should respond with a packet whose data contains information about the device itself. The response data should be ASCII text and the following format should be used as a guideline for formating the data response:

      manufacturer : product : device specific

      The length of the response data can be up to the max data length in size (59 bytes). Manufacturers should use this field to identify their devices. The intent is so that one can scan the bus for devices, elicit a response from each device, and display the device id information in a human readable format. This allows one to ensure that devices are wired correctly and are properly responding on the ROBIN bus.

      More advanced applications might alter their behaviour based on the response provide by the ID request.

    • bit 2 - ACK_REQ - ack requested. When a packet is received with this bit set, the recipient is required to send either an ACK or a NACK in return to the sender to acknowledge that the packet was either received OK (ACK), or that the packet was received but not usable (NACK). A packet might not be usable because the checksum was back or perhaps the data content was not understood (bad command).

      If a packet is received with the ACK_REQ bit set but the packet has a zero-length data payload area, the recipient should respond with an ACK (assuming the cksum was good). This allows a host controller to probe for other nodes on the network.

    • bit 1 - NACK - not acknowledge, sent in response to a packet received with the ACK_REQ bit set. The NACK bit is set to mean the packet was not usable for some reason.

    • bit 0 - ACK - acknowledge, sent in response to a packet received with the ACK_REQ bit set. The ACK bit is set to mean everything about the packet checks out and is good. The ACK packet can also contain a useful data response if it is convenient for the application, or the data area can be empty (zero length).

  • <len> : data len, length of the data payload area. If no data is sent in the packet, the length is set to zero.

  • <data> : data byte, exactly <len> data bytes for sending to the recipient.

  • <cksum> : simple 8-bit overflowing checksum.

Communications Configuration - All devices need to go through some minimal configuration in order to be able to talk on a ROBIN network. Minimally 3 items need to be specified: node id, 8 or 9-bit data length for comms, and the baud rate. All devices should include a mechanism by which these items can be set. Jumpers or switches can work where available. Alternately, if the device has EEPROM or other non-volatile storage available where parameters can be saved and restored across power cycles, ROBIN's CONFIG mechanism can be used. If the CONFIG method is used (see CONFIG bit above), a single jumper or some other means needs to be implemented to tell the device to enter configuration mode. In this mode, communications are set to 8-bit, 9600 baud, and the device being configured should assume the temporary node id of 0xfe. It should then listen for ROBIN packets with the CONFIG bit set and accept configuration information using the 3 command bytes specified above that have meaning when the CONFIG bit is set in the <flags> byte.

After configuration is complete, the configuration jumper should be removed and the device reset or power-cycled, at which time the device should reboot and use the newly configured settings.

Packet Send/Receive Considerations

If the sender wants confirmation of packet reception, it should set the "ack requested" bit. Setting this bit is purely up to the sender - it might choose not to if reception of the packet is not critical. Nothing says that packets must be ACK'd. But if a sender does request an ACK, the recipient is obligated to respond with either an ACK or a NACK. And appropriate ACK response must be the next packet received from the <dst> and it must have the ACK or NACK bit set. If the packet from the <dst> node is received and doesn't have either of these two bits set, the original packet should be considered unresponded to.

If the host requests an ACK but does not get a response, it is up to the host to decide whether to resend the packet or not. The suggested implemenation is to wait for up to some maximum wait time as defined by the host controller, for example 50 ms, and then resend the packet. If still no response is provided, it is recommended that the host repeat the packet a few times but if there is still no response the host should fail the operation as gracefully as it can.

In several of my particular implementations, I wait for up to 50 ms for an ACK or NACK response, and if I don't get one, I resend the packet. I try this for up to 3 times and then give up. Usually the only time I don't get an ACK is when the destination node is turned off, mis-wired, mis-configured, or when the host is addressing the wrong node.

Also note that in the typical half-duplex RS485 network, it takes a finite amount of time to turn around the network from the time data was received to when the receiver can generate a response. Because of this, receivers, especially those built from very fast MCUs, should delay a short amount between receiving a request and responding to allow the sender a chance to release the bus and start listening.

Advanced ROBIN - Multi-Master

While ROBIN does not require multi-master behaviour, it does not preclude it. In the multi-master case, it is possible that two nodes will attempt to talk on the bus at the same time. Therefore, senders need to be able to detect a collision - this happens when two senders transmit at the same time resulting in both packets being garbled.

The listener nodes can discard the packet in this case because the checksum should flag a packet error. What can the sendor do? Most (all) RS485 chips have an independently enabled RX and TX. In the multi-master case, the sendor should leave the RX enabled during its transmit phase. It can then receive the packet that it just sent, similar to a UART loopback mode. After all the bytes are sent, it can compare what it thought it sent, which what it actually sent. If the packets do not match, then the likely cause is that a collision occured - someone else was transmitting at the same time. No extra hardware is required to do this, just a little extra software logic.

Once a collision is detected, the sendor should back-off by a random amount an retry its send. It is important not to back-off by a fixed amount of time because that could lead to two or more senders continously trying to resend and continously generating collisions. A sender should consider giving up on the transmit operation if it detects a certain number of collisions in a row, say 5 or 10.

Note that only Master devices need worry about collisions in a multi-master setup. A typical slave device like a motor controller or a sensor can operate without collision detection. If a master device requests information from a slave device, and the slave's response collides with a packet from another master trying to talk at the same time, the first master will note that the response packet either was never received or was received with a checksum error. The master device can then decide whether to re-query the slave device or not. Thus, the slave device is not required to implement collision detection.

Sample program is here.