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.
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.