Hallo Experten,
Ich habe eine grundsätzliche Frage zur Arbitrierung des CAN-Bus
Protokolls.
Hier steht folgendes:
"Message IDs must be unique on a single CAN bus, otherwise two nodes
would continue transmission beyond the end of the arbitration field (ID)
causing an error."
http://en.wikipedia.org/wiki/CAN_bus
Das bedeutet für mich, dass "lediglich" die COB-ID für die Arbitrierung
verwendet wird, oder?
Nehmen wir mal an, 2 Clients (CANopen) versuchen gleichzeitig einen
SDO-Zugriff auf das OD (Channel 1) von Node 1.
Gleicher Index, gleicher Subindex, COB-ID ist sowieso gleich (601). Wie
klappt das dann ohne Kollision?
Wenn die Arbitrierung über das gesamte CAN-Frame läuft (bis auf den
letzten Teil / ACK, natürlich), dann sollte das ja kein Problem sein.
Wenn auch noch die gleichen Daten gesendet werden: Fein, keine
Kollision. Und beide Clients werten (die gleiche) positive Antwort aus.
Was ist nun aber, wenn alles gleich ist, bis auf die Daten?
Ich hoffe, ich konnte mein Problem verständlich erklären (und
hoffentlich kann mich einer von euch aufklären;)
Viele Grüße,
Dirk.
kann nicht vorkommen da jeder CAN-Knoden eine individuelle NodeID als
Alleinstellungsmerkmal haben MUSS.
Bei der Cob-ID entscheidet dann die NodeID welcher der beiden Knoten die
Bitarbitrierung gewinnt.
achso, ja ne, jetzt verstehe ich!
Die Bitarbitrierung ist nicht auf die CobID begrenzt! - in Deinem
beschriebenen Fall greift die Bitarbitrierung in den Nutzdatenbytes
;)
Die Antwort habe ich vor 2 Stunden auch schon von nem ehem. IXXAT
Mitarbeiter bekommen. Der Wiki-Artikel hat mich dann aber stutzig
gemacht, weil da eben "transmission beyond the end of the arbitration
field (ID) causing an error" steht.
Bei CAN reicht das ja aus, da definiere ich als "Systemdesigner" alle
COB-IDs, "wie's mir passt" und bin entsprechend dafür verantwortlich,
aber CANopen mit seinem SDO-Service an 600 + ID führt da bei mir eben
zum Verständnisproblem.
Jeffrey Lebowski schrieb:> in Deinem beschriebenen Fall greift die Bitarbitrierung in den> Nutzdatenbytes
Nein.
Es gibt z. B. Telegramme mit 11-Bit Identifier (CAN 2.0A). Die
Arbitrierung wird über 11 Bits durchgeführt. Die Bits sind (CANOpen)
aufgeteilt: 4 Bits sind der COB-ID, 7 Bits NODE-ID.
Sorry, ich hab's noch nicht kapiert.
Folgendes Szenario (wie ich es momentan verstehe):
Node ID 1 hat einen SDO-Server (Channel), dieser ist 0x600 + Node-ID =
0x601 (für Rx) und 0x580 + Node-ID = 0x581 (für Tx).
Ein weiterer Knoten mit ID 2 hat auch einen SDO-Server und zwar an
0x602/0x582.
Somit weiß jeder der Knoten 1 und 2 wann er (sein SDO-Service)
angesprochen wird.
Jetzt gibt es 2 Clients mit den IDs 3 und 4.
Beide Clients fangen nun gleichzeitig an, einen SDO-Request an Knoten 1
zu senden. Beide "konsultieren" COB-ID 0x601, die eigene Knoten-ID wird
im Anfrage-Telegramm ja nicht irgendwie "integriert" ...
Was passiert jetzt? Kollision oder nicht? Vertändnisfehler?
Viele Grüße,
Dirk, der Verwirrte ;)
Das knallt dann halt in den Daten, wenn diese unterschiedlich sind.
Wenn beide Nodes den selben Index/Subindex anfragen fällt es nicht
auf. Macht aber auch nix, weil ja beide die richtige Antwort bekommen.
Wenn sich die Datenbereiche unterscheiden gibt es entweder eine Form-
Fehler oder einen CRC Fehler,
Ja, das wäre der eine Fall (wobei ich nicht verstehe, warum du das vom
Index/Subindex abhängig machst, meiner Meinung nach kracht es schon,
wenn der Index sich unterscheidet, da die Arbitrierung nach den 11 Bit
COB-ID aufhört). Dagegen spricht aber, was ich bis jetzt beobachten, bzw
praktisch ausprobieren konnte:
Ich habe hier 2 Knoten, die einen Blocktransfer durchführen (2 PIC32,
einer mit einem Stack von Systec, der andere mit einem "selbst
gebastelten").
Wenn ich nun mit einem dritten Knoten (IXXAT CAN-Karte mit Software
"Canalyzer") an den "beschäftigten Server" einen SDO-Request schicke,
dann sehe ich keine Kollision. Der SDO-Request vom "Canalyzer" wird
ordentlich zwischen 2 Segmente vom Blocktransfer "dazwischengeschoben".
Die Arbitrierung scheint also irgendwie zu funktionieren...
Viele Grüße,
Dirk.
Hallo,
ich fasse das Szenario noch einmal zusammen:
Es gibt einen SDO-Server (Node-ID = 1), auf den zwei SDO-Clients (die
sich auf Knoten mit der Node-ID 3 und 4 befinden - die Node-ID der
Clients spielt übrigens keine Rolle) zugreifen.
1.) Client(3) und Client(4) senden den SDO-Request gleichzeitig.
Damit sind schon mal die CAN-Identifier der Request-Nachrichten.
1a.) Die Dateninhalte (Inhalte der übertragenen Datenbytes) der Requests
sind gleich (z.B. bei SDO-Lese-Zugriff auf den jeweils gleichen
Index/Sub-Index).
Ergebnis: Hier gibt es kein Problem. Der Server merkt nichts davon, dass
er zwei (überlagerte) Requests bekommen hat und antwortet entsprechend.
1b.) Die Dateninhalte (Inhalte der übertragenen Datenbytes) der Requests
sind unterschiedlich (z.B. SDO-Schreib-Zugriff mit unterschieldichen
Inhalten).
Ergebnis: Hier gibt es eine schöne Kollision (Bitfehler bei der
Übertragung der Datenbytes). Mit dem CANanalyzer kann man die einzelnen
Error Frames sehen. Zuguterletzt wird aber der Request dann doch
ausgesendet und der Server antwortet.
2.) Client(3) und Client(4) senden den SDO-Request nicht gleichzeitig.
Ergebnis: Hier erkennt der Server zwei SDO-Requests. Wenn die Requests
gepuffert (i.d.R. in einem Wechselpuffer oder direkt im CAN-Controller
oder auch in einer Software-Queue) werden und es sich um einen Expedited
Transfer (Segemented oder Block-Transfer würde gar nicht gehen. Da kämen
die SDO-Protokoll-Zustandsmaschinen völlig durcheinander) handelt, gibt
es wohl auch zwei SDO-Responses. Allerdings werden die SDO-Clients
(vermutlich) nur die erste Response entgegennehmen. Hier können viele,
schwer zu lokalisierende Probleme auftreten (da kann einem der CANalyzer
mit der CANopen Option helfen - OK, er detektiert die Probleme, aber
kann sie natürlich nicht verhindern ;-) ).
Also, das Szenario 1a würde gehen (ist aber eher Zufall, da Client(3)
und Client(4) synchronisiert werden müssten). Grundsätzlich ist es aber
eine Todsünde bei CAN (nicht nur bei CANopen) die gleiche Nachricht von
unterschiedlichen Knoten aus zu senden.
Hallo Mirko,
Danke für deine ausführliche Antwort.
> Transfer (Segemented oder Block-Transfer würde gar nicht gehen. Da kämen> die SDO-Protokoll-Zustandsmaschinen völlig durcheinander) handelt, gibt
Volltreffer, genau das Problem hatte ich nämlich mit dem "selbst
gebastelten Stack" ;) Ich war bis jetzt nur der Meinung, dass es möglich
sein sollte, an einen SDO-Server einen Request zu senden, auch während
er einen Blocktransfer mit einem weiteren Client durchführt. Dass der
Request negativ beantwortet wird oder der Blocktransfer wiederholt
werden muss, hätte ich mir vorstellen können.
Ich wollte das demnächst noch mit dem Systec-Stack ausprobieren, bin
aber noch nicht dazu gekommen (im Moment ist der selbst gebastelte der
Server und der Systec der Client).
> Also, das Szenario 1a würde gehen (ist aber eher Zufall, da Client(3)> und Client(4) synchronisiert werden müssten). Grundsätzlich ist es aber> eine Todsünde bei CAN (nicht nur bei CANopen) die gleiche Nachricht von> unterschiedlichen Knoten aus zu senden.
Ich habe einen "Displaycontroller-Knoten", der an 0x5000 geschriebene
Strings auf dem LCD ausgibt. Dieser "Service" wird von mehreren
(erweiterbaren) Clients benötigt. Muss ich in dem Fall für jeden
potentiellen Client einen eigenen Channel einrichten?
Viele Grüße,
Dirk.
Knallen kann das nie, da beim CAN Bus Kollisionen selbstständig gelöst
werden. Die Arbitrierung bestimmt nur die Reihenfolge der Pakete.
Übrigens gehen d natürlich alle Bits mit ein, nicht nur die Bits des
Identifiers.
Könnte es sein, dass hier die ID mit einer Zieladresse verwechselt wird?
Tatsächlich ist die ID so gesehen eher eine eindeutige Absenderadresse.
Wenn man einer Node einen ID-Bereich verpasst auf den sie reagieren und
irgendwas tun soll, und diese Node von mehreren anderen Nodes in
gleicher Weise angesprochen wird, dann muss man auch die sendende Node
irgendwie in die ID reincodieren. Damit die ID eindeutig wird. Die
empfangende Node kann diese Bits dann per Maske ignorieren.
Wenn 2 Teilnehmer den gleichen Identifier senden, gewinnen beide die
Arbitrierung und es gibt einen Error in den Daten. Das Retry erfolgt
dann auch wieder gleichzeitig und irgendwann schalten dann die
Errorcounter gleichzeitig beide ab.
Daher muß durch ein Protokoll vermieden werden, daß 2 Teilnehmer den
gleichen Identifier senden können.
Ein einfaches Protokoll dazu ist ein Single-Master Protokoll.
Nachrichten können nur vom Master zum Slave gesendet werden oder
umgekehrt. Nachrichten zwischen 2 Slave sind verboten.
Der Master sendet die Slaveadresse mit gelöschtem Slavebit und ein Slave
sendet seine eigene Adresse mit gesetztem Slavebit.
Somit hat die Arbitrierung immer Erfolg und der Master Priorität.
Eine andere Möglichkeit ist CAN2.0b und der Identifier (29 Bit) enthält
beide Adressen, die des Senders und die des Empfängers.
Peter
Hi,
als erstes sollte man sagen, dass es in einem CANopen Netzwerk nur einen
aktiven SDO Client je Server geben darf. SDO ist einen Punkt-zu-Punkt
Verbindung. Daher muss man, wenn man mit Diagnose-Tools ins Netzwerk
auch aufpassen und korrekterweise den Master ausschalten (ist meist der
einzige mit SDO Clients).
Insofern darf es den beschriebenen Zustand - 2 Clients schreiben auf
einen Server - nicht geben. Und ja, dieser Vorgang führt zu Problemen.
Meist merkt man dies anfangs nicht, da beide Clients genau gleichzeitig
senden müssen. Dies ist erst später der Fall, wenn der Bus mit
höherprioren Nachrichten recht voll ist. Es kracht daher erst bei der
Inbetriebnahme.
Meist führt dies zu einem einmaligen Busoff, der häufig automatisch
aufgelöst wird. Dann fängt sich das ganze System wieder bis zum nächsten
Schluckauf.
bye
Steffen
Hallo miteinander,
Ich fasse mal kurz zusammen, was ich herausgelesen habe:
1) Die Arbitrierung geht "nur" über die COB-ID (so wie auch in den
meisten "offiziellen" Docs beschrieben.
2) Ein SDO-Server benötigt für jeden potentiellen Client einen Channel.
Wenn man sich an 2) hält ist 1) kein Problem.
Wenn man aber mit mehreren Clients den selben Server/Channel anspricht
(wie in meinem Fall mit dem "Display-Server"), kommt es praktisch zu
Kollisionen.
Vielen Dank an euch alle.
Gruß, Dirk.