6.5. Cyclic Redundancy Check (CRC) Error Detection

For certain applications, verifying the integrity of the data you are sending and receiving can be very important. Because of this, the Simple Motor Controller has optional 7-bit cyclic redundancy checking, which is similar to a checksum but more robust as it can detect errors that would not affect a checksum, such as an extra zero byte or bytes out of order.

Cyclic redundancy checking can be enabled by selecting a CRC Mode of “Commands only” or “Commands and responses” in the Input Settings tab of the Simple Motor Control Center. In CRC mode, the Simple Motor Controller expects an extra byte to be added onto the end of every Binary-mode command packet (CRC error checking is not available when the serial mode is “ASCII”). The most-significant bit of this byte must be cleared, and the seven least-significant bits must be the 7-bit CRC for that packet. If this CRC byte is incorrect, a CRC Error will occur and the command will be ignored. The Simple Motor Controller will append a CRC byte to the data it transmits in response to serial commands if the CRC mode is “Commands and responses”.

A detailed account of how cyclic redundancy checking works is beyond the scope of this document, but you can find more information using Wikipedia. The CRC computation is basically a carryless long division of a CRC “polynomial”, 0x91, into your message (expressed as a continuous stream of bits), where all you care about is the remainder. The Simple Motor Controller uses CRC-7, which means it uses an 8-bit polynomial and, as a result, produces a 7-bit remainder. This remainder is the lower 7 bits of the CRC byte you tack onto the end of your command packets.

For sample C code that computes the CRC byte of a command packet, see Section 6.7.6.

The CRC implemented on the Simple Motor Controller is the same as the one on the Maestro servo controller and jrk and qik motor controllers, but it differs from that on the TReX motor controller. Instead of being done MSB first, the computation is performed LSB first to match the order in which the bits are transmitted over the serial line. In standard binary notation, the number 0x91 is written as 10010001. However, the bits are transmitted in this order: 1, 0, 0, 0, 1, 0, 0, 1, so we will write it as 10001001 to carry out the computation below.

The CRC-7 algorithm is as follows:

  1. Express your 8-bit CRC-7 polynomial and message in binary, LSB first. The polynomial 0x91 is written as 10001001.
  2. Add 7 zeros to the end of your message.
  3. Write your CRC-7 polynomial underneath the message so that the LSB of your polynomial is directly below the LSB of your message.
  4. If the LSB of your CRC-7 is aligned under a 1, XOR the CRC-7 with the message to get a new message; if the LSB of your CRC-7 is aligned under a 0, do nothing.
  5. Shift your CRC-7 right one bit. If all 8 bits of your CRC-7 polynomial still line up underneath message bits, go back to step 4.
  6. What’s left of your message is now your CRC-7 result (transmit these seven bits as your CRC byte when talking to the Simple Motor Controller with CRC enabled).

If you have never encountered CRCs before, this probably sounds a lot more complicated than it really is. The following example shows that the CRC-7 calculation is not that difficult. For the example, we will use a two-byte sequence: 0x83, 0x01.

Steps 1 & 2 (write as binary, least significant bit first, add 7 zeros to the end of the message):

    CRC-7 Polynomial = [1 0 0 0 1 0 0 1]
    message = [1 1 0 0 0 0 0 1] [1 0 0 0 0 0 0 0] 0 0 0 0 0 0 0

Steps 3, 4, & 5:

                    _______________________________________________
    1 0 0 0 1 0 0 1 ) 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
                  XOR 1 0 0 0 1 0 0 1 | | | | | | | | | | | | | | |
                      _______________ | | | | | | | | | | | | | | |
                        1 0 0 1 0 0 0 1 | | | | | | | | | | | | | |
           shift  ----> 1 0 0 0 1 0 0 1 | | | | | | | | | | | | | |
                        _______________ | | | | | | | | | | | | | |
                              1 1 0 0 0 0 0 0 | | | | | | | | | | |
                              1 0 0 0 1 0 0 1 | | | | | | | | | | |
                              _______________ | | | | | | | | | | |
                                1 0 0 1 0 0 1 0 | | | | | | | | | |
                                1 0 0 0 1 0 0 1 | | | | | | | | | |
                                _______________ | | | | | | | | | |
                                      1 1 0 1 1 0 0 0 | | | | | | |
                                      1 0 0 0 1 0 0 1 | | | | | | |
                                      _______________ | | | | | | |
                                        1 0 1 0 0 0 1 0 | | | | | |
                                        1 0 0 0 1 0 0 1 | | | | | |
                                        _______________ | | | | | |
                                            1 0 1 0 1 1 0 0 | | | |
                                            1 0 0 0 1 0 0 1 | | | |
                                            _______________ | | | |
                                                1 0 0 1 0 1 0 0 | |
                                                1 0 0 0 1 0 0 1 | |
                                                _______________ | |
                                                      1 1 1 0 1 0 0 = 0x17

So the full command packet we would send with CRC enabled is: 0x83, 0x01, 0x17.