Forum: Mikrocontroller und Digitale Elektronik Sinnvolles verarbeiten von CAN messages


von Michael M. (Firma: ETH Zürich) (cubli)


Lesenswert?

Hallo zusammen,

Ich bin gerade an meiner Masterarbeit und versuche eine sinnvolle 
Datenstruktur für CAN Kommunikation aufzubauen:

Dazu verwende ich das STM32E-EVAL evaluation board von ST und möchte 
über die CAN Schnittstelle mit einem Maxon EPOS2 Motor Controller per 
CAN kommunizieren.

Grundsätzlich bin ich in der Lage, CAN commands an EPOS2 zu senden, um 
z.B. den Controller zu initialisieren (z.B. im Current-control mode), 
setpoints zu ändern, den Motor zu starten/stoppen, etc. Dies geschieht 
über spezielle CAN commands:

Über die ID wird bestimmt, welcher CAN Node angesprochen wird (ich 
möchte schlussendlich 6 motor controller gleichzeitig per can regeln) 
und die 8 bytes data, welche geschickt werden enthalten eine bestimmte 
Kodierung (Anweisung).

Nun möchte ich die Drehzahl des Motors per CAN von EPOS übertragen 
bekommen. Dazu sende ich eine Anfrage raus (z.B mit ID 1536+1 für Node 
1) und unmittelbar danach erhalte ich die gewünschte Drehzahl unter der 
ID 1408+1 für Node 1).

Das Problem ist nun, wie ich am saubersten diese Kommunikation 
implementieren kann, denn der ganze Ablauf, bis zum erhalten der 
Drehzahl spielt sich ja mindestens in zwei files ab: bei mir z.B. in 
EPOS.c wo ich den "CAN_Transmit" Befehl ausführe und in "stm32f10x_it.h" 
(in der Funktion "CAN_Transmit"), wo schlussendlich ein Interrupt 
generiert wird bei Erhalt einer neuen Nachricht.

Nun kann es ja sein, dass zwischen Absenden der Anfrage und Eintreffen 
der Antwort des angefragten Nodes noch andere Messages rein kommen, die 
im "schlimmsten" Fall zu einer früheren, gleichartigen Anfrage gehören.

Die Frage die ich mir nun gestellt habe ich wie ich am besten vorgehe, 
damit die Antwort bestimmt am richtigen Ort landet, rsp. bin ich auf der 
Suche nach einem Interface, mit welchem ich mir diese Kommunikation 
erleichtern könnte.

So könnte ich mir z.B. vorstellen, dass ich für jeden der 6 Motoren ein 
Struct habe mit Node-ID und aktueller Geschwindigkeit und dieses Struct 
dann irgendwie up-to-date halte. Ich weiss aber nicht, wo ich am besten 
diese Variable initizlisiere (z.B in "main.c" und dann den pointer dazu 
global verfügbar abspeichern,???) und vor allem so, dass ich später auch 
andere messages dazu fügen kann, wie anders verarbeitet/interpretiert 
werden und dass ich einfach einen Motor hinzufügen/entfernen kann, ohne 
dass ich in 3 files eine Änderung machen muss.

Ich wäre euch sehr dankbar für einen Tipp, denn ich bin auf dem Gebiet 
als Maschinenbauer überhaupt nicht heimisch:-S


Gruss

Michael
von Peter D. (pdiener) Benutzerseite


Lesenswert?

Man kann ja auch von structs Arrays bilden. Dann definiert man eine 
Konstante, die einmal für das ganze Projet angibt, wie viele Motoren es 
gibt.

z.B. so:

#define NUMBER_OF_MOTORS 6
struct T_Motor motors[NUMBER_OF_MOTORS];

Für die Kommunikation würde ich immer davon ausgehen, dass der zuletzt 
empfangene Drehzahlwert der aktuellste ist. Dann einfach jede Nachricht 
auf die ID prüfen und je nach ID den entsprechenden Wert in der 
zugehörigen Speicherstruktur updaten.

Grüße,

Peter
von Karl H. (kbuchegg)


Lesenswert?

> Das Problem ist nun, wie ich am saubersten diese Kommunikation
> implementieren kann, denn der ganze Ablauf, bis zum erhalten der
> Drehzahl spielt sich ja mindestens in zwei files ab: bei mir z.B.
> in EPOS.c wo ich den "CAN_Transmit" Befehl ausführe und in
> "stm32f10x_it.h" (in der Funktion "CAN_Transmit"), wo schlussendlich
> ein Interrupt generiert wird bei Erhalt einer neuen Nachricht.

Am saubersten, in dem du eine ganz klare Trennung einführst.
Die CAN Schicht interessiert sich nur für CAN-Messages als Ganzes. 
Lediglich die ID des/der Kommunikationsteilnehmers ist für diese Schicht 
noch interessant. Was der Inhalt der Message bedeutet, hat die CAN 
Schicht nicht zu interessieren.

Kommt eine Message rein, dann wird die Message als Ganzes zb in einer 
Queue abgelegt (zusammen mit der ID, von wem sie gekommen ist). Das ist 
die Schicht, in der die Interrupts ins Spiel kommen, die du brauchst, 
damit du keine Message verlierst.

Die darüber liegende Schicht wiederrum interessiert sich nicht für CAN 
Details. Für die ist die darunterliegende Schicht lediglich ein Mittel 
zum Zweck, damit sie Messages auf die Reise bringen kann bzw. die sie 
befragen kann, ob in der Zwischenzeit Messages eingetroffen sind. Dazu 
braucht sie von CAN nichts verstehen und sie braucht auch keine 
Interrupts.
Dafür muss diese Schicht aber darüber Bescheid wissen, was der Inhalt 
der Messages bedeutet und wie der zusammenzustellen/zu_interpretieren 
ist. Das ist ihre Domäne. Auf dieser Ebene wird eine Nachricht vom 
Teilnehmer A zum Teilnehmer B geschickt. Wie dieses Versenden passiert 
ist nicht mehr ihre Aufgabe.
von EC-Bastler (Gast)


Lesenswert?

Hallo hallo,
sitze grad an ähnlicher Hardware (Maxon EPOS2+EC Motor), habe bereits 
den CAN-Controller meines µC soweit am Laufen, nur weiß ich mit dem 
CANopen Protokoll nicht weiter...

@ Michael Merz: Wollte an dieser Stelle fragen, wie du das gelöst hast?
von Matthias L. (Gast)


Lesenswert?

>ID 1536+1 für Node 1)

CANopen ?
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.