In many medical devices, especially those that are microprocessor controlled, it is common for programmable subsystems to communicate via asynchronous serial protocols. Such subsystems include things like programmable power supplies, syringe pumps, temperature controllers, motor controllers and smart linear actuators. I’m often surprised by how many of these devices have poorly thought-out protocols that make it difficult to ensure they will behave safely and correctly during normal operation.
Whether I’m choosing an off-the-shelf subsystem or designing one from scratch I always consider the control protocol carefully and ensure certain features are present.
Here’s some quick background on serial communication protocols. Asynchronous protocols occur on a communication channel called a “bus” and often conform to electrical standards such as RS232 or RS485, TTL levels and open collector standards with pullup resistors. Data is commonly transferred in discrete groups of bytes called “packets” rather than as a continuous stream. There are usually two types of devices communicating: a host and one or more slaves. Communication on the bus will be initiated by the host sending a packet and then this will be responded to by the slave or slaves. For consistency, I call packets from the host “requests” – whether for data or for a particular action from the slave – and the slaves then reply with a “response”. Now I’ll get into the details.
A good protocol must have a well-defined start and end to each packet. Without these, a device can get confused – sometimes for a long time – if it incorrectly identifies a byte from the middle of a packet as a packet start. A common method to define the packet start is to use a particular byte value. It is often impractical to ensure that this byte cannot occur elsewhere in the packet but this, along with additional means can ensure a robust protocol. The end of the packet can be defined similarly with a special byte value or simply by knowing the length of the packet.
A good protocol must have some method to determine if a packet was received correctly and without errors. There are plenty of reasons why there might be a communication error: noise could cause a bit to be misheard, a byte might not be heard at all, a software bug might cause a register to be read early or late, a packet start might be erroneously assumed, etc. I find some of these things happen regularly. If the packet has some sort of redundancy, like a checksum or CRC, then devices can detect errors and take appropriate action, such as ignoring the packet altogether.
A good protocol ensures that any command packet gets an immediate response. It is usually important for performance or safety reasons for the host to know that a request was heard. I’ve encountered many systems that don’t respond until the requested action is complete. In the case of a linear stage or temperature controller, this action can take a long time to complete and the host has no idea if it was even heard during this period. If instead the slave is expected to send an immediate response then if the host doesn’t hear anything within the specified short time, it will know the request was lost and can take appropriate action, like resending, for instance. If the host knows immediately that a request got through, then it can confidently put its mind to something else, like monitoring progress of the requested action, or queuing another action to another slave.
A good protocol specifies maximum time limits on packet and response completion. If it’s assumed that packets can be lost or heard incorrectly, it is important to specify how long a host needs to wait before taking action. Similarly, both hosts and slaves need to know how long to keep waiting for the completion of a packet being received before discarding a packet fragment. Both of these timing parameters allow a protocol to make the best use of available bandwidth, and reduce the time that the system might be in an unknown state.
It’s also useful if minimum timing requires are also specified. This is useful because the host – which is often running a high-level OS – is often not able to react to packets in a very short time. Often it can take 20ms or more for the host to react to the state of a slave or the state of the bus and send out a new request. It’s nice when the protocol does not have unreasonable expectations of the host, which would otherwise drive the need for real-time OSes or additional microprocessors just to handle communication.
A good protocol demands that devices are able to continue communication even when they are busy doing other things. I’m surprised when I find a device which goes deaf while carrying out an action. Picture a linear stage that doesn’t respond to position queries simply because it was asked to execute a particular motion. That’s exactly the time that the host would want to know precisely what’s going on, to ensure the system remains safe.
These are all aspects I consider when I’m designing or selecting subsystems for use in a medical device. It’s not always possible to get exactly what I want, but at least I can identify unfriendly asynchronous serial protocols and allocate sufficient time and resources early on to mitigate any resulting safety or functionality concerns.
Kenneth MacCallum, PEng, is a Principal Engineering Physicist at Starfish Medical. He works on Medical Device Development and loves motors, engines and trains as well as the batteries that power them. He may not know what art is, but he knows when he sees good asynchronous serial protocols.
Photo credit: Wikipedia Media