Hallo zusammen, da Ihr mir bisher sehr geholfen habt bei meinen fragen, kommt hier die nächste: ich nutze STM32F103 (Arduino Blue Pill) mit den CAN Transivern SN65HVD230. Zur Zeit sollen 12 Teilnehmer miteinander Kommunizieren. Um den bus zu entlasten, sende ich immer nur Ereignis abhängig, sprich wenn sich der Zustand eines Sensors oder im Programm etwas ändert. Das funktioniert auch einwandfrei. Um sicherzustellen das die Nachricht auch den richtigen Empfänger erreicht hat, sende ich eine Variable zum Sender zurück. Auch das funktioniert soweit. Wenn der Sender die Bestätigung empfängt wird die Nachricht trotzdem noch 5 mal gesendet um sicher zu stellen das die Rückmeldung korrekt ist. Beim Einschalten wird aber auch eine Nachricht versendet um der Zentrale alle aktuellen Zustände zu melden. Jetzt zu meinem Problem. Wenn ich mehr als 6 Teilnehmer im Bus habe funktioniert zB die Rückmeldung beim Einschalten von zB. Modul 2 nicht mehr, nehme ich den 6ten Teilnehmer wieder raus funktioniert es wieder. Schalte ich die Module nacheinander ein, funktioniert die Rückmeldung. Also habe ich in jedem Modul im Setup ein Delay programmiert, das die Module unterschiedlich verzögert, dann funktioniert es zum Beispiel bis Modul 8 aber die Zeitabstände der einzelne delays müssten immer grösser werden. Zum Beispiel: Modul 1 delay (100) Modul 2 delay (200) usw. Funktioniert bis zB Modul 5 danach muß Modul 6 aber schon ein delay von (1000) haben . da am ende so knappe 100 Teilnehmer am Bus hängen sollen ist das kein gangbarer Weg. Dann habe ich die Anzahl der Sendevorgänge nach Empfang der Empfangsbestätigung von 5 auf 50 erhöht. Dies brachte keine Änderung. Der Bus ist terminiert mit 2 120 Ohm Widerständen. Die CANH und CANL Leitung sind verdrillt und der Abstand zwischen den einzelnen Teilnehmern beträgt ca 12 cm. Je nach zusammenstellung der Teilnehmer, ich kann zur Zeit nur 6 auf meinem Testbrett testen, tritt der Fehler bei anderen Modulen auf. zum Beispiel Ich nutze Modul 1,2,3,4,5 und es fällt Modul 2 aus. Oder ich nutze Modul 2,3,4,5,6 und es fällt Modul 5 und 6 aus. usw. Im Einzeltest funktioniert jedes Modul wie es soll. Exemplarisch habe ich euch die Programierung von einem Modul angehängt. GRuß Kay
Da fallen mir spontan folgende Dinge ein: Welche Datenrate? Braucht jede Message eine eigene CAN ID? Die 8x8 Bit Payload kannst du beliebig verteilt für Signale nutzen. Ungerade Delays besser als gerade z.B 199ms statt 200ms. -> Weniger Daten-Kumulation beim kleinsten gemeinsamen Vielfachen. Random Delays einführen? Ein Triggered Protokoll in der Payload integrieren einführen z.B. Enable-Token? Message Counter?
Bus-Kollisionen löst CAN automatisch verlustfrei auf, das macht es eigentlich leicht. Heißt: Der Sender muss sich über einen geeigneten Sendezeitpunkt keinen Kopf machen. Er schreibt die Botschaft in den Puffer, und der Controller sendet sie, falls keine höher priore gleichzeitig loslegt, und probiert das so lange, bis sie raus ist. Bei den beobachteten Effekten würde ich folgendes prüfen: - haben alle Botschaften verschiedene IDs? Das ist Grundprinzip bei CAN, sonst gibt's Kollisionen. - Ist der Bus voll? Kann passieren wenn die Baudrate niedrig ist. Bei ein paar Metern kannst du 500kBaud fahren, dann passen mehrere Botschaften in eine Millisekunden, das sollte für deinen Fall reichen, oder? - Läuft beim Empfänger vielleicht ein Puffer voll? Wenn am Bus 4 Botschaften in einer Millisekunde ankommen aber die Software nur jede Millisekunde eine Botschaft verarbeitet, dann sind drei verloren. Es gibt ausgeklügelte Konzepte mit FIFO, DMA etc um das zu verhindern. - Messen ist besser als raten. Mit einem CAN-USB-Adapter und Savvycan auf dem PC beobachten was wirklich auf dem Bus passiert, dann wird's spontan klar wo man weiter suchen muss.
Ronny M. schrieb: > Da fallen mir spontan folgende Dinge ein: > > Welche Datenrate? > Braucht jede Message eine eigene CAN ID? Die 8x8 Bit Payload kannst du > beliebig verteilt für Signale nutzen. > Ungerade Delays besser als gerade z.B 199ms statt 200ms. -> Weniger > Daten-Kumulation beim kleinsten gemeinsamen Vielfachen. > Random Delays einführen? > Ein Triggered Protokoll in der Payload integrieren einführen z.B. > Enable-Token? Message Counter? Datenrate ist 500k meine Struktur der CAN Nachrichten ist so aufgebaut das Jedes Modul von der Zentrale eine eigene Nachricht bekommt und Natürlich auch das jedes Modul eine eigene Nachricht an de Zentrale sendet. Also im ersten Moment bei 6 module sind das 12 Nachrichten, sobald zb Modul 1 sich zurück meldet sind es nur noch 10 usw. Um die Menge der nachrichten die gleichzeitig am BUS anliegen zu reduzieren habe ich ja von permanenten senden auf Ereignisabhängiges senden umgestellt. Danke für den Tip mit den ungeraden delays, das macht Sinn. Aber es kann doch nicht des Rätzels Lösung sein die einzelnen STMs verzögert einzuschalten? Am ende können bis zu 100 Teilnehmer im Netz sein das würde ja bei 100ms 10 Sekunden verzögerung bedeuten. Da muß es doch eine elegantere Lösung geben. Meinst Du mit enable Token? das jedes Modul ein "Ich bin da" Signal sendet? Das wird ja im Prinzip gemacht: Wenn Modul 1 eine für Modul 1 bestimmte nachricht von der Zentrale erhält, sendet das Modul eine Variable (Modul1MSG09empfangen) an die Zentrale zurück. Triggered Protocool in Verbindung mit CAN? Hier verstehe ich deinen Ansatz Gruß Kay
> Da muß es doch eine elegantere Lösung geben.
Das denke ich jedesmal wenn ich sehe das an einem Auto die
CAN-Steuergeraete 10-30min brauchen bis die beim ausschalten alle
eingeschlafen sind. :-D
Vanye
Uwe schrieb: > Bus-Kollisionen löst CAN automatisch verlustfrei auf, das macht es > eigentlich leicht. Heißt: Der Sender muss sich über einen geeigneten > Sendezeitpunkt keinen Kopf machen. Er schreibt die Botschaft in den > Puffer, und der Controller sendet sie, falls keine höher priore > gleichzeitig loslegt, und probiert das so lange, bis sie raus ist. > Bei den beobachteten Effekten würde ich folgendes prüfen: > - haben alle Botschaften verschiedene IDs? Das ist Grundprinzip bei CAN, > sonst gibt's Kollisionen. > - Ist der Bus voll? Kann passieren wenn die Baudrate niedrig ist. Bei > ein paar Metern kannst du 500kBaud fahren, dann passen mehrere > Botschaften in eine Millisekunden, das sollte für deinen Fall reichen, > oder? > - Läuft beim Empfänger vielleicht ein Puffer voll? Wenn am Bus 4 > Botschaften in einer Millisekunde ankommen aber die Software nur jede > Millisekunde eine Botschaft verarbeitet, dann sind drei verloren. Es > gibt ausgeklügelte Konzepte mit FIFO, DMA etc um das zu verhindern. > - Messen ist besser als raten. Mit einem CAN-USB-Adapter und Savvycan > auf dem PC beobachten was wirklich auf dem Bus passiert, dann wird's > spontan klar wo man weiter suchen muss. Die Nachrichten ID´s sind verschiedene. Die Baudrate ist 500k. An der Zentrale hängt ein LCD auf dem ich die Zustände der Empfangsbestätigung anzeige. Wenn Zum Beispiel Die Bestätigung von Modul 1 bis 4 da ist, aber nicht die von 5, sehe ich mit meinem Logic Analyser das die Nachricht von der Zentrale an Modul 5 weiterhin gesendet wird und zwar nur noch die. Also genau das was passieren sollte, Empfangsquittung von Modul 5 ist nicht da, also wird die Nachricht weiter gesendet. Die Umgekehrte Nachricht, also von Modul 5 an Zentrale wird nicht mehr gesendet. Ich kann aber sehen, das diese anfänglich gesendet wurde. Schalte ich alle Module nacheinander an und es werden alle Empfangsbestätigungen als 1 angezeigt ist auch ruhe auf dem BUS, keine einzige nachricht. es kann also kein voller Puffer sein, oder? GRuß Kay
Frage: Ist es per Design sichergestellt, dass keine zwei Teilnehmer die gleichen CAN-IDs beim Senden verwenden? Das könnte nämlich Probleme bei der Arbitrierung geben. Eine Message mit einer bestimmten CAN-ID darf nur genau von einem Knoten kommen. Dann: Alle Knoten hängen am gleichen GND? Das fordert der Standard nämlich. fchk
Bei 500kbit/s und 12 Datenpaketen (mit je max 8 Bytes) kann der Bus doch nicht überfüllt sein .Da muss das Problem wo anders liegen. Kann es sein dass der Master die 6 Pakete die am Anfang zu ihm geschickt werden gar nicht schnell genug auslesen kann so dass welche verloren gehen?
Kay L. schrieb: > Wenn der Sender die Bestätigung > empfängt wird die Nachricht trotzdem noch 5 mal gesendet um sicher zu > stellen das die Rückmeldung korrekt ist. Das ist doch grober Unfug. Die CAN-CRC stellt sicher, daß alle Nachrichten im Empfangspuffer korrekt sind. Der Sender sendet ein Paket mit der ID des Empfängers, das die ID des Senders enthält. Der Empfänger schickt eine Quittung zurück und fertig. Kriegt der Sender nach einem Timeout keine Quittung, sendet er das Paket nochmal. Wird die Anzahl der maximalen Sendeversuche überschritten, setzt er einen Fehlerstatus. Vorzugsweise benutzt man den 29Bit-ID und sendet darin die ID des Senders und des Empfängers. Dann kann es nie eine Kollision geben, falls mal 2 Slaves den gleichen Empfänger adressieren.
Eigentlich sagt die ID um was es sich handelt z.B. Ansauglufttemperatur, das muss man nicht mehr weiter adressieren, jeder Teilnehmer kann die Info verwenden oder auch nicht, wenn ein Teilnehmer die Nachricht nicht richtig empfängt, meldet er sich eh und die Nachricht wird wiederholt. Also ist ein komplette ACK Nachricht des Empfängers unnötig.
Frank K. schrieb: > Frage: Ist es per Design sichergestellt, dass keine zwei Teilnehmer die > gleichen CAN-IDs beim Senden verwenden? Das könnte nämlich Probleme bei > der Arbitrierung geben. Eine Message mit einer bestimmten CAN-ID darf > nur genau von einem Knoten kommen. > > Dann: Alle Knoten hängen am gleichen GND? Das fordert der Standard > nämlich. > > fchk Ja, jede Nachricht hat eine eigene ID . Darüber führe ich zusätzlich eine Liste. Und auch ja, alle auf der selben GND Leitung. Alle werden aus dem gleichen Netzteil gespeist
Thomas schrieb: > Eigentlich sagt die ID um was es sich handelt z.B. Ansauglufttemperatur, > das muss man nicht mehr weiter adressieren, jeder Teilnehmer kann die > Info verwenden oder auch nicht, wenn ein Teilnehmer die Nachricht nicht > richtig empfängt, meldet er sich eh und die Nachricht wird wiederholt. > Also ist ein komplette ACK Nachricht des Empfängers unnötig. Ist es nicht, da der ACK von jedem Transiver gesendet wird egal ob er die Nachricht weiter verarbeitet oder nicht. Somit kann es besonders im einschalt Moment dazu kommen, das zum Beispiel die Nachricht an modul 1 von Mdul 2 quittiert worden ist. Modul 1 aber die Nachricht nicht empfangen hat. oder täusche ich mich da?
Peter D. schrieb: > Kay L. schrieb: >> Wenn der Sender die Bestätigung >> empfängt wird die Nachricht trotzdem noch 5 mal gesendet um sicher zu >> stellen das die Rückmeldung korrekt ist. > > Das ist doch grober Unfug. Die CAN-CRC stellt sicher, daß alle > Nachrichten im Empfangspuffer korrekt sind. > > Der Sender sendet ein Paket mit der ID des Empfängers, das die ID des > Senders enthält. Der Empfänger schickt eine Quittung zurück und fertig. > Kriegt der Sender nach einem Timeout keine Quittung, sendet er das Paket > nochmal. Wird die Anzahl der maximalen Sendeversuche überschritten, > setzt er einen Fehlerstatus. > > Vorzugsweise benutzt man den 29Bit-ID und sendet darin die ID des > Senders und des Empfängers. Dann kann es nie eine Kollision geben, falls > mal 2 Slaves den gleichen Empfänger adressieren. Mir geht es darum das die Nachricht beim richtigen Empfänger angekommen ist, da ich nur Ereignissabhängig sende. Das ACK wird von jedem transiver gesendet und nicht nur von dem, an den die Nachricht adressiert ist. Oder hab ich da einen denkfehler?
Thomas schrieb: > wenn ein Teilnehmer die Nachricht nicht > richtig empfängt, meldet er sich eh und die Nachricht wird wiederholt. > Also ist ein komplette ACK Nachricht des Empfängers unnötig. Ganz so einfach geht es natürlich nicht. Auf CAN-Ebene reicht es, wenn ein Teilnehmer das ACK-Bit setzt, damit der Sender zufrieden ist und kein Retry startet. Ob der zuständige Teilnehmer es aber auch empfangen hat, ist damit noch lange nicht sicher.
Georg S. schrieb: > Bei 500kbit/s und 12 Datenpaketen (mit je max 8 Bytes) kann der Bus doch > nicht überfüllt sein .Da muss das Problem wo anders liegen. Kann es sein > dass der Master die 6 Pakete die am Anfang zu ihm geschickt werden gar > nicht schnell genug auslesen kann so dass welche verloren gehen? Genau das ist auch mein Gedanke. Es sieht aber so aus als würde die Zentrale die nachricht von einem Modul nicht erhalten. Ich mache das folgendermassen: Hier an Beispiel von Modul2
1 | if (ZentraleMSG01empfangen == 0) // So lange keine Empangsbestätigung vom Empfänger da ist Senden |
2 | {
|
3 | CANMSG0x100001(); |
4 | ZaehlerCANMSG0x100001 = 0; |
5 | }
|
6 | if (ZentraleMSG01empfangen == 1) |
7 | {
|
8 | if (ZaehlerCANMSG0x100001 < 50) // Wen Empfangsbestäting da ist noch 10 mal senden |
9 | {
|
10 | CANMSG0x100001(); |
11 | ZaehlerCANMSG0x100001 = ZaehlerCANMSG0x100001 + 1; |
12 | }
|
13 | }
|
Kay L. schrieb: > if (ZentraleMSG01empfangen == 0) // So lange keine > Empangsbestätigung vom Empfänger da ist Senden Du mußt natürlich für jede Nachricht ein Timeout aufsetzen. Dieses muß mindesten so lang sein, wie ein Senden, Paket auswerten und Empfangen dauert. Außerdem kann weitere Zeit vergehen, wenn andere Pakete eine höhere Priorität haben. Ständig neu zu senden, solange noch nichts empfangen wurde, müllt Dir sonst alle Sendepuffer zu. Kay L. schrieb: > if (ZaehlerCANMSG0x100001 < 50) // Wen Empfangsbestäting da ist > noch 10 mal senden Nochmal, was soll das bringen?
Thomas schrieb: > wenn ein Teilnehmer die Nachricht nicht richtig empfängt, meldet er sich eh > und die Nachricht wird wiederholt. Wie meldet er sich denn, wenn er das wegen eines Problems nicht kann bzw. die Rückmeldung nicht durchkommt? Deswegen wartet der Sender auf ACK oder Timeout.
Rolf schrieb: > Thomas schrieb: >> wenn ein Teilnehmer die Nachricht nicht richtig empfängt, meldet er sich eh >> und die Nachricht wird wiederholt. > > Wie meldet er sich denn, wenn er das wegen eines Problems nicht kann > bzw. die Rückmeldung nicht durchkommt? "wenn ein Teilnehmer die Nachricht nicht richtig empfängt" bedeutet dass die CAN-Peripherie unabhängig von der Software die CRC-Prüfsummen aller durchlaufenden Pakete mitrechnet und wenn so ein Bitfehler festgestellt wird, wird eine Fehlermeldung auf den Bus gesendet. So bekommt der Sender mit dass sein Paket von mindestens einem Teilnehmer mit Bitfehler empfangen wurde. Wenn der eigentlich gedachte Empfänger das Paket verpasst weil sein Empfangspuffer voll war, das bekommt niemand mit.
Peter D. schrieb: > Kay L. schrieb: >> if (ZentraleMSG01empfangen == 0) // So lange keine >> Empangsbestätigung vom Empfänger da ist Senden > > Du mußt natürlich für jede Nachricht ein Timeout aufsetzen. Dieses muß > mindesten so lang sein, wie ein Senden, Paket auswerten und Empfangen > dauert. Außerdem kann weitere Zeit vergehen, wenn andere Pakete eine > höhere Priorität haben. > > Ständig neu zu senden, solange noch nichts empfangen wurde, müllt Dir > sonst alle Sendepuffer zu. > > Kay L. schrieb: >> if (ZaehlerCANMSG0x100001 < 50) // Wen Empfangsbestäting da ist >> noch 50 mal senden > > Nochmal, was soll das bringen? Zum nochmaligem senden. Zentrale sendet Nachricht 1 an Modul 1, Dummerweise im ersten Programmdurchlauf empfängt Modul 1 die Nachricht und setzt die Empfangsbestätigung auf HIGH, somit würde die Nachricht von Modul 1 an die Zentrale niemals gesendet werden. So wird aber noch 50 mal gesendet. Ursprünglich hatte ich da nur 5 mal. zum Timeout:
1 | void CANMSG0x100001() |
2 | {
|
3 | AUSLESENSENSOREN(); |
4 | // ---------------------------- CAN Nachricht 0x100001 senden
|
5 | // eigentliche Daten werden eingefüllt
|
6 | bitWrite (CAN_TX_msg.data[0], 0, LSEinfahrtSBHSudState); |
7 | bitWrite (CAN_TX_msg.data[0], 1, LSEinfahrtWendelSudUState); |
8 | bitWrite (CAN_TX_msg.data[0], 2, FahrstromFehlerModul2); |
9 | bitWrite (CAN_TX_msg.data[0], 3, Modul2MSG09empfangen); |
10 | CAN_TX_msg.len = 1; // Länge der Nachricht |
11 | |
12 | if ( ( counter % 2) == 0) |
13 | { // Rest der Nachricht wird befüllt |
14 | CAN_TX_msg.type = DATA_FRAME; |
15 | if (CAN_TX_msg.len == 0) CAN_TX_msg.type = REMOTE_FRAME; |
16 | CAN_TX_msg.format = EXTENDED_FORMAT; |
17 | CAN_TX_msg.id = 0x100001; // nachrichten ID |
18 | }
|
19 | CANSend(&CAN_TX_msg); // Übergabe der Nachricht an die Hardware |
20 | |
21 | }
|
das ist die eigentliche senden Funktion. was meinst Du genau mit Timeout? Gruß Kay
:
Bearbeitet durch User
Das ist schon mal kein gutes CAN-Design. Normalerweise melden sich alle Slaves, wenn sie bereit sind, mit einer Nachricht beim Master (mit Wiederholungstimer). Wenn alle Slaves gesendet haben, sendet der Master ein Ack. Dann kann die Nachrichtenübermittlung losgehen, gerne auch mit Ack bei jeder Message. Eine Sendungswiederholung ist nur bei Timeout des Acks notwendig, da CAN Busfehler selbständig händelt. Eigentlich braucht nur der Master ein EmpfangsFIFO, aber das sollte eh überall implementiert sein, wenn die SW/HW was taugt. Und nicht vergessen: Der Identifier codiert den Nachrichtentyp und darf nur von EINEM CAN-Knoten gesendet werden!
Kay L. schrieb: > das ist die eigentliche senden Funktion. Und wenn diese terminiert, ist nicht mal ein einziges Bit gesendet worden. Alles steht noch im Sendepuffer. Kay L. schrieb: > was meinst Du genau mit Timeout? Eben eine realistische Zeitdauer, in der die Hardware mindestens 2 Pakete übertragen konnte, zuzüglich Beenden des gerade laufenden Paketes, Übertragen aller Pakete mit höherwertigem ID, sonstiger Overhead.
Peter D. schrieb: > Kay L. schrieb: >> das ist die eigentliche senden Funktion. > > Und wenn diese terminiert, ist nicht mal ein einziges Bit gesendet > worden. Alles steht noch im Sendepuffer. > > Kay L. schrieb: >> was meinst Du genau mit Timeout? > > Eben eine realistische Zeitdauer, in der die Hardware mindestens 2 > Pakete übertragen konnte, zuzüglich Beenden des gerade laufenden > Paketes, Übertragen aller Pakete mit höherwertigem ID, sonstiger > Overhead. Meinst Du in etwa so? (Interval ist 250ms)
1 | {
|
2 | // ---------------------------- Begin CAN Senden
|
3 | // ---------------------------- CAN Nachricht 0x10001 senden
|
4 | // eigentliche Daten werden eingefüllt
|
5 | bitWrite (CAN_TX_msg.data[0], 0, LSEinfahrtSBHSudState); // |
6 | bitWrite (CAN_TX_msg.data[0], 1, LSEinfahrtWendelSudState); |
7 | CAN_TX_msg.len = 1; // Länge der Nachricht |
8 | unsigned long currentMillis = millis(); // Senden alle x millisekunden |
9 | if (currentMillis - previousMillis >= interval) |
10 | {
|
11 | previousMillis = currentMillis; |
12 | if ( ( counter % 2) == 0) |
13 | { // Rest der Nachricht wird befüllt |
14 | CAN_TX_msg.type = DATA_FRAME; |
15 | if (CAN_TX_msg.len == 0) CAN_TX_msg.type = REMOTE_FRAME; |
16 | CAN_TX_msg.format = EXTENDED_FORMAT; |
17 | CAN_TX_msg.id = 0x100001; // nachrichten ID |
18 | }
|
19 | CANSend(&CAN_TX_msg); // Übergabe der Nachricht an die Hardware |
20 | }
|
21 | }
|
:
Bearbeitet durch User
Dass in der Hälfte der Fälle, je nach counter, die ID etc nicht befüllt wird ist Absicht?
Helmut -. schrieb: > Das ist schon mal kein gutes CAN-Design. Normalerweise melden sich alle > Slaves, wenn sie bereit sind, mit einer Nachricht beim Master (mit > Wiederholungstimer). Wenn alle Slaves gesendet haben, sendet der Master > ein Ack. Dann kann die Nachrichtenübermittlung losgehen, gerne auch mit > Ack bei jeder Message. Eine Sendungswiederholung ist nur bei Timeout des > Acks notwendig, da CAN Busfehler selbständig händelt. Eigentlich braucht > nur der Master ein EmpfangsFIFO, aber das sollte eh überall > implementiert sein, wenn die SW/HW was taugt. Und nicht vergessen: Der > Identifier codiert den Nachrichtentyp und darf nur von EINEM CAN-Knoten > gesendet werden! Ok, verstehe. Das hört sich gut an. Das werde ich dementsprechend ändern.
Uwe schrieb: > Dass in der Hälfte der Fälle, je nach counter, die ID etc nicht befüllt > wird ist Absicht? Nein, weder beabsichtigt noch gewusst. Meinst du Zeile 12? Ich dachte das bedeutet "bei jedem 2ten Durchlauf"?
Kay L. schrieb: > Wenn der Sender die Bestätigung > empfängt wird die Nachricht trotzdem noch 5 mal gesendet um sicher zu > stellen das die Rückmeldung korrekt ist. Wie von Helmut schon geschrieben würde ich das CAN-Konzept nochmal überdenken: Ein CAN-Bus verliert üblicherweise keine Botschaften. Nur wenn die Software schlecht programmiert ist (Ich habe in 15 Jahren keine verloren). Ich würde die verschiedenen Botschaften immer zyklisch aussenden. Jeder Empfänger hat eine Timeout-Funktion für seine relevanten Botschaften. Schlägt der Timeout an so sendet der Empfänger einen Remote-Frame an den Sender um die Botschaft nochmals anzufordern. Dafür sind Remote-Frames ja gedacht.
1 | if (CAN_TX_msg.len == 0) CAN_TX_msg.type = REMOTE_FRAME; |
Mein Eindruck: Es mangelt am Konzept, an Design-Entscheidungen. Also: - Will man mit Remote-Frames arbeiten? Der Code scheint da irgendwie drauf vorbereitet zu sein, aber ob das gewollt oder aus Versehen ist, ist nicht klar. - Sind die Knoten darauf ausgelegt, dass auch mal "viele" Botschaften kommen, und die entweder alle ausgewertet werden müssen oder verloren gehen dürfen, weil sie eh später nochmal kommen. - Ist geklärt, wie das Timing sein soll, also - Nach Aufruf der Sendefunktion steht die Botschaft erst mal nur im Puffer. Auf dem Bus kommt sie erst, wenn dieser frei ist, das kann 0 bis mehrere Millisekunden dauern. - Soll eine Seite die Message stur im festen Raster wiederholen (zB 100ms) oder aufhören oder nach Ablauf einer bestimmten Zeit nochmal aktiv nachfragen dass sie etwas vermisst. Es gibt verschiedenste mögliche Konzepte, alle mit ihren Vor- und Nachteilen. Um es einfach zu halten, würde ich vorschlagen: - Keine Remote-Frames. - Jeder Knoten sendet seinen Status stur im festen Raster (z.B. 100ms oder 250ms oder was auch immer je nach zeitlichen Anforderungen). - Wenn ein Knoten "nicht da ist" (weil er später Power bekommt als die anderen oder abgesteckt wurde), können das die anderen detektieren indem sie "Timeout" erkennen, also "aktuelleZeit minus empfangsZeitpunkt ist größer als 5*Zykluszeit". - Falls es schnell gehen soll (also die Reaktionszeit zu langsam wäre mit dem festen Raster) kann man die Botschaft auch "bei Event sofort" senden, und danach wieder im festen Raster. - Sender und Empfänger müssen eine genügend lange Warteschlange (FIFO, Queue) haben, so dass auch die Fälle "viele Botschaften fast zeitgleich senden" und "viele Botschaften kommen gleichzeitig an" verlustfrei funktionieren. Die CAN-Controller-Hardware hat nur begrenzte Ressourcen, was dazu führt, das einfache Beispiele mit ein, zwei Botschaften perfekt laufen, aber sobald der Bus voller wird, Messages verloren gehen. Daher muss dann der Software-Treiber den FIFO bereithalten.
Hallo zusammen, erstmal vielen dank für die zahlreichen Antworten. Es scheint am Puffer gelegen zu haben, nachdem ich jetzt nicht mehr bei jedem Durchlauf sondern im Intervall von 100ms sende melden sich 10 von 11 Modulen korrekt bei der Zentrale. Auf meinem Testaufbau kann ich zZ nur maximal 8 Teilnehmer gleichzeitig testen. Da sind alle da (Test Modul1 - 8 und Test Modul 4 -11) auf meiner Modellbahn meldet sich modul 1 nicht korrekt an, hier kann der Fehler aber auch an dem Aufbau liegen. Muß ich noch in Ruhe testen. Ich bin aber schon viel weiter. Vielen Dank dafür Zum Eintrag von Uwe: Ja mangelndes Konzept, da stimme ich dir zu. Ich bin noch blutiger Anfänger und lerne noch. Die CAN Sachen hab ich aus der CAN Bibliothek und so für mich umgestrickt das es funktioniert, oder halt auch nicht ;-) Ich hatte anfänglich das Konzept des "immer sendens alle 200ms". Dabei funktionierte ab 6 teilnehmern die Kommunikation gar nicht mehr. Wenn ich mit einem Intervall von 1 Sekunde sende geht es zumindest mit 10. Aber auch ab dann geht keinerlei Kommunikation mehr. Intervalle über 200ms gehen auch nicht, da auf Ereignisse sofort reagiert werden muß. Also hatte ich mir überlegt, das immer bei einem Zustandwechsel etwas gesendet wird. Zusätzlich noch im Zeitlichem Abstand von Zeit x nochmal der aktuelle Zustand gesendet wird. Nur falls mal eine Nachricht den Empänger nicht erreicht, Ich gebe zu über das Prinzip " die Slaves melden sich zunächst bei dem master (Zentrale) an und erst dann wird vom Master gesendet, hatte ich nicht auf dem Schirm. Klingt aber nach einem vernünftigen Plan. Dann wäre auch nicht schlimm wenn ein Modul mal einen reset macht oder sich aufhängt, nach der erneuten Anmeldung wird eh die Nachricht von der Zentrale an das Modul erneut gesendet. Auch das weitersenden nach der Empfangsbestätigung dürfte damit wegfallen. Das setzte ich dann so um Hierzu eine Frage: Würdet Ihr eine extra "Anmeldenachricht" dafür von den Slaves zum Master senden oder einfach die normale Nachricht (die sowieso später immer gesendet wird) senden und diese dann als "Anmeldung" an der Zentrale nutzen? Remote Frames nutze ich nicht
:
Bearbeitet durch User
Kay L. schrieb: > Wenn > ich mit einem Intervall von 1 Sekunde sende geht es zumindest mit 10. > Aber auch ab dann geht keinerlei Kommunikation mehr. Mal so nebenbei: Mit einem 8-Bit Atmega328 mit 16MHz und einem externen MCP2515 CAN-Controller verarbeite ich 1000 CAN-Botschaften pro Sekunde. Ohne Probleme oder irgendwelche verspäteten Botschaften. Ein STM32 mit internen CAN sollte sich da geradezu langweilen. Mir scheint in deiner Software ist noch irgendwo ein Fallstrick drin.
Thomas F. schrieb: > Kay L. schrieb: >> Wenn >> ich mit einem Intervall von 1 Sekunde sende geht es zumindest mit 10. >> Aber auch ab dann geht keinerlei Kommunikation mehr. > > Mal so nebenbei: Mit einem 8-Bit Atmega328 mit 16MHz und einem externen > MCP2515 CAN-Controller verarbeite ich 1000 CAN-Botschaften pro Sekunde. > Ohne Probleme oder irgendwelche verspäteten Botschaften. > > Ein STM32 mit internen CAN sollte sich da geradezu langweilen. > Mir scheint in deiner Software ist noch irgendwo ein Fallstrick drin. Da gebe ich dir vollkommen Recht. Ich lerne ja noch und nutze halt oft die Bibliotheken, die leider auch sehr häufig Fehler und/oder Umständliche Wege beinhalten. Oder auch Beispiel Codes die ich dann mit Try and error für mich passend mache. Da mir Erfahrung fehlt hab ich auch nicht immer das logischste Konzept parat. Aber egal, ich hab schon gefühlt 400 Millionen mal Programmabschnitt neu angefangen :-) ich bin ja bereits seit 4 Jahren an dem Projekt dran, hab damals bei null angefangen. ich bin deshalb auch für jeden Hinweis dankbar.
:
Bearbeitet durch User
Ein durchschnittlicher CAN-Bus in einem Auto hat 20-25% Buslast. Die Botschaften werden zyklisch alle 10 - 100 ms gesendet. Generell überträgt man zyklisch Statusmeldungen, deren Inhalt an die aktuellen Gegebenheiten angepasst wird. Das BCM sendet z.B. "Fernlicht an, Blinker links aus". Das Fernlicht sendet dann "ich bin an, kein Fehler", der Blinker "ich bin aus". Einzelne eventgetriggerte Ereignisse gibt es nur bei den Diagnosejobs. Alles andere wird zyklisch in festem Zeitraster gesendet.
Kay L. schrieb: > Hierzu eine Frage: Würdet Ihr eine extra "Anmeldenachricht" dafür von > den Slaves zum Master senden oder einfach die normale Nachricht (die > sowieso später immer gesendet wird) senden und diese dann als > "Anmeldung" an der Zentrale nutzen? Das liegt bei dir; ich empfehle eine andere Nachricht zu senden, da du im Fehlerfall (wenn sich ein Slave aufhängt und die Anmeldung zwischendrin kommt) gleich merkst, dass da was nicht stimmt.
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.