CANopen Primer
Note
This only goes over the basics of CANopen for what is need to work on a OreSat device. For the full standards, see the CAN in Automation (CiA) website.
CANopen is a message protocol for CAN messages on a CAN bus by CAN in Automation (CiA).
CANopen only uses little endian in its messages.
Nodes
A node is a CANopen device.
All nodes will have an unique NODE-ID, between 0x01 and 0x7F.
Note
On OreSat, the C3 will always have the NODE-ID of 0x01.
All nodes other than the C3 have NODE-IDs are multiples of 0x04;
e.g: 0x04, 0x08, 0x12, etc. See the notes in the PDO section
for the reasoning.
OD (Object Dictionary)
The data structure that hold all data for CANopen node.
Objects can have indexes and subindex.
Valid indexes range from 0x1000 to 0x8000 and valid subindexes range from
0x00 to 0xFF.
Objects at an index can be Variables, Arrays, or Records.
Variable
Can be at a index or at a subindex of a Record/Array.
Has a access type of readonly, writeonly, readwrite, or constant.
Has a default value (if not set it will be 0 or something similar for the data type).
Optional, callbacks can be setup by software on read and/or writes.
Data Types
Name |
C Data Type |
Description |
|---|---|---|
BOOLEAN |
bool |
A true / false value |
INTEGER8 |
int8_t |
8-bit signed integer |
INTEGER16 |
int16_t |
16-bit signed integer |
INTEGER32 |
int32_t |
32-bit signed integer |
INTEGER64 |
int64_t |
64-bit signed integer |
UNSIGNED8 |
uint8_t |
8-bit unsigned integer |
UNSIGNED16 |
uint16_t |
16-bit unsigned integer |
UNSIGNED32 |
uint32_t |
32-bit unsigned integer |
UNSIGNED64 |
uint64_t |
64-bit unsigned integer |
REAL32 |
float |
32-bit floating point number |
REAL64 |
double |
64-bit (double-precision) floating point number |
VISABLE_STRING |
char [] |
An ASCII string |
OCTET_STRING |
uint8_t [] |
An octet string |
DOMAIN |
void * |
A null value that must be have callback function(s) |
Note
There are other standard CANopen data types, but they are omitted as they are unused by OreSat.
Array
Can only be at an index.
All subindexes other than subindex
0x00, must be the same data type.Subindex
0x00is a Variable with value of the highest subindex.Variables in a Array do not have have sequential subindex; e.g.: a Array can have object at subindexes
0x00,0x01,0x04(no objects at0x02or0x03in this example).
Record
Can only be at an index.
Subindex
0x00is a Variable with value of the highest subindex.Variables in a Record do not have have sequential subindex; e.g.: a Record can have object at subindexes
0x00,0x01,0x04(no objects at0x02or0x03in this example).
Object Groups
Indexes can be divide into 3 groups: Mandatory, Manufacture, and Optional.
Mandatory Objects (
0x1000,0x1001,0x1018) are required indexes for all nodes.Manufacture Objects (
0x2000to0x5FFF) are objects added by manufacturer.Optional Objects (
0x1000to0x1FFFand0x6000to0x8000) are objects added by user.
Note
On OreSat:
Indexes
0x1000to0x2FFFare reserved for CANopen standard objectsIndexes
0x3000to0x3FFFare reserved for common OreSat objects between all cardsIndexes
0x4000to0x4FFFare reserved for unique OreSat objects for a cardIndexes
0x5000to0x5FFFare reserved for mapped RPDO objectsIndexes above
0x6000are not used.
Files
Both EDS and DCF files are used to document and configure a CANopen device as well as generate code for the OD for software / firmware.
EDS (Electronic Data Sheet)
An EDS file a .conf or .ini like configuration file for describing the
OD. It is used as the documentation and configuration file of a device.
DCF (Device Configure File)
A DCF file is mostly a EDS file with a extra section for device configuration
like NODE-ID, node name, and other node unique things.
A EDS is general file for a device and is used to generate the DCF. The DCF is used when the device is on an actual production CAN bus.
The main benefit of a DCF is if there are multiple of the exact same device on the CAN bus, they all will have an unique DCF that was made from the same EDS file.
Note
For OreSat, EDS / DCF files are not used anymore. They were to hard to keep in sync, a one change to a card EDS could effect all other cards. Now a centralized database of OD definitions as YAML files can be found in the oresat-configs git repo. Each YAML config acts like EDS, but as all configs are loaded in by script the resulting data gets turned into a DCF equivalent. Also, all YAML config file are much smaller and easier to quickly understand than an EDS / DCF file.
Messages
COB-ID term is used as the name of the 11-bit identifier field of a CAN
message for a CANopen message.
COB-ID is made up of 4-bits for the CANopen message id and 7-bits for the
NODE-ID.
CANopen nodes use the COB-ID to id all messages.
Heartbeat
All node send out a 1-byte heartbeat message with a COB-ID of
0x700 + NODE-ID.
Heartbeat consumer node(s) can use the heartbeat message to confirm what boards are on and in a good state.
Value |
Description |
|---|---|
0x00 |
Boot up |
0x04 |
Stopped |
0x05 |
Operational |
0x7F |
Pre-operational |
Example heartbeat messages from node 0x10
$ candump vcan0
vcan0 710 [1] 05
vcan0 710 [1] 05
vcan0 710 [1] 05
Note
On OreSat, all nodes (including the C3) broadcast a heartbeat every second. The C3 monitors all heartbeats.
SDO (Service Data Object)
SDOs allow a node to upload or download an object value to or from another node’s OD. The initiating node acts as the client and the node it is communicating with acts as the server in client-server model. A upload can also be thought of as a write; where the client upload/writes a value to the server. A download can also be thought of as a read; where the client download/reads a value from the server.
SDOs are the only messages that span over multiple CAN message, as the value that is being read or written can be any length as defined by OD.
A SDO client will use a COB-ID of 0x580 + NODE-ID of the node that being is reading
from or writing to (NODE-ID is the id of SDO server). A SDO server will respond using
a COB-ID of 0x600 + NODE-ID (its own NODE-ID).
There are 3 types of SDOs; expedited, segmented, and block. CANopen libraries can determine the best SDO type based off of the value’s data type.
Expedited is for message with data type of equal to or less than 4-bytes. Only one request message is sent, and one ACK/NACK like message is returned. On a write, the last 4-bytes of the request are the value being written. On a read, the last 4-bytes of the response are the value (if no error).
Segmented is for message with data type of greater than 4-bytes. More than one request message is sent. On every request message, an response message is sent back. This is useful for larger data types like int64, uint64, float64, etc. Is consider the default SDO transaction type.
Block is for large block data (typically for a DOMAIN data type). Data is sent in block of 127 message and then a CRC is applied to the block, if the block is valid the next block is sent. For bulk data transfers, block type transfers are way more efficient than a Segmented type transfer; One ACK every 127 message vs on every message.
Example expedited SDO download from node 0x10 from index 0x1018 subindex 0x00.
$ candump vcan0
vcan0 610 [8] 40 18 10 00 00 00 00 00
vcan0 590 [8] 4F 18 10 00 04 00 00 00
Note
On OreSat, only the C3 will act as the SDO client and all other nodes are SDO servers. Expedited SDOs are used by the C3 to command and control all other nodes. Block SDOs are used for file transfers.
PDO (Process Data Object)
PDOs are producer / consumer type message. Any node can produce or consume PDO, if configured.
There are two type of PDOs: TPDO (Transmit PDO) and RPDO (Receive PDO). A node can produce data using TPDO and consume data using RPDO.
All PDOs are 1 to 8-byte message of mapped data from/to the OD.
Both RPDO and TPDO can be set up to be sent out every X SYNC message or on a timer.
All nodes get 4 TPDOs and RPDOs by default, TPDO COB-ID are
0x180 + NODE-ID, 0x280 + NODE-ID, 0x380 + NODE-ID,
0x480 + NODE-ID. RPDO COB-ID are 0x200 + NODE-ID,
0x300 + NODE-ID, 0x400 + NODE-ID, 0x500 + NODE-ID.
So a board with NODE-ID 0x04 can use the following 4 COB-ID for it’s TPDOs:
0x184, 0x284, 0x384, 0x484 and 4 COB-ID for it’s RPDOs:
0x204, 0x304, 0x404, 0x504.
Example TPDOs from node 0x10
$ candump vcan0
vcan0 190 [6] 2D 17 1B 00 00 00
vcan0 290 [2] 00 00
Note
On OreSat, the C3 will consume all TPDOs, all other nodes will produce and/or consume TPDOs as needed. All beacon data will be sent to the C3 via TPDOs.
Note
As mention in the Node section above. All nodes on OreSat use a NODE-ID with a
multiple of 0x04.
This is done as 4 TPDOs (a total of 64 bytes of data) is not enough for OreSat Nodes. So PSAS decided to give all nodes 4 times the normal PDOs. So a OreSat CANopen node now has 256 bytes for telemetry.
All nodes they use the PDOs of +1, +2, +3 to their NODE-IDs with a exception
of the C3, which only has PDOs of +1, +2 of it’s NODE-ID.
An example of board with NODE-ID of 0x04:
No nodes with
NODE-IDof0x05,0x06,0x07will exist on OreSat.Can use the following 16 TPDOs:
0x184,0x284,0x384,0x484,0x185,0x285,0x385,0x485,0x186,0x286,0x386,0x486,0x187,0x287,0x387, and0x487.Can use the following 16 RPDOs:
0x204,0x304,0x404,0x504,0x205,0x305,0x405,0x505,0x206,0x306,0x406,0x506,0x207,0x307,0x407, and0x507.
SYNC
A message that TPDO can be configure to response to after every X occurrences.
A SYNC message always has COB-ID of 0x80 with no payload.
Example SYNC message
$ candump vcan0
vcan0 080 [0]
Note
On OreSat, the C3 is the SYNC producer, all other nodes are consumers.
EMCY (Emergency)
An error message from the node. Useful for diagnostic.
A EMCY message has a COB-ID of 0x80 + NODE-ID.
Name |
Bytes |
Description |
|---|---|---|
EEC |
2 |
Emergency error code, a classification of the error |
ER |
1 |
Error register, value from index |
MSEF |
5 |
Manufacturer-specific error code, defined by PSAS |
Example EMCYs from node 0x10
$ candump vcan0
vcan0 090 [8] 00 01 01 01 02 03 04 05
vcan0 090 [8] 00 22 05 12 34 56 78 90
Note
On OreSat, the C3 is the EMCY consumer, all nodes (including the C3) are EMCY producers.
Time Sync
Warning
This is not CANopen standard, but is used on OreSat.
The time sync message on OreSat uses the SCET format with the Unix timestamp as the epoch. SCET is from the ECSS CANbus extension protocol standard.
ECSS SCET Definition
struct {
unsigned 32 Coarse Time
unsigned 24 Fine Time (sub seconds)
} scet
On OreSat the SCET value is a uint64 with Coarse Time first 4 bytes, followed by the Fine Time 3 bytes, and the final byte is padding.
Time Syncing
Time syncing is handle by the C3 and the GPS board. The TPDO with COB-ID of
0x181 is reserved to be the Time Sync TPDO. Both the C3 and GPS board can
send it. All nodes that care about time, except the node that sent the Time
Sync TPDO, will sync their clocks to the time in the Time Sync TPDO when it is
received.
The C3 has an RTC (Real Time Clock) and the GPS board has a GPS receiver and will set it’s system time to the GPS time in GPS messages.
The GPS board will only send the Time Sync TPDO, if has sync it’s system time to GPS time and it receives a SYNC message from the C3. So, either way the C3 has full control when all clocks are synchronized. The C3 can just send out the Time Sync TPDO (it will use the time from it’s RTC) or request it from the GPS board, if the GPS board is on.
Software Utilities
The CANopen Monitor project can be used to monitor the decoded CANopen
messages over a CAN bus. It is a TUI that displays the decode values, so you do
not have to convert the raw hex values from candump to their “real” values.
Also, candump is great at quickly testing a node or two, but can easily
become impossible to read once several node start sending data across the CAN
bus or when a large block data transfer is in progress, so CANopen Monitor
becomes more reasonable for viewing CANopen messages on the CAN bus.