Forum: Mikrocontroller und Digitale Elektronik CANopen - Datenlogger


von Jk M. (h4l9000)


Lesenswert?

Hi,

ich habe 10 CANopen Sensoren am CANBus (Sensor: Abtastrate 1ms, Baudrate 
500 kBit/s) und möchte nacheinander jeden Sensor für zB. 10 Sekunden 
auslesen (Messwerte pro Messung = 10000).

Als Master benutze ich ein Galileo Gen2 Board.
Momentan benutze ich zum Auslesen der Sensoren die IP Filter Option 
(SocketCAN) und ändere je nachdem welchen Sensor ich auslesen möchte die 
gesetzte Node-ID im Filter.

Bsp.für NodeIP 10:
rfilter[0].can_id   = 0x18A;  %Beispiel Node IP: 10 (A)
rfilter[0].can_mask = 0x1FFFFFFF;;
...
setsockopt(iSock, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, 
sizeof(rfilter));
...
read(iSock, &frame, sizeof(frame))


Als CANopen Übertragungstyp für die Sensoren habe ich "Ereignisgesteuert 
+ zyklisch" eingestellt (=255).

Ist das die richte Methode um Sensoren mit hoher Abtastrate nacheinander 
auszulesen, oder gibt es da einen eleganteren Weg?

Zudem ist die Frage wie ich am besten die Taktung von 1ms zustande 
bringe.
Momentan mache ich das mit einer While-Schleife, in welcher die 
Auslesefunktion (read()) für die Sensoren steht. Diese Schleife bricht 
dann nach 10 Sekunden (Messdauer) ab.
Da gibt es doch sicher eine bessere bzw. genauere Methode? Vllt. mit 
delays in microSek. Bereich?
Nach jeder read()- Funktion speichere ich die Daten übrigens in einen 
String[n].


Vielen Dank!

Cheers,
Johannes

von Florian (Gast)


Lesenswert?

Ohne mehr Details zu wissen ist das relativ schwierig.

Du hast bei CANopen ja mehrere Möglichkeiten Daten zu verschicken bzw 
das verschicken von zyklischen Daten zu beeinflussen. Ich nehme mal an, 
dass du bereits weißt was die entsprechenden Übertragungsarten sind 
(PDO, SDO, etc).

Bei deiner Datenrate würde ich die Sensoren nacheinander ab / anschalten 
über entsprechende SDO's, sodass immer nur einer der 10Sensoren versucht 
mit 10kHz die Daten zu versenden (was bei einerm 500kbit/s Bus 
vielleicht ein wenig hoch angesetzt ist).

Denn: Ereignis-gesteuert bedeutet ja, das du für jedes PDO ein SYNC 
schicken musst, da wird dir die Buslast vermutlich um die Ohren fliegen, 
wenn dann zu den Daten auch noch SYNC, HEARTBEAT etc kommt.

Aber vielleicht kann jemand mit mehr Erfahrung noch was dazu sagen.

von Jk M. (h4l9000)


Lesenswert?

Danke für deine schnelle Antwort!


Habe die Sensoren bei Übertragungstyp 255 nur zyklisch eingestellt, 
nicht ereignisgesteuert. Sorry mein Fehler.

EventTimer der Sensoren ist demzufolge auf 1ms gesetzt.


Da ich mit Linux noch nicht so vertraut bin:
Ich benutze CANopenSocket (https://github.com/CANopenNode/CANopenSocket) 
als Master. Wie ich NMTs, SDOs Befehle vom Linux Terminal ausführe ist 
mir klar.
Wie kann ich SDOs (z.B start/preop/stop) an Sensoren senden vom c++ Code 
aus?
Mit "system("...");" ?

von Florian O. (simuru)


Lesenswert?

Jk M. schrieb:
> Wie ich NMTs, SDOs Befehle vom Linux Terminal ausführe ist
> mir klar.

Das ist schonmal gut.

> Wie kann ich SDOs (z.B start/preop/stop) an Sensoren senden vom c++ Code
> aus?

Die Frage ist ungut ;)
Preoperational, Stopped, etc sind die Zustände der Zustandsautomaten den 
jedes CANOpen Gerät implementieren muss (wenn man CiA 301 Conform ist). 
Damit sollte man nicht steuern ob ein Gerät etwas sendet oder nicht.

folgendes solltest du haben oder dir klar machen:
1.du hast eine vollständige Beschreibung des Gerätes
2. du weißt welches PDO genutzt wird um die Daten die du haben möchtest 
zu verschicken
3. du weißt wie man per SDO auf das Objektverzeichnis zugreifst und die 
PDO Kommunikationsparameter einstellt.

Sonst wird das ganze etwas schwierig.

Generelles zu den Übertragungsarten (PDO, SDO etc) steht in Abschnitt 7 
CiA-301. Gibts kostenlos wenn man sich bei can-cia.org anmeldet.
Details zu den PDO Kommunikationsparametern (wie auch Event Timer zu 
verschicken nach 1ms und ähnlich) stehen in der Beschreibung zum 
Objektverzeichnis, Kapitel 7.4, bzw genauer 7.4.8.1

von Jk M. (h4l9000)


Lesenswert?

1. ja
2. ja
3. ja

Eine Sensorabfrage mit RTR will ich eigentlich vermeiden.
Ansonsten wüsste ich nicht wie ich meine Sensoren an(senden)- / 
ausschalten(pause) soll ohne SDO Befehle.

von Steffen R. (steffen_rose)


Lesenswert?

> ich habe 10 CANopen Sensoren am CANBus (Sensor: Abtastrate 1ms, Baudrate
> 500 kBit/s) und möchte nacheinander jeden Sensor für zB. 10 Sekunden
> auslesen (Messwerte pro Messung = 10000).
>
> Als Master benutze ich ein Galileo Gen2 Board.
> Momentan benutze ich zum Auslesen der Sensoren die IP Filter Option
> (SocketCAN) und ändere je nachdem welchen Sensor ich auslesen möchte die
> gesetzte Node-ID im Filter.

Du verwirrst deine Mitleser. Du liest nicht aus (SDO), sondern du 
konfigurierst die Sensoren so, dass diese mit der entsprechenden Rate 
gesendet werden und du sie entsprechend empfängst.


> Als CANopen Übertragungstyp für die Sensoren habe ich "Ereignisgesteuert
> + zyklisch" eingestellt (=255).

Deine Wortwahl ist richtig. Lass dich nicht verwirren. Der eingestellte 
Eventtimer gilt nur, wenn nicht vorher das PDO aus anderen Gründen 
geschickt wird. Es kann also auch vorkommen, dass dein Zyklus nicht 
eingehalten wird, sondern Daten auch mal schneller kommen könnten.

255 bedeutet Profilspezifisch. Nutzt Du ein Profil? Ansonsten wäre der 
Typ 254.

> Ist das die richte Methode um Sensoren mit hoher Abtastrate nacheinander
> auszulesen, oder gibt es da einen eleganteren Weg?

Wenn die Sensoren diesen Weg können, dann finde ich ihn richtig. 
Schneller gehts eher nicht. Wenn du aber hohe Ansprüche an die 
Zyklusgenauigkeit hast und die Sensoren den Sync dazu nutzen können, 
wäre die Sync TPDOs die richtigen.

Achte insgesamt darauf, dass du den Bus nicht überlastest.

> Zudem ist die Frage wie ich am besten die Taktung von 1ms zustande
> bringe.
> Momentan mache ich das mit einer While-Schleife, in welcher die
> Auslesefunktion (read()) für die Sensoren steht. Diese Schleife bricht
> dann nach 10 Sekunden (Messdauer) ab.
> Da gibt es doch sicher eine bessere bzw. genauere Methode? Vllt. mit
> delays in microSek. Bereich?
> Nach jeder read()- Funktion speichere ich die Daten übrigens in einen
> String[n].

Du kennst deine Sensoren. Wenn diese den Zyklus einhalten, brauchst du 
auf Masterseite im einfachsten  Fall nur auf die Nachrichten zu warten 
und die 10 Sekunden bzw. die 10000 Nachrichten zu zählen. Oder was 
willst du mit der 1ms Wartezeit erreichen.

Florian schrieb:
> Denn: Ereignis-gesteuert bedeutet ja, das du für jedes PDO ein SYNC
> schicken musst,

Nein, das sind die synchronen PDOs.

Florian O. schrieb:
> Preoperational, Stopped, etc sind die Zustände der Zustandsautomaten den
> jedes CANOpen Gerät implementieren muss (wenn man CiA 301 Conform ist).
> Damit sollte man nicht steuern ob ein Gerät etwas sendet oder nicht.

Jein. Das man den NMT Zustand nicht unbedingt immer so umschaltet, wie 
man ihn grad braucht - dem würde ich zustimmen. Das hier scheint aber 
keine normale Anwendung zu sein. Insofern könnte man schon ausnutzen, 
dass PDOs nur im Zustand NMT Operational gesendet wird.
Zum Umschalten des NMT Zustandes wir ein NMT Kommmando geschickt.

Jk M. schrieb:
> Eine Sensorabfrage mit RTR will ich eigentlich vermeiden.
> Ansonsten wüsste ich nicht wie ich meine Sensoren an(senden)- /
> ausschalten(pause) soll ohne SDO Befehle.

Ich glaube, hier missverstehst du Florian.
Soweit ich seine Anmerkungen verstehe, empfiehlt er Dir statt des NMT 
Kommandos das PDO per SDO an-/auszuschalten. Hierzu nutzt man das Bit 31 
der COBID.

Empfinde ich aber als genauso unelegant wie das Umschalten per NMT.
@Florian: Ich empfinde es nicht schön im NMT Operational ein PDO 
umzukonfigurieren.

von Florian O. (simuru)


Lesenswert?

Steffen R. schrieb:
> Empfinde ich aber als genauso unelegant wie das Umschalten per NMT.
> @Florian: Ich empfinde es nicht schön im NMT Operational ein PDO
> umzukonfigurieren.

@Steffen: Ja da hast du recht  - schön ist was anderes.
Aber soweit ich weiß gibt es keinen sinnvollen Mechanismus außer die 
Geräte per NMT umzuschalten - aber dann braucht er mehr NMT-Master 
funktionalität, die war im CANOpenNode Stack glaube ich recht dünn. Und 
wenn ich dann folgendes lese:

> Wie kann ich SDOs (z.B start/preop/stop) an Sensoren senden vom c++ Code
> aus?
> Mit "system("...");" ?

glaube ich, dass das der schwierigere Weg ist..


Wenn ich mich recht entsinne kann man auch die PDO Mapping parameter 
dafür misbrauchen indem man die Anzahl der gemappten PDO's auf 0 setzt..

von Steffen R. (steffen_rose)


Lesenswert?

Florian O. schrieb:
> Wenn ich mich recht entsinne kann man auch die PDO Mapping parameter
> dafür misbrauchen indem man die Anzahl der gemappten PDO's auf 0 setzt..

Das Mapping darf nur von deaktivierten PDOs (also Bit 31 in der COBID 
gesetzt) geändert werden (inclusive der Länge).

Insofern wäre bei dieser Variante das deaktivieren über die COBID das 
Mittel der Wahl.

von Florian (Gast)


Lesenswert?

Steffen R. schrieb:
> Das Mapping darf nur von deaktivierten PDOs (also Bit 31 in der COBID
> gesetzt) geändert werden (inclusive der Länge).
>
> Insofern wäre bei dieser Variante das deaktivieren über die COBID das
> Mittel der Wahl.

Das hatte ich so nicht mehr auf dem Schirm, danke für die Aufklärung!

von Jk M. (h4l9000)


Lesenswert?

mit COB-ID 31 ist die Mapping Variable gemeint?

Laut meinem Datenblatt ist bei PDO-MappingMode 31 = "spec.Msg._U64_P" 
mit Size: 8Bytes.

Bei Bit32 allerdings ist "spec.Msg._NIL_T" mit Size: 0bytes angegeben.

Wenn ich möchte dass der entsprechende Sensor "ausgeschaltet" ist, wäre 
doch der MappingMode 32 die bessere Lösung?


Den MappingMode kann ich ändern mit:

ID-Node 10:    "cansend 60A#22 0021 01 32 00 00 00"

(mit: PDO1-Mapping Index/Subindex: 2100H  /  01H)

Ist das richtig?

Und nochmals danke für Eure super Kompetenz!

von Steffen R. (steffen_rose)


Lesenswert?

Mit der von dir verwendeten Software kenne ich micht nicht aus.

Jk M. schrieb:
> mit COB-ID 31 ist die Mapping Variable gemeint?

Nein. Die COB-ID ist die CAN ID, mit der das PDO gesendet wird. 
(@experts plus ein paar Zusatzinfos)

Mit 31 ist das Bit 31 gemeint. (siehe Index 0x1800 im CiA301)

> Den MappingMode kann ich ändern mit:
>
> ID-Node 10:    "cansend 60A#22 0021 01 32 00 00 00"
>
> (mit: PDO1-Mapping Index/Subindex: 2100H  /  01H)

Der Bereich ab 0x2000 ist herstellerspezifisch. Ohne Details kann dir da 
niemand helfen. Wenn deine Sensoren standardkonform sind kommst du über 
den Bereich 0x1000..0x1FFF an die entsprechde Konfiguration.

Willst du über den von dir angesprochenen herstellerspezifischen 
MappingMode gehen, musst du schauen, welcher dazu führt, dass die PDOs 
nicht mehr gesendet werden. Der Effekt wäre dann wohl derselbe.

Üblich wäre allerdings selbst bei solchen Lösungen, dass "nur" das 
Mapping variiert wird, d.h. welche Daten die PDOs enthalten.

von Florian (Gast)


Lesenswert?

Hallo JK,

CANopen ist bei mir schon ein paar Tage her, deswegen wäre es gut wenn 
Steffen nochmal was dazu sagen könnte.

Wie ich es sehe:
Im Objektverzeichnis stehen ab 1800(hex) bis 19FF(hex) die PDO 
Kommunikationsparameter für TPDOS - also für PDOS die dein Sensor senden 
kann. Unter dem Subindex 01(hex) steht die COB-ID mit folgendem Aufbau

Aus CiA-301 Seite 136ff:
1
Bitpos, Beschreibung
2
+------+------+--------+----------------------------+----------------
3
|31    |  30  |  29    |  28                    11  | 10          0
4
+------+------+--------+----------------------------+----------------
5
|valid |  RTR | frame  |      Extended ID           | 11bit CAN-ID
6
+-------------+--------+----------------------------+----------------
1
valid    =   0 PDO exists / is valid
2
         =   1 PDO does not exist / is not valid

Ein nicht valides PDO wird nicht verschickt - auch nicht auf Anfrage.

Du könntest also das bit 31 auf 1 setzen damit inaktive Sensoren keine 
Messwerte verschicken. Das verändern dieses Bits bzw der 
Kommunikationsparameter geschieht über SDO's

von Jk M. (h4l9000)


Angehängte Dateien:

Lesenswert?

ich habe mal 2 Screenshots gemacht... vllt hilft das ja zum Verständnis.

von Jk M. (h4l9000)


Lesenswert?

okay, danke!
Ich versuche mal mein Glück und melde mich dann wieder.

von Jk M. (h4l9000)


Angehängte Dateien:

Lesenswert?

Bei Index: 1800H  und Sub.Index 1H  steht  0000'0180h+Node-ID.

So wie ich das verstanden ist der Aufbau folgendermaßen:
       0  -    0   -   0   -  0'0180h+Node-ID.
    "valid"-"RTR"-"frame"-"0'0180h+NodeID"

Wenn ich also "1000'0180h+Node-ID" setzte dürfte der Sensor mit 
entsprechender ID nicht mehr senden?

von Steffen R. (steffen_rose)


Lesenswert?

Jk M. schrieb:
> Wenn ich also "1000'0180h+Node-ID" setzte dürfte der Sensor mit
> entsprechender ID nicht mehr senden?

Richtig.
Lies unabhängig davon mal den gültigen Wert aus, ob er dieser Vorschrift 
entspricht. Der beschiebene Wert ist der standardisierte Defaultwert und 
kann wie alles umkonfiguriert werden.

Jk M. schrieb:
> ich habe mal 2 Screenshots gemacht

Das ist auf jeden Fall herstellerspezifisch. Sollteste du mit der COBID 
nicht klarkommen, würde ich es mit der Eventmaske probieren. 0 könnte 
ich mir gut vorstellen.

von Jk M. (h4l9000)


Lesenswert?

also das klappt soweit.
allerdings war es doch etwas verwirrend mit den bin/ hex und den 11-29 
bits.

   10000000000000000000000110010100   COD-ID: 20

oder eben in hex:

   0x80000194    (hier habe ich versehentlich 0x10000194 verwendet was 
natürlich falsch ist ;) )

cheers,
johannes

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.