MCP2515 Grundlage Frage

Moin,

ich bastele gelegentlich für meine Modellbahn mit Arduinos herum. Ich habe schon eine Drehscheibe mit Bedienpult gebaut, welche über den CAN-BUS kommuniziert.
Nun wollte ich Weichensteuerungen über den CAN-BUS bauen und verzweifle ein wenig.
Ich möchte dazu den CAN-BUS verstehen und nicht einfach nur, wie ich es bei der Drehscheibe gemacht habe, kopieren. Bei der Drehscheibe hatte ich zwei Megas, die miteinander kommuniziert haben. Nun brauche ich Nanos

Nun zu meiner Frage:

  • Ich habe ein Nano(NoName) mit einem fertigen MCP2515 Modul verbunden.
  • Ich habe von der Lib das BeispielSketch CAN_Senden genommen, den CS_Pin angepaßt und übertragen.
  • Nun kommt im Seriellen Monitor folgende Ausgabe:

Entering Configuration Mode Successful!
Setting Baudrate Successful!
MCP2515 Initialized Successfully!
Error Sending Message...

letzteres andauernd.
Muß der CAN-BUS immer min. eine Gegenstelle haben?
Oder warum kommen nur Fehlermeldungen, beim Senden?

Kann mir da jemand weiter helfen?

Gruß
Harald

Meine CAN Ahnung ist arg begrenzt.

Leider hältst du geheim welche Library du nutzt.
Welcher Error genau auftritt
Den Code welchen du verwendest.
Ob die Abschlusswiderstände montiert/aktiv sind.

Bisher habe ich da noch nicht explizit drauf geachtet, aber ich denke schon. Möglicherweise ist nicht nur eine Gegenstelle, sondern auch ein quittierender Empfänger der Nachricht notwendig. Eventuell haben auch die Filter Einfluß.

Moin,

ich halte nix geheim. Mir war nur nicht bewußt, daß die Lib, die ich benutzte auf die grundlegenden Eigenschaften eines CAN-BUSses Auswirkungen hat. Okay, ich bin halt noch Anfänger und in so etwas wohl zu naiv.
Meine Lib: GitHub - coryjfowler/MCP_CAN_lib: MCP_CAN Library
Mein Modul: https://i.ebayimg.com/images/g/sjYAAOSwYc5Z7BQI/s-l1600.jpg
Ich verwende die CAN-Senden Code der unter Examples zu finden ist.
Gruß
Harald

Moin, danke für die Einschätzung, jedoch verstehe ich nicht, welche Gegenstelle sich denn dann meldet, wenn sie keine angeschlossene für die Daten interessiert. Es gibt im CAN-BUS doch keinen Master, der alles regelt. Also müßte dies ja irgend einer übernehmen. Und woher weiß derjenige, daß er es tun soll? Oder machen es Alle? Wenn ich 100 Anschlüsse haben, explodiert doch die Leitung nur wegen der Quittung.
Sorry, ich verstehe es nicht.

Gruß
Harald

Moin, die 2.

Die Fehlermeldung habe ich bereits gepostet.:
Error Sending Message...
Die kommt aus dem Code. Und bedeutet, Nachricht konnte nicht gesendet werden. Wenn ich den Code richtig verstanden habe.

Gruß
Harald

Als ich meinen Text schrieb, kamen mir auch Zweifel wegen der mehreren Empfänger, die möglich sind. Aber diese Fehlermeldung habe ich auch schon gelesen.

Meine Ausführungen zu UNO - Mega - Teensy mittels CAN-Bus verbinden werden Dir vermutlich auch nicht helfen.

Aber das läßt sich herausfinden :thinking:

Fast, CAN ist ein Multimaster Bus.
Lese mal wie der funktioniert.
Sehr gute Beschreibung

Wenn mich nicht irre brauch man keine Bestätigung, alle Nodes hören zu, der für wen die Nachricht ist reagiert.

Ich bin ja nicht blind.

Die Lib liefert dir 9 verschiedene Error Codes.
Hier MCP_CAN_lib/mcp_can_dfs.h at master · coryjfowler/MCP_CAN_lib · GitHub nachzulesen.
Du wertest offensichtlich nur auf Erfolg aus.
Das ist für eine Diagnose zu wenig.

Meine Frage war:
Welche dieser Meldungen kommt?

Das "Warum?" interessiert dich nicht?

Jain!
Im Allgemeinen hast du recht.

Der jeweilige Master kann allerdings einfordern, dass sein Paket mit einem ACK bestätigt wird.
Beispiel:
KFZ Bremslicht, da ist eine Bestätigung von Nöten.

CAN Receive Example
// MCP2515 - UNO
// SCK - 13
// SI  - 11
// SO  - 12
// CS  - 10
// https://web.archive.org/web/20190916005524/http://henrysbench.capnfatz.com/henrys-bench/arduino-projects-tips-and-more/arduino-can-bus-module-1st-network-tutorial/
// CAN Receive Example der Bibliothek https://github.com/coryjfowler/MCP_CAN_lib
#include <mcp_can.h>
#include <SPI.h>

long unsigned int rxId;
unsigned char len = 0;
unsigned char rxBuf[8];
char msgString[128];                        // Array to store serial string

#define CAN0_INT 2                              // Set INT to pin 2
MCP_CAN CAN0(10);                               // Set CS to pin 10


void setup()
{
  Serial.begin(115200);
  delay(500);
  
  // Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled.
  if(CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ) == CAN_OK)
    Serial.println("MCP2515 Initialized Successfully!");
  else
    Serial.println("Error Initializing MCP2515...");
  
  CAN0.setMode(MCP_NORMAL);                     // Set operation mode to normal so the MCP2515 sends acks to received data.

  pinMode(CAN0_INT, INPUT);                            // Configuring pin for /INT input
  
  Serial.println("MCP2515 Library Receive Example...");
}

void loop()
{
  delay(1000);
  /*
  if(!digitalRead(CAN0_INT))                         // If CAN0_INT pin is low, read receive buffer
  {
    CAN0.readMsgBuf(&rxId, &len, rxBuf);      // Read data: len = data length, buf = data byte(s)
    
    if((rxId & 0x80000000) == 0x80000000)     // Determine if ID is standard (11 bits) or extended (29 bits)
      sprintf(msgString, "Extended ID: 0x%.8lX  DLC: %1d  Data:", (rxId & 0x1FFFFFFF), len);
    else
      sprintf(msgString, "Standard ID: 0x%.3lX       DLC: %1d  Data:", rxId, len);
  
    Serial.print(msgString);
  
    if((rxId & 0x40000000) == 0x40000000){    // Determine if message is a remote request frame.
      sprintf(msgString, " REMOTE REQUEST FRAME");
      Serial.print(msgString);
    } else {
      for(byte i = 0; i<len; i++){
        sprintf(msgString, " 0x%.2X", rxBuf[i]);
        Serial.print(msgString);
      }
    }
        
    Serial.println();
  }
  */
}

/*********************************************************************************************************
  END FILE
*********************************************************************************************************/ 
CAN Send Example
// MCP2515 - UNO
// SCK - 13
// SI  - 11
// SO  - 12
// CS  - 10
// http://henrysbench.capnfatz.com/henrys-bench/arduino-projects-tips-and-more/arduino-can-bus-module-1st-network-tutorial/
// CAN Send Example der Bibliothek https://github.com/coryjfowler/MCP_CAN_lib
#include <mcp_can.h>
#include <SPI.h>

MCP_CAN CAN0(10);     // Set CS to pin 10

void setup()
{
  Serial.begin(115200);
  delay(500);

  // Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled.
  if (CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ) == CAN_OK) Serial.println("MCP2515 Initialized Successfully!");
  else Serial.println("Error Initializing MCP2515...");

  CAN0.setMode(MCP_NORMAL);   // Change to normal mode to allow messages to be transmitted
}

byte data[8] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};

void loop()
{
  // send data:  ID = 0x100, Standard CAN Frame, Data length = 8 bytes, 'data' = array of data bytes to send
  byte sndStat = CAN0.sendMsgBuf(0x100, 0, 8, data);
  meldung(sndStat);
  if (sndStat == CAN_OK) {
    Serial.println("Message Sent Successfully!");
  } else {
    Serial.println("Error Sending Message...");
  }
  delay(1000);   // send data per 100ms
}

void meldung(const byte stat)
{
  switch (stat)
  {
    case 0: Serial.print(F("CAN_OK             ")); break;
    case 1: Serial.print(F("CAN_FAILINIT       ")); break;
    case 2: Serial.print(F("CAN_FAILTX         ")); break;
    case 3: Serial.print(F("CAN_MSGAVAIL       ")); break;
    case 4: Serial.print(F("CAN_NOMSG          ")); break;
    case 5: Serial.print(F("CAN_CTRLERROR      ")); break;
    case 6: Serial.print(F("CAN_GETTXBFTIMEOUT ")); break;
    case 7: Serial.print(F("CAN_SENDMSGTIMEOUT ")); break;
    case 0xff: Serial.print(F("CAN_FAIL       (0xff")); break;
  }
  Serial.println();
}
/*********************************************************************************************************
  END FILE
*********************************************************************************************************/
Ausgabe
13:00:35.522 -> Entering Configuration Mode Successful!
13:00:35.522 -> Setting Baudrate Successful!
13:00:35.522 -> MCP2515 Initialized Successfully!
13:00:35.569 -> CAN_OK             
13:00:35.569 -> Message Sent Successfully!
13:00:36.554 -> CAN_OK             
13:00:36.554 -> Message Sent Successfully!
13:00:37.538 -> CAN_OK             
13:00:37.538 -> Message Sent Successfully!
13:00:38.569 -> CAN_OK             
13:00:38.569 -> Message Sent Successfully!
13:00:39.554 -> CAN_OK             
13:00:39.554 -> Message Sent Successfully!
13:00:40.538 -> CAN_OK             
13:00:40.538 -> Message Sent Successfully!
13:00:41.548 -> CAN_SENDMSGTIMEOUT 
13:00:41.548 -> Error Sending Message...
13:00:42.569 -> CAN_SENDMSGTIMEOUT 
13:00:42.569 -> Error Sending Message...
13:00:43.553 -> CAN_SENDMSGTIMEOUT 
13:00:43.553 -> Error Sending Message...
13:00:44.585 -> CAN_GETTXBFTIMEOUT 
13:00:44.585 -> Error Sending Message...
13:00:45.569 -> CAN_GETTXBFTIMEOUT 
13:00:45.569 -> Error Sending Message...
13:00:46.574 -> CAN_GETTXBFTIMEOUT 
13:00:46.574 -> Error Sending Message...
13:00:47.561 -> CAN_GETTXBFTIMEOUT 
13:00:47.561 -> Error Sending Message...
13:00:48.566 -> CAN_OK             
13:00:48.566 -> Message Sent Successfully!
13:00:49.550 -> CAN_OK             
13:00:49.597 -> Message Sent Successfully!
13:00:50.571 -> CAN_OK             
13:00:50.571 -> Message Sent Successfully!
13:00:51.555 -> CAN_OK             

Die Meldung CAN_GETTXBFTIMEOUT kommt, wenn ich beim Empfänger den USB-Stecker abziehe.

Vorläufige Einschätzung: Mindestens eine Gegenstelle muß elektrisch vorhanden sein, auch wenn sie die Daten nicht empfängt.

@Sensibelchen_HH: An der Stelle könntest Du selbst weiter testen :slightly_smiling_face:

Hmmm....

Die Frage ist:

Die beiden Abschlusswiderstände sind nötig, sonst ist es kein Bus.
Soviel steht fest!

Wie auch immer, ich bin jetzt hiermit auch an meinem Ende angekommen.

Meine Erfahrung:
Bisher haben meine CAN Installationen sofort geklappt.
Ausnahme: Hatte Module mit 8MHz Quarz und welche mit 16MHz
Hat ein bisschen gedauert, bis ich das begriffen hatte. Es der Lib mitgegeben, dann liefen die auch zusammen, ohne Probleme.

Moin,

danke erst einmal für die viele Hilfe.
"Ich" werte nur das aus, was in dem Beispielcode programmiert wurde. Ich habe dies ausgewählt, um zu begreifen, was wie läuft. Und ja, es interessiert mich, warum etwas nicht geht, deshalb frug ich hier.

Ich habe nun das abgeänderten Code gestartet und erst kommt 3 mal die Meldung:
CAN_SENDMSGTIMEOUT
Error Sending Message...

und anschließend:
CAN_GETTXBFTIMEOUT
Error Sending Message...

Also wenn die Letztere kommt, wenn keine Gegenstelle da ist, bedeutet es wohl, daß er keine "Antwort" erhält. Aber was bedeutet die erste Meldung?

"ich muß erst warm werden" oder was?

Ich müßte also als Erstes min einen weiteren MCP2515 am Bus haben und beim Senden Abfragen, ob die Nachricht rausgegangen ist.

Gruß
Harald

PS. Meine Module haben alle 8MHz. Aber das wußte ich vor dem ersten Projekt und hatte seit dem immer darauf geachtet, daß der Wert richtig angegeben wurde.

Im Datenblatt zum MCP2515 gibt es ein Kapitel "ERROR DETECTION", das zu lesen sich lohnen könnte. Dazu kannst Du in die Bibliothek schauen, wie dort die Fehlermeldungen mit den Codes des MCP2515 zusammenhängen.

Weil die Bibliotheksbeispiele nur CAN_OK auswerten, führt mich das zu der Annahme, die anderen Zustände zu unterscheiden ist nicht von Wert.

Du schickst also so lange eine Nachricht, bis CAN_OK kommt, dann wartest Du auf die Antwort des Empfängers als Quittung.

Du könntest auch mal mit anderen Bibliotheken vergleichen, ob es dort andere Meldungen gibt. ESP32 und Teensy haben eigene Hardware für CAN-BUS eingebaut, die haben andere Register, also eventuell auch andere Meldungen.

Moin,

mit diesen Datenblättern komme ich irgendwie nicht klar. Meistens auch nur auf englisch, wo ich sofort aussteige.
Ich probiere es dann lieber aus, jedoch muß es für mich irgendwie nachvollziehbar sein.
Bei meiner Drehscheibe habe ich die Kommunikation selbst überlegt und die funktioniert. Ich kann sogar weitere Bedienpulte bauen und anschließen und das sollte laufen. Aber der CAN-Bus lief von Anfang an ohne Probleme, was nun nicht der Fall war.
Okay, bei der Drehscheibe hatte ich einen CAN-USB oder CAN-Ethernet Adapter dran. Der hat dann wohl die Meldungen erzeugt, die mir jetzt fehlen. Was der genau gemacht hat, weiß ich nicht. Der gab mir nur die Daten für den Bus vor und machte den Bus RocRail tauglich. Aber aktuell habe ich keinen mehr davon. Damals hatte ich ihn, weil über den die 12V Spannungsversorgung kam, über die ich fast alles betrieben habe. Nun habe ich eine andere Stromversorgung und diesen Adapter nicht dran.
Ich werde es mal probieren min einen zusätzlichen MCP2515 in den Bus zu klemmen. Mal sehen was dann passiert.

Gruß
Harald

Mann kann auch PDF mit Deepl übersetzen

Moin,

okay, kannte ich noch nicht. Aber leider funktioniert das irgendwie nicht.
ABER, bevor hier nun eine Diskussion draus wird, wie die Seite funktioniert, habe ich mir eine andere Seite gesucht und gefunden, die es gemacht hat. :slight_smile:

Nun habe ich einiges zu lesen. Ich probiere weiter und werde berichten.

Danke
Gruß
Harald

Ich habe den Eindruck, irgendwo lauert ein Mißverständnis.

Für mich liest sich dieser Satz, als würdest Du versuchen, nur mit einem MCP2515 einen Bus aufzubauen, was natürlich nicht geht. Da Du das weißt frage ich mich, ob es noch einen dritten Teilnehmer gibt, den nur Du kennst? Oder hast Du nur den Satz unglücklich formuliert?

Was Du da zu RocRail und dergleichen schreibst, ist mir leider gänzlich unklar.

Da mein CAN-BUS tut, was er soll, brauchst Du nur zu antworten, wenn Du noch weiter Hilfe von mir in Anspruch nehmen möchtest.

Ja bitte, davon lebt dieses Forum :slightly_smiling_face:

Moin,

Jain,
Ich war der Annahme, daß man keinen BUS an sich braucht, um eine Kommunikation aufzubauen und zu testen. Ich brauche ja auch keine Räder an einem Auto um zu sehen ob sich der Motor und dann die Räder drehen würden um zu fahren.
ABER:
kurzer Zwischenbericht.
Ich habe nun einen BUS, wie Du es nennst, aufgebaut. Also ZWEI MCP2515 mit je einem Arduino. Allerdings an einem Rechner.
Der eine hat den Senden-Code und der andere den etwas veränderten Receive-Code.
Der Sender meldet weiterhin die Fehler, aber der Empfänger empfängt alle Sendungen vollständig.
Nun bin ich mehr als verwirrt.
Was sagen die Fehlermeldungen: "CAN_SENDMSGTIMEOUT" und "CAN_SENDMSGTIMEOUT" denn nun wirklich aus? Darüber habe ich noch nirgends etwas gefunden. Was mache ich falsch?
Ich nehme doch die Beispiel-Sketche.

Gruß
Harald

PS: RocRail ist ein Steuerungsprogramm für Modellbahnen. Und die Signale auf den CAN, sollen in den PC kommen, damit dieses Programm damit etwas anfangen kann und Steuerungen vornehmen kann.

Wen Du so wie so wie ich verstanden habe die Steuerung mit PC machen willst dan hol dir doch ein USB CAN Adapter damit brauchst den 2 Ardu nicht mehr