-
Notifications
You must be signed in to change notification settings - Fork 1
CAN Protocol
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
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 |