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
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.
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("...");" ?
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
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.
> 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.
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..
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.
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!
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!
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.
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
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?
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.