Skip to content
SimonRichards edited this page Oct 15, 2011 · 3 revisions

CAN Protocol

Message Format

CAN provides us with 1-8 bytes of data per packet. This comes with an overhead of at least 44 bits + bit stuffing. Because of the high proportion of overhead introduced by the low level frame (85% with one data byte — 40% with 8 bytes) it was decided that we can easily sacrifice a large proportion of each packet to our own protocols frame, without increasing overhead drastically, while aiming to keep our frames under 8 bytes to ensure they don't require fragmentation.

Based off this the protocol shown below was developed:

+--------------+------------+---------+-------------------------+
| From Address | To Address | Command | Data (Command Specific) |
|    1 byte    |   1 byte   | 1 byte  |       1 - 5 bytes       |
+--------------+------------+---------+-------------------------+

The address sent in this protocol doesn't necessarily have to directly relate to some CAN ID. Think of it like an IP address vs the CAN ID as a MAC address.

In our implementation the addresses do actual correspond to the CAN ID, because we only need 5 addresses for the boards we first limit it to only 3 bits then derive the CAN ID as a 3 bit priority code, followed by a one bit, followed by the 3 bit address, another one bit and finally 3 zero bits.

The reason for embedding 1 bits into the message is to avoid bit stuffing in the majority of cases.

This makes the implementation of the sending code simpler as it is easy to take the given address and create the CAN ID on the fly.

For example the pseudo code is

can_id = priority ⊕ 0b1 ⊕ address ⊕ 0b1000

where ⊕ is a binary concatenation operator.

The command is the major decider of what is being sent. It is simply an enum declared in lib/drivers/protocol/definitions.h, the descriptions of what each of these commands mean and what the associated data is follows.

The data is entirely command specific and can be

Commands

Command Description enum Identifier enum Value Data bytes
None Default command used to represent empty command struct. Reception of a message containing this is representative of an error. CMD_NONE 0x00 None
Get Variable Requests the device return the value of the variable given in the Variable Identifier. CMD_GET 0x01 Variable Identifier (1 byte, variable_t)
Reply Is a response to a Get Variable request, the number of bytes used to encode the variable is variable dependent CMD_REPLY 0x02 Variable Identifier (1 byte, variable_t), Variable Value (1-4 bytes, unsigned char - unsigned int)
Set Variable Sends a new value for a variable, the number of bytes used to encode the variable is variable dependent. CMD_SET 0x03 Identifier (1 byte, variable_t), Value (1-4 bytes, unsigned char - unsigned int)
Request Calibration Asks the recipient if it is ready to transition into claibration state. CMD_REQ_CALIBRATE 0x04 None
Acknowledge Calibration Responding to the above request, the sender is ready to transition. CMD_ACK_CALIBRATE 0x05 None
Request Run Same as request calibration, except the transition is into the run state. CMD_REQ_RUN 0x06 None
Acknowledge Run Same as acknowledge calibration, except the transition is into the run state. CMD_ACK_RUN 0x07 None
No The sending board is not ready for the transition just requested be the recipient. CMD_NO 0x08 None
Error An error condition has been met, recipient(s) are to transition to error state. CMD_ERROR 0x09 None
Run Transition into run state. CMD_RUN 0x0A None
Calibrate Transition into calibration state. CMD_CALIBRATE 0x0B None