CAN 2.0 Frames mit Arduino senden

Hallo Arduino-Freunde,

ich heiße Jan und mache gerade meine ersten Arduino "Gehversuche". Ich habe vor auf dem CAN Bus eines Fahrzeugs auf Knopfdruck 6 Frames zu senden. Es handelt ein 500kBaud Standard Frame (11Bit ID) Highspeed-CAN.
Screenshot 2022-02-19 142715
Als Hardware habe ich von der Firma Longan-Labs den CANbed v1.2 beschafft. Dieser ist für meinen Einsatz denke ich die idealste, schlankste Lösung.
In der Bibliothek war ein Beispiel zum Senden einer Botschaft. Jetzt ist das für mich leider etwas undurchsichtig und ich weiß nicht recht wo ich meine Daten entsprechend einfügen muss. Und zudem noch wie ich meinen Taster an einem Digitaleingang in die Operation einfüge.

Dies ist das Script:

// send a frame from can bus

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

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

const int SPI_CS_PIN = 17;              // CANBed V1
// const int SPI_CS_PIN = 3;            // CANBed M0
// const int SPI_CS_PIN = 9;            // CAN Bus Shield

MCP_CAN CAN(SPI_CS_PIN);                                    // Set CS pin

void setup()
{
    Serial.begin(115200);
    while(!Serial);
    while (CAN_OK != CAN.begin(CAN_500KBPS))    // init can bus : baudrate = 500k
    {
        Serial.println("CAN BUS FAIL!");
        delay(100);
    }
    Serial.println("CAN BUS OK!");
}

unsigned char stmp[8] = {0, 0, 0, 0, 0, 0, 0, 0};
void loop()
{
    // send data:  id = 0x00, standrad frame, data len = 8, stmp: data buf
    stmp[7] = stmp[7]+1;
    if(stmp[7] == 100)
    {
        stmp[7] = 0;
        stmp[6] = stmp[6] + 1;
        
        if(stmp[6] == 100)
        {
            stmp[6] = 0;
            stmp[5] = stmp[6] + 1;
        }
    }
    
    CAN.sendMsgBuf(0x00, 0, 8, stmp);
    delay(100);                       // send data per 100ms
}

// END FILE

Ich erkenne wie die Baudrate festgelegt wird und die Anzahl der Daten Bytes sowie die Festlegung der ID.
Ich würde gerne an einen Digitaleingang eine Spannung von einem Taster anlegen als Trigger. Wie muss ich das dort einfügen?

Wäre super wenn mir jemand eine Hilfestellung geben kann wie ich meine Frames dort einfüge und die Operation mit meinem Taster :slight_smile:
Vielen Dank!
Gruß Jan

Meinst Du so?

Standard ID: 0x641       DLC: 8  Data: 0x02 0x10 0x03 0xAA 0xAA 0xAA 0xAA 0xAA
-----------------------------
Standard ID: 0x641       DLC: 8  Data: 0x03 0x22 0xF1 0x00 0xAA 0xAA 0xAA 0xAA
-----------------------------
Standard ID: 0x641       DLC: 8  Data: 0x03 0x22 0xF1 0x54 0xAA 0xAA 0xAA 0xAA
-----------------------------
Standard ID: 0x641       DLC: 8  Data: 0x03 0x22 0x02 0x00 0xAA 0xAA 0xAA 0xAA
-----------------------------
Standard ID: 0x641       DLC: 8  Data: 0x02 0x3E 0x00 0xAA 0xAA 0xAA 0xAA 0xAA
-----------------------------
Standard ID: 0x641       DLC: 8  Data: 0x04 0x31 0x01 0x03 0x0D 0xAA 0xAA 0xAA
-----------------------------

Oder ist "641" dezimal gemeint?

Kommst Du da nicht mit irgendwelchen Vorschriften in Konflikt, wenn Du daran rumfummelst?

DATEI - BEISPIELE - 02. Digital

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


const int SPI_CS_PIN = 17;              // CANBed V1
// const int SPI_CS_PIN = 3;            // CANBed M0
// const int SPI_CS_PIN = 9;            // CAN Bus Shield

const byte tastePin = 2;
bool gedrueckt = false;
MCP_CAN CAN(SPI_CS_PIN);                                    // Set CS pin

void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start..."));
  while (!Serial);
  while (CAN_OK != CAN.begin(CAN_500KBPS))    // init can bus : baudrate = 500k
  {
    Serial.println("CAN BUS FAIL!");
    delay(100);
  }
  Serial.println("CAN BUS OK!");
  digitalWrite(tastePin, LOW);
  pinMode(tastePin, INPUT_PULLUP);
}

unsigned char stmp[6][8] =
{
  {0x02, 0x10, 0x03, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA},
  {0x03, 0x22, 0xF1, 0x00, 0xAA, 0xAA, 0xAA, 0xAA},
  {0x03, 0x22, 0xF1, 0x54, 0xAA, 0xAA, 0xAA, 0xAA},
  {0x03, 0x22, 0x02, 0x00, 0xAA, 0xAA, 0xAA, 0xAA},
  {0x02, 0x3E, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA},
  {0x04, 0x31, 0x01, 0x03, 0x0D, 0xAA, 0xAA, 0xAA}
};

void loop()
{
  if (!digitalRead(tastePin) && !gedrueckt)
  {
    gedrueckt = true;
  }
  if (gedrueckt)
  {
    // Und hier kommt dann die Übergabe
  }
}
// END FILE

Wenn Du die Beispiele beherrschst, kommt der Rest allein.

Sein Fahrzeug aus dem VW-Baukasten.
Wenn das Steuergerät das ohne Verifikation versteht...

Was weißt Du, was ich, bezogen auf dieses Thema, wissen sollte?

Ich bin noch am überlegen, ob es Audio oder Navi sein kann...
Leider zulange da raus.
Hast Du ja schon gemerkt (freundlichster! Seitenhieb)

:upside_down_face: :slightly_smiling_face:

vielleicht auch: Weder; noch...

https://www.neohysens.de/assets/media/downloads/neohysens/Datenblatt_Sensorsystem_NEO974A_V001.pdf

Hallo,
vielen Dank für eure Antworten!
Es handelt sich um einen Innenraum CAN Bus und ich möchte durch das Senden der Botschaften im Multimedia Display mir die Suche durch eine endlose Menüführung verkürzen. Also quasi eine Direktwahltaste für eine Funktion im Display erstellen.

Ich werde mal versuchen und berichten :slight_smile:

Schönes Wochenende!

War ich ja mit Audio/Navi nicht so weit weg. :wink:

Genau- guten Riecher gehabt :wink:

Ich habe jetzt dein bearbeitetes Script eingefügt.
Beudetet wenn ich jetzt Digital IN 2 nach low lege werden die Frames versendet?
Ich hätte ein 2,5V Signal welches ich über einen verfügbaren Taster im Auto auf Masse legen kann. Reicht diese Flanke aus oder brauch er mehr Spannung?

Gruß Jan :slight_smile:

Nene..
Nicht machen.
Der Taster muss zwischen GND und dem Arduino-Pin.
Mit der Aktivierung des INPUT_PULLUP wird intern der PIN des AVR auf HIGH gezogen.
Drückst Du jetzt die Taste, wird GND auf den PIN gezogen.

Also komplett ohne Potential da ran.
Alternativ könntest mit einem Optokoppler an den Pin und die 2,5V aktivieren den OK auf der Primaerseite.

Und denke dran, mein Codeschnipsel muss noch ausgebaut werden mit der entsprechenden Senderoutine.
Und nach dem senden muss "gedrueckt" wieder zurück gesetzt....

Okay verstanden :slight_smile:
Ich habe das mal eingefügt:

void loop()
{
  if (!digitalRead(tastePin) && !gedrueckt)
  {
    gedrueckt = true;
  }
  if (gedrueckt)
  {
    CAN.sendMsgBuf(0x641, 0, 8, stmp);
    delay(100);             
  }
  
  
}
// END FILE

jetzt sendet er wenn er "gedrueckt" liest die Frames mit der ID 641 oder?
Wie stelle ich das senden wieder ein? Bzw. setze gedrückt zurück wie du bereits angesprochen hast...

Ich glaube für mich als Rookie ist das ein bisschen zu hoch eingestiegen -oder? Ich habe mal mit den Beispielen etwas gespielt die sind recht kurz und nicht so verschachtelt. Da steig ich noch halbwegs durch

Wäre meine Idee - aber ich hab nichts hier um das wenigstens zu kompilieren...

  if (gedrueckt)
  {
    for (byte b = 0; b < sizeof(stmp) / sizeof(stmp[0]); b++)
    {
      CAN.sendMsgBuf(0x641, 0, 8, stmp[b]);
      delay(100);
    }
    gedrueckt = false;
  }

Habe es gerade getestet Sendet leider nichts. Ich weiß nicht ob PIN2 funktioniert.


Habe meinen Taster jetzt zwischen D2/SDA und GND angeschlossen.

Das ist der Code den der Arduino jetzt aktuell verwendet:

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


const int SPI_CS_PIN = 17;              // CANBed V1
// const int SPI_CS_PIN = 3;            // CANBed M0
// const int SPI_CS_PIN = 9;            // CAN Bus Shield

const byte tastePin = 2;
bool gedrueckt = false;
MCP_CAN CAN(SPI_CS_PIN);                                    // Set CS pin

void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start..."));
  while (!Serial);
  while (CAN_OK != CAN.begin(CAN_500KBPS))    // init can bus : baudrate = 500k
  {
    Serial.println("CAN BUS FAIL!");
    delay(100);
  }
  Serial.println("CAN BUS OK!");
  digitalWrite(tastePin, LOW);
  pinMode(tastePin, INPUT_PULLUP);
}

unsigned char stmp[6][8] =
{
  {0x02, 0x10, 0x03, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA},
  {0x03, 0x22, 0xF1, 0x00, 0xAA, 0xAA, 0xAA, 0xAA},
  {0x03, 0x22, 0xF1, 0x54, 0xAA, 0xAA, 0xAA, 0xAA},
  {0x03, 0x22, 0x02, 0x00, 0xAA, 0xAA, 0xAA, 0xAA},
  {0x02, 0x3E, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA},
  {0x04, 0x31, 0x01, 0x03, 0x0D, 0xAA, 0xAA, 0xAA}
};

void loop()
{
  if (!digitalRead(tastePin) && !gedrueckt)
  {
    gedrueckt = true;
  }
  if (gedrueckt)
  {
    for (byte b = 0; b < sizeof(stmp) / sizeof(stmp[0]); b++)
    {
      CAN.sendMsgBuf(0x641, 0, 8, stmp[b]);
      delay(100);
    }
    gedrueckt = false;
  }
  
}
// END FILE

Dann las Dir das doch ausgeben:

  if (!digitalRead(tastePin) && !gedrueckt)
  {
    gedrueckt = true;
Serial.println(F("Taste gedrueckt"));
  }

Und wenn sich deine Antwort auf meinen Text bezieht, dann in meinem Post auf antworten klicken - sonst sehe ich das nicht...

Hallo,
also meinen Taster ließt er wohl doch korrekt ein:
image

Kann es sein, dass er mit dieser Tabelle nicht zurecht kommt?

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


const int SPI_CS_PIN = 17;              // CANBed V1
// const int SPI_CS_PIN = 3;            // CANBed M0
// const int SPI_CS_PIN = 9;            // CAN Bus Shield

const byte tastePin = 2;
bool gedrueckt = false;
MCP_CAN CAN(SPI_CS_PIN);                                    // Set CS pin

void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start..."));
  while (!Serial);
  while (CAN_OK != CAN.begin(CAN_500KBPS))    // init can bus : baudrate = 500k
  {
    Serial.println("CAN BUS FAIL!");
    delay(100);
  }
  Serial.println("CAN BUS OK!");
  digitalWrite(tastePin, LOW);
  pinMode(tastePin, INPUT_PULLUP);
}

unsigned char stmp[6][8] =
{
  {0x02, 0x10, 0x03, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA},
  {0x03, 0x22, 0xF1, 0x00, 0xAA, 0xAA, 0xAA, 0xAA},
  {0x03, 0x22, 0xF1, 0x54, 0xAA, 0xAA, 0xAA, 0xAA},
  {0x03, 0x22, 0x02, 0x00, 0xAA, 0xAA, 0xAA, 0xAA},
  {0x02, 0x3E, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA},
  {0x04, 0x31, 0x01, 0x03, 0x0D, 0xAA, 0xAA, 0xAA}
};

void loop()
{
  if (!digitalRead(tastePin) && !gedrueckt)
  {
    gedrueckt = true;
    Serial.println(F("Taste gedrueckt"));
  }
  if (gedrueckt)
  {
    for (byte b = 0; b < sizeof(stmp) / sizeof(stmp[0]); b++)
    {
      CAN.sendMsgBuf(0x641, 0, 8, stmp[b]);
      delay(100);
    }
    gedrueckt = false;
  }
  
}
// END FILE

Das ist die Frage - ich hab gesschrieben, das ich nichts hier habe um das zu probieren.
Ich weiss nicht, was die Funktion da erwartet.

Jetzt hat es funktioniert!! Es lag am Sende befehl:

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


const int SPI_CS_PIN = 17;              // CANBed V1
// const int SPI_CS_PIN = 3;            // CANBed M0
// const int SPI_CS_PIN = 9;            // CAN Bus Shield

const byte tastePin = 2;
bool gedrueckt = false;
MCP_CAN CAN(SPI_CS_PIN);                                    // Set CS pin

void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start..."));
  while (!Serial);
  while (CAN_OK != CAN.begin(CAN_500KBPS))    // init can bus : baudrate = 500k
  {
    Serial.println("CAN BUS FAIL!");
    delay(100);
  }
  Serial.println("CAN BUS OK!");
  digitalWrite(tastePin, LOW);
  pinMode(tastePin, INPUT_PULLUP);
}

unsigned char stmp[6][8] =
{
  {0x02, 0x10, 0x03, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA},
  {0x03, 0x22, 0xF1, 0x00, 0xAA, 0xAA, 0xAA, 0xAA},
  {0x03, 0x22, 0xF1, 0x54, 0xAA, 0xAA, 0xAA, 0xAA},
  {0x03, 0x22, 0x02, 0x00, 0xAA, 0xAA, 0xAA, 0xAA},
  {0x02, 0x3E, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA},
  {0x04, 0x31, 0x01, 0x03, 0x0D, 0xAA, 0xAA, 0xAA}
};

void loop()
{
  if (!digitalRead(tastePin) && !gedrueckt)
  {
    gedrueckt = true;
    Serial.println(F("Taste gedrueckt"));
 
    for (byte b = 0; b < sizeof(stmp) / sizeof(stmp[0]); b++)
    {
      CAN.sendMsgBuf(0x641, 0, 8, stmp[b]);
      delay(100);
    }
    gedrueckt = false;
  }
  
}
// END FILE

Sag ich immer wieder; auch (ich) ein blindes Huhn findet nen Byte.
Na dann.

1 Like

Ich habe was hier, aber in der Sonne gesessen, war einfach zu verlockend :sunglasses:

... baue ich meinen Aufbau wieder ab. Gratulation :melting_face:

2 Likes