09.07.2022

CanOpen - Tips und Tricks

CanOpen ist ein standardisiertes Protokoll, dass auf einem CAN-Bus implementiert ist. Andere Protokolle sind beispielsweise NMEA2000 und JS1939 oder auch nur pure CAN. Der CAN-Bus ist heutzutage sehr verbreitet und nach wie vor ein sehr zuverlässiger Bus im industriellen Umfeld. Die größte Flexibilität bei gleichzeitig sinnvollem Bedienkomfort im Vergleich mit den anderen Protokollen bietet CanOpen. Daher habe ich mich für Sensoren entschieden, die über den CanOpen-Standard kommunizieren.

Bei CanOpen hat jeder Knoten eine eindeutige CAN-Bus-Adresse (ID), die aber gleichzeitig auch dazu dient, die Adressen der Datentelegramme (die sog. COB-IDs) festzulegen. Die ID kann im Bereich von 0 bis 64 oder bis 127 liegen, je nachdem, was die Steuerung zulässt. Dabei muss jede ID eindeutig sein. Das einfachste Verfahren die Sensoren auf die gewünschte ID und Baudrate einzustellen ist per DIP-Switches. Nur leider haben die meisten Sensoren keine, sondern werden über den CAN-Bus entweder per LSS-Service der Steuerung oder manchmal auch mit Hilfe von individuellen SDOs (Service Daten Objekte) eingestellt. Die LSS-Variante ist das offizielle Verfahren gemäß CanOpen-Stanbdard
Interessanterweise scheinen manche Sensoren nicht über so viel Intelligenz zu verfügen, dass sie die COB-IDs automatisch anpassen, wenn die ID geändert wird. Die Standard-ID, auf die der Sensor werksseitig eingestellt wurde, darf auf dem Bus nicht existieren, wenn man den Sensor konfigurieren möchte. Darüber hinaus müssen alle Sensoren mit derselben Baudrate laufen. Moderne Sensoren lauschen an dem existierenden Bus und stellen die Baudrate selbst ein.

Die Einbindung der Kübler CANOpen Absolutpositionsgeber, die ich zum Bestimmen der Drehwinkel der Pods einsetze, erwies sich genau aus dem Grund, dass die COB-IDs bei einer ID-Änderung nicht angepasst werden (weder per LSS- noch per SDO-Einstellung), als ein wenig hartnäckig. Bei Kübler geht das einstellen von Baudrate bzw. ID auch über die speziellen SDO-Objekte 0x2100 bzw. 0x2101, indem man einfach den gewünschten Wert in das entsprechende Objekt schreibt. Dadurch war es möglich, die Unstimmigkeiten zu beheben. Natürlich muss die Baudrate zunächst an der Steuerung auf den Standardwert des Sensors eingestellt werden, da sonst gar keine Kommunikation möglich ist (und muss dann auch in der Steuerung geändert, wenn sie im Sensor geändert wurde). Die Änderungen werden erst nach einem Reset des Sensor aktiviert. Deshalb müssen die Werte vorher dauerhaft im Sensor gespeichert werden. Dies geschieht bei dem Kübler Drehsensor über den spezifischen Parameter 0x2105, in den man den Wert 0x65766173 schreiben muss (das sind die Hex-Werte der ASCII-Codes für das Wort "save").

Das manuelle Einstellen der COB-IDs per SDO ist bei allen Sensoren grundsätzlich möglich. Dazu muss man die entsprechende COB-ID aber zunächst ungültig setzen, da sonst keine Änderungen möglich sind (Fehlermeldung). Das ungültig Setzen erfolgt, indem man die aktuelle Adresse in das entsprechende COB-ID-SDO (0x1800sub1, 0x1800sub2, 0x1800sub3 oder 0x1800sub4) mit gesetztem Bit 31 schreibt, hexadezimal also beispielsweise 0x800018A für die COB-ID des ersten Prozessdatenobjekts (PDO) in das SDO 0x1800sub1, wenn die Knoten-ID 10 (0x0A) ist. Nun kann man die neue COB-ID, die sich immer aus der Basisadresse 0x180, 0x280 , 0x380 oder 0x480 zuzüglich der Knoten-ID (also z.B. 0x180 + 0x0A) zusammensetzt, in das entsprechende SDO (z.B. 0x1800sub1) schreiben. Den Vorgang muss man ein zweites Mal ausführen, um das PDO wieder zu aktivieren. Auch hier müssen die Werte dauerhaft im Sensor gespeichert werden, was standardmäßig über das SDO 0x1010 erfolgt. SDO 0x1010sub1 benutzt man beispielsweise zum Speichern aller Parameter. Auch hier (0x1010sub1 )muss man den Wert 0x65766173 hineinschreiben. Nach diesen manuellen Anpassungen funktionieren die Sensoren von Kübler so wie sie sollen.

Viele moderne Sensoren erlauben es, dynamisch, also durch den Benutzer, zu definieren, welche Sensorwerte auf welchen Sendekanälen (TPDOs) bzw. Empfangskanälen (RPDOs) übertragen werden (PDO ist der Oberbegriff dazu). Hersteller freuen sich immer, dem Benutzer ein passendes CAN-USB-Interface zusätzlich zu verkaufen, damit man dann den Sensor mit einem, wenn man Glück hat kostenlosen, Konfigurationstool konfigurieren kann, das natürlich nur mit dem herstellerspezifischen CAN-USB-Interface zusammenarbeitet. Dies ist aber nicht erforderlich, da jede bessere Steuerung ein allgemeines Tool mitliefert, mit dem man auf die SDOs (Service Data Object) die der Sensor liefert, zugreifen kann. Man muss der Steuerung per eds-Datei bekannt machen, welche SDOs das Gerät (z.B. der Sensor) beherrscht. Dann kann man über die SDO-Objekte alle übertragungsrelevanten Parameter konfigurieren. Das Ganze ist etwas mühsamer als mit spezifischen Tools, aber man muss das in der Regel ja auch nur einmal pro Sensor machen, was bei 30 bis 50 Sensoren mit etwas Übung kein Problem sein sollte, zumal man sich sonst ja mit 10 verschiedenen herstellerspezifischen Tools amüsieren darf, die den Vorgang zu sehr unterschiedlichen Graden automatisieren (wenn das Tool z.B. nur SDO-Zugriff erlaubt, ist die Arbeit dieselbe wie ohne das Tool).

In jedem CANOpen-Gerät gibt es vier TPDOs à 8 Bytes und vier RPDOs à 8 Bytes. Das Mapping bestimmt also, welcher interner Sensorwert aus dem Objektverzeichnis (einer Liste aller verfügbarer Werte) auf welchen der maximal 4 x 8 Byte der TPDOs/TPDOs gesendet bzw. empfangen werden. Eine korrespondierende eds-Datei (Electronic Data Sheet) teilt der Steuerung neben den Konfigurationsparametern mit, welche Einträge (also mögliche Sensordaten) es im Objektverzeichnis (OD = Object Directory) gibt, die man mappen kann. Natürlich sind ein paar Sicherheitsmaßnahmen implementiert, damit man die Werte nicht aus Versehen ändern kann. Grundsätzlich ist das Mapping für die RPDOs in den SDOs 0x1600 bis 0x17FF und für die TPDOs in den SDOs 0x1A00 bis 0x1BFF zu finden. An jeder dieser Adressen verbirgt sich ein Array mit einem Zählwert und normalerweise acht weiteren Einträgen für die Mappings. Allerdings kann die Zahl der Einträge auch bis zu 64 sein, wenn man ein bitweises Mapping zulässt, was aber die Ausnahme ist. Der Zählwert (nullter Eintrag, also z.B. 0x1A00sub0 oder oft auch geschrieben als 0x1A00,0x00 (Adresse (Index)) gibt die Anzahl der gültigen weiteren Einträge an. Jeder der Einträge ist ein UNSIGNED32-Wert, der nach dem folgenden Schema aufgebaut ist:

  • Bits 16-31: Adresse des zu mappenden Eintrags im Objektverzeichnis (Die Adressen liegen meist im Bereich 0x3000 oder für sensor-spezifische Werte im Bereich 0x6000)
  • Bits 8-15: Sub-Index des Wertes an der angegebenen Adresse (da auch hier an jeder Adresse ein Array liegen kann)
  • Bits 0-7: Anzahl der Bits des zu übertragenden Wertes (also für 1 Byte wäre das der Wert 8)

Eine gute Idee ist es, in einem EDS-Editor (z.B. dem Open Source Editor OpenEDSEditor) das Mapping anzulegen, bevor man die Werte auf dem Sensor ändert. Aus dem Editor kann man sich die dort automatisch generierten richtigen Adresseinträge (die UNSIGNED32) herauskopieren, was Fehler vermeidet.

So, nun wissen wir, wie die Datenstrukturen aufgebaut sind, aber wie ändert man die? Um also das Mapping von Sensordaten zu ändern, müssen folgende Schritte ausgeführt werden:

  1. PDO deaktivieren
    Ein PDO wird deaktivert, indem man in der COB-ID (z.B. Adresse 0x1800sub1) das Bit 31 setzt, also hat der Sensor beispielsweise die ID 10 (0xA) wäre die gültige COB-ID 0x18A. Soll sie nun deaktiviert werden, muss man die COB-ID auf 0x800018A sestzen.
  2. TPDO bzw. RPDO mapping deaktivieren
    Dies geschieht, indem man den Zählwert des entsprechenden TPDO/RPDO auf Null setzt, also zum Beispiel 0x1A00sub0 wird auf Null gesetzt.
    Erst nach den Schritten 1. und 2. kann man die eigentlichen Einträge ändern. Ansonsten bekommt man eine Fehlermeldung.
  3. TPDO bzw. RPDO Einträge setzen
    Nun schreibt man per SDO die Einträge, die dem gewünschten Mapping entsprechen, also zum Beispiel um eine Sendeobjekt zu definieren:
    0x1A00sub1 (Mapping Entry 1) = 0x31010110 legt fest, dass der Wert an Adresse 0x3101, subindex 0x01 mit einer Länge von 16-Bit (0x10) übertragen werden soll.
    So geht man mit allen Änderungen vor. Ungenutzte Einträge enthalten automatisch den Wert 0x00 (Null).
  4. Gültige Anzahl der Einträge setzen
    Ist man mit einem TPDO/RPDO mapping fertig, dann muss man noch die Anzahl der gültigen Einträge setzen. In unserem Beispiel wäre das 0x1A00sub0 = 0x1 (ein gültiger Eintrag)
  5. PDO re-aktivieren
    Jetzt noch das PDO re-aktivieren, im dem man die COB-ID ohne Bit 31 schreibt (wie Schritt 1 aber ohne 0x8000___)
  6. Speichern aller Werte
    Damit nicht alles ohne dauerhaft Wirkung bleibt, müssen die Werte alle gespeichert werden. Normalerweise ist 0x1010sub1 (save all) die richtige Adresse dafür (man kann auch spezifisch nur die Kommunikationsparameter speichern). Zum Speichern muss man in die Adresse 0x1010sub1 den Wert save als Hexdezimalzahl speichern, was dem Wert 0x65766173 entspricht.
  7. EDS-Datei auf der Steuerung austauschen
    Sensor aus der Konfiguration löschen und neu anlegen, um die neue EDS-Datei mit dem Sensor zu verbinden.

Das Ganze ist eine ziemliche Byte-Schieberei, aber wenn man es ein paar Mal gemacht hat, ist es recht einfach.

Ein Frage, die ich mir auch gestellte habe ist, welche Art der Datenübertragung die Richtige ist. CanOpen bietet synchrone, asynchrone und Event basierte Übertragung an. Grundsätzlich sollte man sich überlegen, welche Werte man tatsächlich für die Steuerung benötigt und alle anderen ungültig machen (COB-ID mit 0x8000___), um Bandbreite auf dem CAN-Bus zu sparen. Beleibt die Frage, ob man synchrone, asynchrone und Event basierte Übertragung wählen sollte. Diese Formulierung ist eigentlich falsch, weil der CAN-Bus ein serieller Bus ist, der gar keine synchrone Datenübertragung kann. Synchron bedeutet daher auf dem CAN-Bus, dass normalerweise der Busmaster ein SYNC Signal auf den Bus schreibt. Alle Sensoren, die auf Synchronbetrieb eingestellt sind, frieren nun zeitgleich ihren jeweils aktuellen Wert ein und senden ihn dann je nach Priorität an die Steuerung. So wird sichergestellt, dass alle Sensorwerte zu einem definierten Zeitpunkt gehören. Dadurch vermeidet man, dass z.B. eine Bewegungsregelung durch Zeitabweichungen der Messwerte negativ beeinflusst wird (nennt man auf Neudeutsch „jitter“). Somit stellt sich die Frage für alle Bewegungsregelungen nicht. Bei allen anderen Steuerungen kann man wählen, was man will, wenn die Vorgänge langsam genug sind. Aber Achtung: Event-basiert ist mit Sicherheit nicht die datensparsamste Variante (und wird auch nicht von allen Sensoren beherrscht). Man muss unbedingt eine entsprechende „inhibit time“ setzen, sonst ist der Bus dicht, wenn der Sensor nur ein wenig „wackelt“.

Eingestellt wird die Übertragungsart über die Transmit PDO1 Kommunikationsparameter. Die Einträge findet man unter 0x1800, 0x1801, 0x1802 und 0x1803. In den dort angesiedelten Arrays findet sich auch die COB-ID in der folgenden Struktur:

0x1800sub0 höchster unterstützter Subindex (= Anzahl der Einträge in dem Array, Standardwert ist 5, nicht änderbar)
0x1800sub1 COB-ID Basisadresse 0x180 plus die Knoten-ID. Wenn man das PDO deaktivieren möchte, dann 0x80000180 plus Knoten-ID.
0x1800sub2 Übertragungstyp (synchron (Wert 1-240)/ asynchron-herstellerspezifisch (Wert 254))
0x1800sub3 Sperrzeit zwischen zwei TPDO-Nachrichten (Vielfache von 100 µs), Im Englischen „inhibit time“. Für Event-basierte Übertragung. Der Wert muss so hoch sein, dass nicht der ganze Bus zusammenbricht.
0x1800sub4 Nicht benutzt
0x1800sub5 Intervallzeit bei asynchroner/zyklischer Übertragung in Millisekunden (0 = aus)

Für das Ändern der Übertragungsparameter gilt dasselbe wie für das Ändern der COB-IDs, nähmlich, dass das entsprechende PDO vorher deaktiviert werden muss (COB-ID mit Bit 31 gesetzt).

Abbildung 1: IMU-Sensoren

IMU Sensoren mit CANOpen

Der IMU (Inertialsensor) mit GPS von LP-Research (LPMS-IG1P), der in Deutschland von der Firma Nexonar vertrieben wird, scheint nicht CanOpen kompatibel zu sein, was bei einem Sensor, der dies verspricht und 700-800€ kostet, nicht akzeptabel ist. Darüber hinaus liefert die Firma nicht einmal eine korrekte eds-Datei für einen Satz Standardeinstellungen aus, was auch nicht akzeptabel ist. Der Sensor wird auf einem mit CANOpen betriebenen CAN-Bus bei einem CAN-Bus-Scan nicht erkannt. Mit Hilfe eines CAN-USB-Adapters war am PC zu erkennen, dass die ID des Sensor angefragt wird, aber keine korrekte Rückmeldung hinsichtlich CanOpen erfolgte. Als Sahnehäubchen teilte man mir auf Nachfrage mit, dass die GPS-Daten, die der Sensor theoretisch liefern kann, nicht auf den CAN-Bus gemappt werden können... Auch mit dem aktuellsten Firmware-Update hat sich der Sensor nicht als CANOpen-Sensor ansprechen lassen. Das heißt für mich im Klartext, dass ich mehr als 700 Euro in die Mülltone werfen kann. Mein Fazit: Finger weg von LP-Research und Finger weg von Nexonar. Keiner von beiden scheint zu wissen, was er hinsichtlich CanOpen tut. Bei allen technischen Geräten, die ich bisher im Zusammenhang mit meinem Projekt erworben habe (und das sind ettliche, die deutlich komplexer sind als ein popeliger CANOpen-Sensor), bin ich kein anderes Mal so auf die Nase gefallen.

Ich habe jetzt eine andere IMU (weitere > 500€) von einer Firma GEMAC aus Chemnitz gekauft. Die Firma scheint technisch mehr Ahnung zu haben (jedenfalls hat deren Techniker die richtigen Antworten auf meine Fragen gegeben), aber wieso die nicht an eine Privatperson verkaufen wollen, erschließt sich mir nicht. Die gute Nachricht ist: Der Sensor von GEMAC funktioniert grundsätzlich. Es handelt sich dabei um einen 6-DOF-Sensor, also einen Sensor, der einen Gyroskopsensor und eine linearen Beschleunigungssensor aufweist. Im Gegensatz dazu ist der LPMS-IG1P ein 9-DOF-Sensor, der auch das Magnetfeld der Erde auswertet. Die Werte, die der GEMAC Sensor liefert erscheinen plausibel, so dass ich ihn jetzt noch in die Vektorsteuerung einbinden muss.