-
Notifications
You must be signed in to change notification settings - Fork 1.5k
/
can-protocol.rst
174 lines (130 loc) · 6.11 KB
/
can-protocol.rst
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
.. _can-protocol:
================================================================================
CAN Protocol
================================================================================
.. contents::
:depth: 1
:local:
This document describes the CAN Protocol. For examples of usage, check out our :ref:`CAN Guide! <can-guide>`
Configuring ODrive for CAN
--------------------------------------------------------------------------------
Configuration of the CAN parameters should be done via USB before putting the device on the bus.
To set the desired baud rate, use :code:`<odrv>.can.config.baud_rate = <value>`.
Each axis looks like a separate node on the bus.
Thus, they both have the two properties :code:`can_node_id` and :code:`can_node_id_extended`.
The node ID can be from 0 to 63 (0x3F) inclusive, or, if extended CAN IDs are used, from 0 to 16777215 (0xFFFFFF).
If you want to connect more than one ODrive on a CAN bus, you must set different node IDs for the second ODrive or they will conflict and crash the bus.
Example Configuration
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: iPython
odrv0.axis0.config.can.node_id = 3
odrv0.axis1.config.can.node_id = 1
odrv0.can.config.baud_rate = 500000
odrv0.save_configuration()
odrv0.reboot()
Transport Protocol
--------------------------------------------------------------------------------
We've implemented a very basic CAN protocol that we call "CAN Simple" to get users going with ODrive.
This protocol is sufficiently abstracted that it is straightforward to add other protocols such as CANOpen, J1939, or Fibre over ISO-TP in the future.
Unfortunately, implementing those protocols is a lot of work, and we wanted to give users a way to control ODrive's basic functions via CAN sooner rather than later.
CAN Frame
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
At its most basic, the CAN Simple frame looks like this:
* Upper 6 bits - Node ID - max 0x3F (or 0xFFFFFF when using extended CAN IDs)
* Lower 5 bits - Command ID - max 0x1F
To understand how the Node ID and Command ID interact, let's look at an example
The 11-bit Arbitration ID is setup as follows:
:code:`can_id = axis_id << 5 | cmd_id`
For example, an Axis ID of :code:`0x01` with a command of :code:`0x0C` would be result in :code:`0x2C`:
:code:`0x01 << 5 | 0x0C = 0x2C`
Messages
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`Download CAN Messages as csv <./_static/can-protocol.csv>`_.
.. csv-table:: CAN Messages
:file: _static/can-protocol.csv
:header-rows: 1
.. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
All multibyte values are little endian (aka Intel format, aka least significant byte first).
.. note::
* These messages are call & response. The Master node sends a message with the RTR bit set, and the axis responds with the same ID and specified payload.
* These CANOpen messages are reserved to avoid bus collisions with CANOpen devices. They are not used by CAN Simple.
* These messages can be sent to either address on a given ODrive board.
* You must send a valid GPIO pin number in the first byte to recieve coreect ADC voltage feedback. Since you're both sending and receiving data the RTR bit must be set to false.
Cyclic Messages
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Cyclic messages are sent by ODrive on a timer without a request. As of firmware verion `0.5.4`, the Cyclic messsages are:
.. list-table::
:widths: 25 25 25 50
:header-rows: 1
* - ID
- Name
- Config Variable
- Default Rate (ms)
* - 0x01
- Heartbeat
- `heartbeat_rate_ms`
- 100
* - 0x09
- Get Encoder Estimates
- `encoder_rate_ms`
- 10
* - 0x03
- Get Motor Error
- `motor_error_rate_ms`
- 0
* - 0x04
- Get Encoder Error
- `encoder_error_rate_ms`
- 0
* - 0x1D
- Get Controller Error
- `controller_error_rate_ms`
- 0
* - 0x05
- Get Sensorless Error
- `sensorless_error_rate_ms`
- 0
* - 0x0A
- Get Encoder Count
- `encoder_count_rate_ms`
- 0
* - 0x14
- Get Iq
- `iq_rate_ms`
- 0
* - 0x15
- Get Sensorless Estimates
- `sensorless_rate_ms`
- 0
* - 0x17
- Get Bus Voltage Current
- `bus_vi_rate_ms`
- 0
.. ID | Name | Rate (ms)
.. --: | :-- | :--
.. 0x001 | ODrive Heartbeat Message | 100
.. 0x009 | Encoder Estimates | 10
.. Command ID | Message Name
.. :-- | :-- | :--
.. 0x01 | `heartbeat_rate_ms` | Heartbeat
.. 0x09 | `encoder_rate_ms` | Get Encoder Estimates
.. 0x03 | `motor_error_rate_ms` | Get Motor Error
.. 0x04 | `encoder_error_rate_ms` | Get Encoder Error
.. 0x1D | `controller_error_rate_ms` | Get Controller Error
.. 0x05 | `sensorless_error_rate_ms` | Get Sensorless Error
.. 0x0A | `encoder_count_rate_ms` | Get Encoder Count
.. 0x14 | `iq_rate_ms` | Get Iq
.. 0x15 | `sensorless_rate_ms` | Get Sensorless Estimates
.. 0x17 | `bus_vi_rate_ms` | Get Bus Voltage Current
These can be configured for each axis, see e.g. :code:`axis.config.can`.
Interoperability with CANopen
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can deconflict with CANopen like this:
* :code:`odrv0.axis0.config.can.node_id = 0x010` - Reserves messages 0x200 through 0x21F
* :code:`odrv0.axis1.config.can.node_id = 0x018` - Reserves messages 0x300 through 0x31F
It may not be obvious, but this allows for some compatibility with CANOpen.
Although the address space 0x200 and 0x300 correspond to receive PDO base addresses, we can guarantee they will not conflict if all CANopen node IDs are >= 32. E.g.:
* CANopen nodeID = 35 = 0x23
* Receive PDO 0x200 + nodeID = 0x223, which does not conflict with the range [0x200 : 0x21F]
Be careful that you don't assign too many nodeIDs per PDO group. Four CAN Simple nodes (32*4) is all of the available address space of a single PDO.
If the bus is strictly ODrive CAN Simple nodes, a simple sequential Node ID assignment will work fine.