Mehrere CAN Teilnehmer

OP #7871988
Lesenswert?

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

Angehängte Dateien:
Persönliche Seite #7871997
Lesenswert?

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?

#7872007
Lesenswert?

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.
OP #7872009
Lesenswert?

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

OP #7872022
Lesenswert?

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

#7872024
Lesenswert?

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

#7872025
Lesenswert?

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?

#7872035
Lesenswert?

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.

#7872045
Lesenswert?

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.

OP #7872051
Lesenswert?

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

OP #7872065
Lesenswert?

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?

OP #7872068
Lesenswert?

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?

#7872074
Lesenswert?

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.

OP #7872075
Lesenswert?

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
  }
#7872086
Lesenswert?

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?

#7872112
Lesenswert?

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.

OP #7872128
Lesenswert?

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

#7872142
Lesenswert?

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!

#7872146
Lesenswert?

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.

OP #7872180
Lesenswert?

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
    }
OP #7872465
Lesenswert?

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.

#7872470
Lesenswert?

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;
#7872531
Lesenswert?

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.
OP #7872632
Lesenswert?

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

#7872662
Lesenswert?

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.

OP #7872676
Lesenswert?

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.

#7872699
Lesenswert?

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.

Angehängte Dateien:
#7872709
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren