Auswerten von bekannten Can Bus Nachrichten

Hallo zusammen,
ich habe es geschafft nach einigen Versuchen Can Bus Nachrichten mit zu lesen und auf das Bussystem zu senden. Einige Nachrichten besitzen jedoch einen Counter. Damit ich diese Funktionen ansteuern kann, muss ich immer wissen bei welcher Zahl der Counter aktuell steht, damit die Nachricht akzeptiert wird. Nun ist mein Gedanke den Can Bus auf die Nachricht der benötigten Funktion zu filtern. Wird nun die Funktion betätigt, will ich dass der aktuelle Counterstand gespeichert wird und um eins erhöht wird. Beim Betätigen eines Knopfes soll somit sichergestellt werden, dass immer eine Nachricht mit dem aktuellen Counterstand auf das Bussystem gesendet wird. Wie würdet ihr dies realisieren?

Hallo,

wenn du die Daten vom Bus lesen und senden kannst, dann musst du ja das Protokoll kennen und programmiert haben. Damit weißt du auch an welcher Stelle welche Daten stehen. Ich verstehe dein Problem noch nicht so ganz.
Beherrschst du die Grundlagen von Eingänge einlesen, auf Taster reagieren, zählen entprellter Tasterbetätigungen usw.?
Wenn nicht und es ganz einfach werden soll, es gibt eine Bounce2 Lib

Damit kannste dich mittels Taster austoben und gezielt Werte ändern. Wenn alles verstanden kannste das in dein Konzept einbauen.

Danke für die Antwort! Das reine auslesen und senden beherrsche ich. Dadurch habe ich festgestellt, dass durch den Counter sich die akzeptierte Nachricht jedes Mal um eins erhöhen muss.
System sendet .......05, damit die Funktion beim nächsten Mal akzeptiert wird muss die Nachricht dann ......06 lauten. Da sowohl das System senden kann als auch ich über einen Taster, will ich die letzte Nachrichten speichern und jedes Mal um eins erhöht beim Taster hinterlegen. Dadurch würde die Nachricht vom Taster dann immer akzeptiert.
Mein Problem ist, dass mir nicht so ganz klar ist wie ich nur das eine Byte immer neu abspeichere in der Senden Funktion.

Um diese Frage zu beantworten, müssten wir Deine Sendefunktion kennen. Ganz allgemein musst Du eine (statische) Variable erhöhen.

Hast Du bedacht, dass nach Deinem Senden mit der erhöhten Nummer die Sendung vom originalen System nie mehr durch kommt, da das dann in der Nummerierung immer hinterher hinkt?

Gruß Tommy

Die Nummerierung vom originalen System passt sich glücklicherweise automatisch an. Das konnte ich bei meinen ersten Tests schon feststellen. Dies ist nun für mein System auch erforderlich. Ich habe mir mal einen Ablaufplan skizziert und im Anhang beigefügt. Sollte man für die Realisierung lieber zwei Mikrocontroller verwenden (einer für das empfangen und einer für das Senden) oder kann man ohne Bedenken nur einen Benutzen. An dem Mikrocontroller will ich ein Tablet anschließen. Durch das Betätigen einer Taste soll die Funktion 1 mit der richtigen Can Nachricht versendet werden. Beim betätigen der Funktion 1 werden 4 Can Bus Nachrichten versendet.

Da die Nachrichten sehr schnell hintereinander gesendet werden, muss der Mikrocontroller diese schnell einlesen und verarbeiten können. Damit er die Nachrichten nicht alle speichern muss, will ich diese direkt weiter an das Tablet senden und dort verarbeiten. Würdet ihr dies auch so machen und mit welcher Funktion? Mein erster Ansatz ist mit der Funktion Keyboard.print. Allerdings weiß ich nicht, ob es mit ihr einfach möglich ist die Daten nachher auf dem Tablet weiter zu verarbeiten?

void loop()
{
  if(!digitalRead(CAN0_INT))                                    // Eigentlich überflüssig?
  {
    CAN0.readMsgBuf(&rxId, &len, rxBuf);                        // Daten lesen: rxId= ID; len= Länge; rxBuf= Daten
    
    if(rxId ==15F and rxBuf[0] ==0x01 and rxBuf[1] ==0x02 and rxBuf[2] ==0x04 )                       

      Serial.print(rxId, HEX);                                  // nur zum Testen nötig
      Serial.print("   ");                                      // "        "        "
      Serial.print(rxBuf[1]);                                   // "        "        "
      Serial.println();                                         // "        "        "
  
      if(rxBuf[3] ==0x03 and rxBuf[4] ==0x09 and rxBuf[5] ==0x00)                         
      {
        Keyboard.print("Funktion1");                                    // Senden Funktion1
      }
      if(rxBuf[3] ==0x03 and rxBuf[4] ==0x09 and rxBuf[5] ==0x80)                        
      {
        Keyboard.print("Funktion1counter");                             // Senden Funktion1counter
      }
      if(rxBuf[3] ==0x04 and rxBuf[4] ==0x08 and rxBuf[5] ==0x80)                      
      {
        Keyboard.print("Funktion2");                                    // Senden Funktion2
      }
      if(rxBuf[2] ==0x04 and rxBuf[4] ==0x08 and rxBuf[5] ==0x80)                         
      {
        Keyboard.print("Funktion2counter");                             // Senden Funktion2counter
      }
    }
  } 
}

Welchen Arduino verwendest Du? Nicht alle können als Keyboardemulation arbeiten.

Gruß Tommy

Ich besitze 2x (ARD SHD CAN V2 Arduino Shield - CAN-BUS v2, MCP2515 / MCP2551) und 2x Seeduino 4.2). Ist die Funktion dafür geeignet? Würdest du einen oder zwei Mikrocontroller verwenden?

https://www.reichelt.de/de/de/arduino-shield-can-bus-v2-mcp2515-mcp2551-ard-shd-can-v2-p247102.html?PROVID=2788&gclid=EAIaIQobChMI-66qvej86wIVhPuyCh2eOwC7EAQYASABEgLVDfD_BwE&&r=1
https://www.reichelt.de/seeeduino-v4-2-seeeduino-v4-2-p243397.html?PROVID=2788&gclid=EAIaIQobChMIxZbMz-j86wIVGOJ3Ch3L5AA_EAQYASABEgKenfD_BwE

Mit schnell meine ich 10-20 Nachrichten pro Sekunde. Es gibt ja glaube ich Befehle die sehr langsam sind.

jotti:
Mit schnell meine ich 10-20 Nachrichten pro Sekunde.

bei so präzisen Angaben bleibt mir nur: "geht locker".
Wie wärs mit ein paar Angaben zu Bus-Geschwindigkeit, Quartz-Frequenz am Can-Board und Nachrichtenlänge?

Limitierende Faktoren sind da wohl eher eine langsame Ausgabe auf die Serielle oder das Weiterreichen über Keyboard?!?

Und dann bleibt immer noch: setz halt Filter im Controller auf die Nachrichten die dich wirklich interessieren, dann macht das schon der CAN Controller und du "belastet" den Uno nicht (und auch nicht den SPI Bus).

Kannst vieleicht mal genauer beschreiben was das ganze Projekt wird, warum muss eine Nachricht auf das Tablet um dann verändert wieder in den Bus zu gehen?
Trennst du das Gerät das diese Can-Bus Nachricht senden aus dem Can-Bus Raus? ... dein Arduino macht so zu sagen eine Man-In-The-Middle Attacke? Schaut aber auf deinem Bild nicht so aus.
Was hilft dir dann eine veränderte Nachricht (vom Tablet), wenn die Steuereinheit die Original-Nachricht vom Steuergerät schon lange hat?

Das ursprüngliche Bussystem bleibt vollständig erhalten. Ich will ein paar Funktionen bei einer Anlage ebenfalls von einer anderen Seite ansteuern können. Da die Befehle nur akzeptiert werden, wenn die Counterzahl stimmt, muss meine neue Steuereinheit die Befehle von der ursprünglichen Steuereinheit auch einlesen und die zusendenden Nachrichten immer anpassen. Da ich die Steuerung über ein Tablet realisieren will, dachte ich speichere ich hier auch die Nachrichten. Es sind später 8 verschiedene Can Bus Nachrichten a 8 Byte die gespeichert werden müssen. Die Busgeschwindigkeit beträgt 250 kbits/s.

wie kann die Counterzahl für die "Steuereinheit" stimmen, wenn da plötzlich ein weiterer Teilnehmer (tablet) den Counter "hochdreht".
der alte Teilnehmer "Steuergerät" ist dann außer sync und hat immer noch die alte Nummer+1 und würde daher nach dem Tablet eine falsche Nummer schreiben.
... das kann doch so nicht funktionieren - oder ist für mich nicht plausibel - oder ist anders als du beschreibst.

Ich denke, dass die Steuereinheit auch die Daten irgendwie einliest. Es funktioniert auf jedenfalls und er sendet dann die erhöhte Busnachricht auch nach mehrmaligem Betätigen durch den nicht vorgesehenen externen Teilnehmer. Sende ich allerdings von externer Seite die Nachricht mit einem falschen Counterstand deaktiviert die Software sofort die Steuereinheit. Ich habe jetzt mal einzelnen Programmausschnitte, die ich benötigen werde, einzeln getestet.
Das Einbinden eines Zählers in der Can Bus Nachricht funktioniert noch nicht. Der Counter zählt im seriellen Monitor hoch aber die gesendetet Nachricht enthält dauerhaft die Botschaft 01 an der Stelle des Counters und erhöht sich nicht. Wie muss ich dies umsetzen.

#include <mcp_can.h>
#include <SPI.h>

/*SAMD core*/
#ifdef ARDUINO_SAMD_VARIANT_COMPLIANCE
    #define SERIAL SerialUSB
#else
    #define SERIAL Serial
#endif

// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9;
int counter=1;

MCP_CAN CAN(SPI_CS_PIN);                                    // Set CS pin

void setup() {
    SERIAL.begin(115200);

    while (CAN_OK != CAN.begin(CAN_500KBPS)) {            // init can bus : baudrate = 500k
        SERIAL.println("CAN BUS Shield init fail");
        SERIAL.println(" Init CAN BUS Shield again");
        delay(100);
    }
    SERIAL.println("CAN BUS Shield init ok!");
}

unsigned char stmp[8] = {1, 2, 3, 4, 5, 6, counter, 0};

void loop() {
  
    SERIAL.println("In loop");
    // send data:  id = 0x70, standard frame, data len = 8, stmp: data buf
    CAN.sendMsgBuf(0x70, 0, 8, stmp);
    counter++;
    SERIAL.println( counter );
    delay(1000);                       // send data once per second
}

Hat sich erledigt. Habe die Nachricht in die Schleife gesetzt und jetzt funktioniert es.

jotti:
Hat sich erledigt. Habe die Nachricht in die Schleife gesetzt und jetzt funktioniert es.

Ich wollte gerade den Trecker aus der Garage holen :grin: