Type
CANopen
CAN in Automation
CANopen is a specific protocol built on top of CAN bus.
Connection String Options
Name |
Default Value |
Required |
Description |
|
Name |
CAN open |
|||
Code |
|
|||
Maven Dependency |
<dependency> <groupId>org.apache.plc4x</groupId> <artifactId>plc4j-driver-canopen</artifactId> <version>0.12.0</version> </dependency> |
|||
Default Transport |
|
|||
Supported Transports |
|
|||
Config options: |
||||
|
INT |
CAN node identifier. Depending on used CAN version it might be 11 or 29 bit unsigned int. |
||
|
BOOLEAN |
Forces PLC4X to send CANopen heartbeat (NMT) messages to the bus. |
||
|
INT |
1000 |
Time after which dispatched BUS operation (ie. SDO request) will be marked as failed. |
|
Transport config options: |
||||
socketcan |
Name |
Value |
Description |
Supported Operations |
||
CANopen PDO |
|
PDO messages are broadcasted to the bus and have to be mapped at application layer. |
CANopen SDO |
|
SDO are request/response conversations. Both read and write path is supported. |
|
|
More details on the driver
CAN, despite (or due) to its popularity has ambiguous meaning. There are multiple articles and sources which attempts to give introduction, yet very few of them is consistent between each other.
There are two dominant formats of frames - CAN 2.0A and 2.0B:
-
CAN 2.0A uses 11 bit identifier and up to 8 bytes of data.
-
CAN 2.0B uses 29 bit identifier and up to 8 bytes of data.
To make things worse with introduction of CAN FD amount of combinations increased even more. Double check frame format as this integration supports CANopen and does not support CANopen FD nor CAN 2.0B.
Further reading on CAN flavors: https://en.wikipedia.org/wiki/CAN_bus
Default transport used with this protocol is socketcan. Currently, only 2.0A format (up to 8 bytes of data) is supported.
Implemented driver supports currently socketcan transport. Change of transport requires code modifications and injection of new "transport" type which will encode CANopen payloads to specific frame format.
Socketcan seems to be most widespread way to access CAN bus. It also masks different hardware variants which might come with their own drivers.
The CANopen specification defines Object Dictionary (OD). This driver does honor OD structure through usage of index and sub index for addressing fields. It does not ship Electronic Data Sheet (EDS) parser leaving it for applications who wish to utilize it.
Address Format
CANopen specification defines several groups of addresses dedicated to certain kind of operations. Critical services and message exchanges related with them have lower identifiers making them wining eventual bus access.
The array size block is necessary only if application expect same value several times.
If SDO returns for example 4 values of UNSIGNED8 it can be declared as <service>:<nodeId>:UNSIGNED8[4]
for PDO.
Equivalent for SDO is <service>:<nodeId>:<index>/<subindex>:UNSIGNED8[4]
.
Service | Format | Supported operations | Description |
---|---|---|---|
SDO |
SDO:nodeId:index/subindex:type[arraySize] |
|
SDO is for request/response communication. Both expedited and segmented modes are supported. No support for block transfer. Transfer kind is automatically determined based on payload length.
All numeric values - ndodeId, index, subindex can be specified using hexadecimal notation (ie. |
PDO |
|
|
PDO is an asynchronous operation hence receiving of it requires subscription. Check Apache PLC4X API documentation for more detailed example of how to use subscriptions API. Subscriber will be notified with value mapped to type defined in field syntax. |
NMT |
|
|
NMT messages are sent using CAN node ID Subscriptions to this service receive structure with two fields: |
HEARTBEAT |
|
|
HEARTBEAT messages have the lowest priority on the bus. They have the highest priority on the bus. Messages of this kind indicate operating state of an node (booted, operational). Subscriptions to this service receive structure with two fields: |
Below table contains type mapping defined in CANopen specification.
CANopen Type |
Length (in bits) |
PLC4X Type |
BOOLEAN |
1 |
BOOL |
UNSIGNED8 |
8 |
USINT |
UNSIGNED16 |
16 |
UINT |
UNSIGNED24 |
24 |
UDINT |
UNSIGNED32 |
32 |
UDINT |
UNSIGNED40 |
40 |
ULINT |
UNSIGNED48 |
48 |
ULINT |
UNSIGNED56 |
56 |
ULINT |
UNSIGNED64 |
64 |
ULINT |
INTEGER8 |
8 |
SINT |
INTEGER16 |
16 |
INT |
INTEGER24 |
24 |
DINT |
INTEGER32 |
32 |
DINT |
INTEGER40 |
40 |
LINT |
INTEGER48 |
48 |
LINT |
INTEGER56 |
56 |
LINT |
INTEGER64 |
64 |
LINT |
REAL32 |
32 |
REAL |
REAL64 |
64 |
LREAL |
RECORD |
8 * size |
BYTE |
OCTET_STRING |
8 * size |
STRING (UTF-8) |
VISIBLE_STRING |
8 * size |
STRING (UTF-8) |
TIME_OF_DAY |
unsupported |
|
TIME_DIFFERENCE |
unsupported |
|
UNICODE_STRING |
8 * size |
STRING (UTF-8) |
All string types are decoded using UTF-8 encoding regardless of their kind (octet, visible, unicode).
In case if device returns text using different encoding it is recommended to use RECORD
type and construct text manually above PLC4X.
The size in case of variable length structures is automatically assumed to full length of SDO answer.
In case of writing length of field can be ommited.
For example request write(SDO:1:2/3:RECORD, payload)
will try to write whole payload to specified address.
Same applies to responses sent by devies as requester often might not know full length of reply payload.