Problem mit der CANBUS Verbindung

Hallo Leute,
ich bin noch sehr neu in der Welt der Arduino Programmierung und konnte zu meinem Thema keine konkreten Antworten auf Google finden. Deshalb widme ich mich jetzt an euch und bedanke mich schon mal recht herzlichst!
Ich versuche gerade von einem Arduino eine CAN-Nachricht an einen anderen zu senden. Dafür nutze ich die CANBUS Shields von Keyestudio (MCP2515).
Auf der Wiki-Seite von Keyestudio finde ich nur einen Beispiel Code bei dem das Verfahren "Polling" genutzt wird.
https://wiki.keyestudio.com/KS0411_keyestudio_CAN-BUS_Shield

Ich würde das Empfangen der Daten aber gerne über Interrupts steuern, bekomme es aber absolut nicht hin sowas einzubauen.
Ich hoffe sehr, dass mir jemand helfen kann, da ich einfach nicht weiterkomme.

Liebe Grüße

shax233:
Ich würde das Empfangen der Daten aber gerne über Interrupts steuern, bekomme es aber absolut nicht hin sowas einzubauen.

Was hast Du bislang versucht?

receive_interrupt.ino wäre doch ein Anfang.

Wo hast du diesen Scetch dazu gefunden?
Ich habe es über ein Event Flag versucht (Interrupt Pin?) versucht, allerdings habe ich es nicht hinbekommen dieses zu setzen.

shax233:
Wo hast du diesen Scetch dazu gefunden?

Als Beispiel der Programmbibliothek. Für mich ist das ein guter Ausgangspunkt, um neue Hardware zu erkunden.

Danke schonmal für die Antwort.
Wenn ich auf der Website: KS0411 keyestudio CAN-BUS Shield - Keyestudio Wiki
auf die Library gehe finde ich dieses Beispiel nicht. Wie bist du zu der Library gekommen?
Tut mir sehr leid, dass ich so "dämliche" Fragen stelle, aber ich habe zu diesem CAN-Bus Shield nichts gefunden, außer den Beispiel Scatch auf der Seite und eine Dropbox mit Beispielen, von denen aber keins das interrupt.ino Scatch beinhaltet.

Ah, ich habe es jetzt gefunden, danke.
Allerdings verstehe ich den Unterschied der beiden Codes nicht wirklich.
In meinem Code checke ich doch auch in der loop-Schleife ob eine neue Botschaft angekommen ist, und wenn ja dann werte ich diese aus.

void loop() 
{
    tCAN message;
if (mcp2515_check_message()) 
  {
    if (mcp2515_get_message(&message)) 
    {

              
            for(int i=0;i<message.header.length;i++) 
              {
                nodePayload[i]=message.data[i];

In dem Beispiel "receive_interrupt" wird doch auch in der Loop-Schleife nur geprüft, ob das EventFlag = 1 ist und dann wird die CAN-Botschaft ausgewertet.

    attachInterrupt(0, MCP2515_ISR, FALLING); // start interrupt
}

void MCP2515_ISR()
{
    flagRecv = 1;
}

void loop()
{
    if(flagRecv) 
    {                                   // check if get data
        flagRecv = 0;                   // clear flag

        while (CAN_MSGAVAIL == CAN.checkReceive()) 
        {
       
            CAN.readMsgBuf(&len, buf);

            for(int i = 0; i<len; i++)
            {
                Serial.print(buf[i]);Serial.print("\t");
            }
            Serial.println();
        }

Der Unterschied wird mir hier leider nicht ersichtlich, bis auf den tatsächlichen Befehl Interrupt. Aber solange prüft er die Loop-Schleife ja trotzdem und es wird keine ISR aufgerufen.

shax233:
Ah, ich habe es jetzt gefunden, danke.

Bitte gerne, ein Anfang ist gemacht :slight_smile:

shax233:
Allerdings verstehe ich den Unterschied der beiden Codes nicht wirklich.
In meinem Code checke ich doch auch in der loop-Schleife ob eine neue Botschaft angekommen ist, und wenn ja dann werte ich diese aus.

Ich drehe Deine Frage mal um: Warum willst Du einen Interrupt verwenden?

Wenn Du keine sinnvolle Antwort findest, bedeutet dies, Du brauchst keinen.

Andererseits hast Du ein Shield, weshalb der Pin 2 des UNOs fest mit diesem Interrupt belegt ist. Du kannst den Pin ungenutzt lassen oder verschwenderisch für einen Interrupt verwenden, um einen Merker zu setzen. Mein leicht ironischer Unterton rührt von meiner Abneigung gegenüber Shields her, weil diese so "einfach" zu nutzen sind, daß gerne eine vernünftige Beschreibung gespart wird. Das gilt leider auch für Dein Shield von keyestudio. Aber es gibt noch schlechtere Beispiele.

Ich klinke mich da mal ein, weil das bei mir auch gerade hoch-aktuell ist.

Bei mir kommen Shields von SeeedStudio zum Einsatz, da kommt eine eigene Lib mit. Die Standard-CAN-Lib scheitert hier.

Dort wird im Interrupt-Beispiel der Ansatz verfolgt, beim Auftreten des Interrupts lediglich ein Flag zu setzen. Hintergrund: Ein CAN BUS-Frame ist ja kein Selbstzweck, der uC soll ja mit den empfangenen Daten irgendwas anstellen.

In meinem Fall erhält er den Befehl, das Ruder eines Schiffes auf eine Stellung von -100 bis +100 zu fahren, wobei 0 "geradeaus" heißt. Gleichzeitig überwacht er das Ruder anhand eines Winkelgebers. Wenn also als letzter CAN Frame eine +25 gekommen ist, muss er einen Motor ansteuern und das Ruder genau bei der Position zum Stehen bringen. Er muss also ständig den Ist- mit dem Soll-Wert vergleichen, während aber keine neuen CAN-Frames mehr kommen.

Man sieht: ohne Interrupt geht das nicht.

Viele Grüße
Jörg

joergpauly:
Man sieht: ohne Interrupt geht das nicht.

Nö, ich sehe das nicht. Ist aber egal, denn das wäre ein anderes Thema.

In diesem Thema ist es noch ungewiß.

shax233:
Der Unterschied wird mir hier leider nicht ersichtlich, bis auf den tatsächlichen Befehl Interrupt. Aber solange prüft er die Loop-Schleife ja trotzdem und es wird keine ISR aufgerufen.

Doch, die ISR würde ja aufgerufen, wenn ein Interrupt erkannt wird. Jedenfalls wird sie mit attachInterrupt() ja eingerichtet.
Da allerdings sollte der erste Parameter nicht einfach 0, sondern digitalPinToInterrupt(2) sein - wenn das Shield den Interrupt an Pin 2 bereitstellt. Ob der dann auf fallende oder steigende Flanke reagieren soll wäre auszuprobieren.

Vielleicht hilft es auch noch, das flagRecv als "volatile" zu deklarieren, denn es wird ja irgendwann an anderer Stelle verändert.

Davon abgesehen kann ich in diesem Fall den Vorteil des Interrupts auch nicht wirklich erkennen. Ob ein von der ISR gesetztes flagRecv oder checkMessage() zur Nachrichtenerkennung verwendet wird ist fast gleichwertig. Der Funktionsaufruf dürfte minimal mehr Ressourcen verbrauchen.

agmue:
Nö, ich sehe das nicht. Ist aber egal, denn das wäre ein anderes Thema.

Ok, hier vielleicht etwas OT, aber jetzt hast Du mich neugierig gemacht.

Edit sagt: Disregard everything after Hello!
Verwechslung mit digitalRead()...

also für CAN Botschaften auszutauschen sehe ich auch keine Notwendigkeit von Int.
Ausnahme, dein Programm ist mit anderen Dingen immer ausgelastet. Dann könnte es theoretisch sein, das du erst "irgendwann" zum Abholen des CAN Datensatz kommst, dieser aber vielleicht zwischenzeitlich schon mit der nächsten Nachricht überschrieben wurden ist. Dann ist die erste Info weg.

Aber wie weit bist du nun mit den mitgelieferten Beispielen? Mache einfache Schritte, sende im ersten Stepp zyklisch einen hochzählenden Wert an den zweiten Teilnehmer und lasse dir das im Terminal anzeigen. Wenn du das geschafft hast, biste quasi mit Senden und Empfangen am Ziel.

refo

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.