Zum Hauptinhalt springen

CANopen-Treiber

Überblick

CANopen — Application Layer nach EN 50325-4 / CiA 301 auf dem CAN-Bus (verbreitet bei Motorantrieben, Encodern und IO-Modulen). Native Neuimplementierung 2026-07 — die frühere Delegation an Apache PLC4j canopen wurde entfernt (PLC4X CANopen unterstützt nur den lokalen SocketCAN-Transport und lässt sich nicht über TCP transportieren; auf Edge-Systemen ohne physischen CAN-Bus schlug connect deshalb fehl). Verwendet wird nun eine eigene SDO-Expedited-Upload-Implementierung in plantpulse-plc-protocol (CanopenSdoClient) plus Transport-Abstraktion (CanTransport) — dasselbe native Muster wie bei AB-ETH / BACnet.

PunktWert
opc_typeCANOPEN
Implementierungsklasseplantpulse.driver.protocol.canopen.CANOpenDriver
Bibliothekeigene native Implementierung (canopen aus plantpulse-plc-protocol — SDO Expedited Upload)
VererbungBaseProtocolDriver (nicht PLC4j)
getProtocol()"canopen:tcp" (alte PLC4X-Schema-Notation beibehalten — Kompatibilität für Logs/Diagnose)
Standardport20200 (CAN-over-TCP-Gateway)
Statusstabil (SDO-Expedited-Polling)
readOK (SDO Expedited Upload, Werte ≤ 4 Byte)
write❌ (nur lesend — SDO Download nicht implementiert)
Sicherheitkeine
Voraussetzung: CAN-over-TCP-Gateway

Der Standardtransport (tcp) kommuniziert mit CANopen-Knoten jenseits eines CAN-↔-TCP-Gateways. CAN-Frames werden mit einem eigenen Binär-Framing von canId(4B BE) + dlc(1B) + data[dlc] über TCP übertragen (kein Handshake, keine Busnamen-Aushandlung — identisches Framing wie im Simulator). transport=socketcan (lokales can0) ist derzeit ein Stub (erfordert native AF_CAN-Bindung/JNI), daher schlägt connect fehl — der Zweig für physische CAN-Schnittstellen folgt später.


Klassenstruktur

BaseProtocolDriver
└── CANOpenDriver — connect() 에서 CanTransport(tcp/socketcan) + CanopenSdoClient 생성

Bei fehlgeschlagenem read (Abort/Timeout/Socket) wird der Socket invalidiert (connected=false + close), damit der Edge einen Neuaufbau der Verbindung auslöst.


Zusammenfassung des Wire-Formats (Eigenimplementierung — SDO Expedited Upload)

  • Anfrage: COB-ID 0x600+nodeId, data [0x40, index LE(2B), subindex, 0×4].
  • Antwort: COB-ID 0x580+nodeId, command 0x43 (4B) / 0x47 (3B) / 0x4B (2B) / 0x4F (1B) — Wert little-endian. 0x80 = Abort (Code u32 LE) → Kommunikationsausnahme.
  • Segmented / Block Transfer nicht unterstützt (Werte > 4B, z. B. lange Strings) — für das Polling skalarer Tags genügt Expedited.

OPC-Registrierungsoptionen

FeldBedeutungStandard
opc_agent_ipIP des CAN-TCP-Gateways192.168.1.20
opc_agent_portTCP-Port des Gateways20200
options.read-timeoutSDO-Antwort-Timeout (ms)3000
options.transporttcp / socketcan (Stub)tcp
options.can-interfaceSchnittstellenname im socketcan-Moduscan0
Alte PLC4X-Optionen entfernt

Die Option node-id aus alten Formularen/Dokumenten entfällt — die Node-ID ist jetzt das erste Feld der Tag-Adresse (siehe unten). Auch die Optionen request-timeout/heartbeat werden von der nativen Implementierung nicht akzeptiert (Timeout über read-timeout).


Format von Tag plc_address (neuer Vertrag)

<nodeId>:<index>:<subindex>[:<TYPE>]
FeldBedeutungNotation
nodeIdCANopen-Node-ID (1..127)dezimal
indexObjektverzeichnis-Index (0..0xFFFF)hexadezimal mit Präfix 0x (0x6041) oder dezimal
subindexSubindex (0..255)hexadezimal mit Präfix 0x oder dezimal
TYPE (optional)Typ für die LE-Byte-Interpretationbei Auslassung Ableitung aus data_type → andernfalls UINT16
NotationBedeutung
1:0x6041:0:UINT16Knoten 1, DS402 Statusword
3:0x2000:0:REALKnoten 3, float32 im herstellerspezifischen Bereich
1:0x6064:0:INT32Position actual value (32 Bit signed)
5:8192:1Knoten 5, Index dezimal 8192 (= 0x2000), TYPE weggelassen → UINT16

TYPE-Token (inkl. Aliasen)

Token (Alias)GrößeInterpretation
BOOL (BOOLEAN)1ungleich 0 bedeutet true
UINT8 (U8, USINT, BYTE) / INT8 (I8, SINT)1u8 / i8
UINT16 (U16, UINT, WORD) / INT16 (I16, INT)2u16 / i16 (Standard UINT16)
UINT32 (U32, UDINT, DWORD) / INT32 (I32, DINT)4u32 / i32
REAL (FLOAT, F32, REAL32)4IEEE-754 float (LE)
STRING (STR, VISIBLE_STRING)≤4ASCII (abschließende NUL entfernt)

Bei weggelassenem TYPE Ableitung aus data_type: Boolean→BOOL, Integer→INT16, Long→INT32, Float→REAL, Double→REAL (Näherung auf 4B), String→STRING.


Unterstützt / nicht unterstützt

  • read: SDO Expedited Upload (≤ 4 Byte) — OK.
  • write: nicht unterstütztisWriteSupported() = false und write() liefern immer false. (SDO Download folgt.)
  • Segmented / Block SDO, PDO-Mapping, NMT-/Heartbeat-Überwachung, SYNC, EMCY, LSS: nicht unterstützt.
  • Direktes SocketCAN / USB-CAN: Stub (CAN-over-TCP-Gateway vorausgesetzt).

curl-Registrierungsbeispiel

curl -X POST http://<edge-host>/api/v1/opc \
-H "Content-Type: application/json" \
-d '{
"opc_id": "OPC_CANOPEN_DRIVE1",
"opc_type": "CANOPEN",
"opc_name": "Servo Drive 1",
"opc_agent_ip": "192.168.1.20",
"opc_agent_port": "20200",
"site_id": "SITE_00001",
"auto_collect": true,
"timecycle": 1000,
"options": { "read-timeout": "3000" },
"tag_list": [
{"tag_id":"OPC_CANOPEN_DRIVE1_T01","tag_name":"Statusword","plc_address":"1:0x6041:0:UINT16","data_type":"Integer"},
{"tag_id":"OPC_CANOPEN_DRIVE1_T02","tag_name":"ActualPos","plc_address":"1:0x6064:0:INT32","data_type":"Long"}
]
}'

Hinweise

  • Standards CiA 301 (Application Layer) / CiA 402 (Drives).
  • Code: Paket canopen in plantpulse-edge-driver/src/plantpulse/driver/protocol/canopen/CANOpenDriver.java + plantpulse-plc-protocol.
  • Betrieb: Das Gateway-Framing ist ein eigenes Binärformat (canId+dlc+data) — es unterscheidet sich vom Textprotokoll socketcand. Es wird empfohlen, die Adressen anhand der EDS-Datei des Geräts zu verifizieren.