Forum: Mikrocontroller und Digitale Elektronik Mehrere CAN Teilnehmer


von Kay L. (kgbrus)


Angehängte Dateien:

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

von Ronny M. (supertyp) Benutzerseite


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?

von Uwe (uhi)


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.

von Kay L. (kgbrus)


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

von Vanye R. (vanye_rijan)


Lesenswert?

> 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

von Kay L. (kgbrus)


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

von Frank K. (fchk)


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

von Georg S. (randy)


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?

von Peter D. (peda)


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.

von Thomas (kosmos)


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.

von Kay L. (kgbrus)


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

von Kay L. (kgbrus)


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?

von Kay L. (kgbrus)


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?

von Peter D. (peda)


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.

von Kay L. (kgbrus)


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
  }

von Peter D. (peda)


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?

von Rolf (rolf22)


Lesenswert?

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.

von Georg S. (randy)


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.

von Kay L. (kgbrus)


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

: Bearbeitet durch User
von Helmut -. (dc3yc)


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!

von Peter D. (peda)


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.

von Kay L. (kgbrus)


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
    }

: Bearbeitet durch User
von Uwe (uhi)


Lesenswert?

Dass in der Hälfte der Fälle, je nach counter, die ID etc nicht befüllt 
wird ist Absicht?

von Kay L. (kgbrus)


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.

von Kay L. (kgbrus)


Lesenswert?

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"?

von Thomas F. (igel)


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;

von Uwe (uhi)


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.

von Kay L. (kgbrus)


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

: Bearbeitet durch User
von Thomas F. (igel)


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.

von Kay L. (kgbrus)


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.

: Bearbeitet durch User
von Soul E. (soul_eye)


Angehängte Dateien:

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.

von Helmut -. (dc3yc)


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.

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.