Bekomms einfach nicht gebacken (canbus)

Hallo, hab seit neuestem eine Uno R4 minima, nun versuch ich daten per canbus aus einem BMS auszuwerten, das BMS schickt daten wie Ladezustand, Temperaturen, Zellspannung und vielles mehr, bin nicht der Profiprogrammierer, nur hin und wieder was einfaches, mit der MCP2515 hab ich das vor langer Zeit für ein Motorsteuergerät hinbekommen, aber nicht mit dem sn65hvd230 der ja am Uno hängt, bekomme ständig fehler beim upload, vielleicht schinmal jemmand sowas realisiert ?

#include <Arduino_CAN.h>
static CanMsg msg;

unsigned int SOC;

void setup() {

  CAN.begin(CanBitRate::BR_500k);
}

void loop(void) {

  gauge_display();

  if (CAN.available()) {
    CanMsg msg = CAN.read();
    switch (CAN_ID) {
      case 170:
        SOC = (float)(word(msg_data[6], msg_data[7]));
        break;
    }
  }
}

void gauge_display() {

  Serial.print(SOC);
  delay(10);
}

Was für Fehler?

Sowas komisches habe ich schon lange nicht mehr gesehen...

Ganz neu und daher mir unbekannt.

Beim separat zu installierenden Core für die IDE wird eine CAN-Bibliothek mitgeliefert, die auch Beispiele wie CANRead.ino hat. Nutze zunächst dieses Beispiel zum Testen.

  • Bekommst Du fehlermeldungen? Wenn ja, welche?
  • Wird die richtige CAN-Bibliothek verwendet?
  • Was siehst Du auf dem seriellen Monitor?

Hi, ja das funktioniert wunderbar, daten kommen an, ich weis nur noch nicht , wie ich die daten aufbereite, und die jeweiligen datenlängen aufsplite und auswerte.

Dann zeige mal die Daten in BINÄR oder HEXADECIMAL und erkläre welchen Wert du daraus haben möchtest.

und das Codehandbuch zum dekodieren des Datenstreams.

Also, ich hab das hier mal mit nem can adapter savvyCan simuliert, sonst müsste ich ans Auto rennen, eine Drehzal wird simuliert und die stellt sich aus 2 datenbits zusammen, datenbit 5+6 sollte 3000UPM ergeben

mach mal den gleichen Screenshot mit 4500 RPM.

PS: du willst nicht Bits sonder Bytes

ja bytes.

ok, eigentlich wie erwartet.
Du musst ein Byte um 8 bit shiften und dann den Wert durch 4 dividieren

//https://forum.arduino.cc/t/bekomms-einfach-nicht-gebacken-canbus/1171807/8

byte paket[6];

void debug(byte p[6]) {
  uint16_t result;
  result = p[5] << 8 | p[4];
  Serial.print("0x"); Serial.println(result, HEX);
  Serial.println(result);
  Serial.println(result / 4);
}

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

  paket[0] = 0x0;
  paket[1] = 0x0;
  paket[2] = 0x0;
  paket[3] = 0x0;
  paket[4] = 0xE0;
  paket[5] = 0x2E;

  debug(paket);

  paket[0] = 0x0;
  paket[1] = 0x0;
  paket[2] = 0x0;
  paket[3] = 0x0;
  paket[4] = 0x50;
  paket[5] = 0x46;

  debug(paket);

}

void loop() {
  // put your main code here, to run repeatedly:

}

bringt:
0x2EE0
12000
3000
0x4650
18000
4500

Was jetzt noch ein Rätsel ist wie man aus dem CanMsg Objekt die Bytes vernünftig bekommt.
Da der R4 relativ neu ist: Google mal wie mit dieser Library umzugehen ist, evtl. hilft auch ein Post im Englischsprachigen Forum unter R4.

ja genau das ist das Problem, es ist zu neu, und die Dokumentation ist auch nicht das wahre
Arduino UNO R4 Minima CAN Bus, im internationalen Forum ist auch nix zu finden, da steht einer auch vor dem selben Problem

\variants\MINIMA\includes\ra\fsp\inc\api\r_can_api.h

/** CAN data Frame */
typedef struct st_can_frame
{
    uint32_t         id;                           ///< CAN ID.
    can_id_mode_t    id_mode;                      ///< Standard or Extended ID (IDE).
    can_frame_type_t type;                         ///< Frame type (RTR).
    uint8_t          data_length_code;             ///< CAN Data Length Code (DLC).
    uint32_t         options;                      ///< Implementation-specific options.
    uint8_t          data[CAN_DATA_BUFFER_LENGTH]; ///< CAN data.
} can_frame_t; 

Könnte das helfen?

https://www.buildpics.org/tag/can-bus/

das wäre die elegante lösung für mich, aber hab nicht so den durchblick um das auf den R4 umzusetzen

Das Problem ist, ein Anfänger kauft sich eine neue, noch wenig verbreitete Hardware. Mit einem ESP32 oder einem UNO R3 mit MCP2515 würde sich das unkomplizierter darstellen.

Bitte erweitere das Beispiel:

void loop()
{
  if (CAN.available())
  {
    CanMsg const msg = CAN.read();
    Serial.println(msg);

    Serial.println(msg.id);       // es geht um diese Zeilen
    Serial.println(msg.data[6]);
    Serial.println(msg.data[7]);

  }
}

Bitte berichte :slightly_smiling_face:


das ist schonmal was, ja ich weis ich bin ein Anfänger, das Board hab ich mir geholt weil der schon Can Kann, und der preis echt gut ist, ich versuch jetzt das ganze mal mit switch case zu machen, damit auch mehrere id´s eingelesen und ausgewertet werden, danke für die ersten schritte

Es sind nur 6 Bytes, daher:

    Serial.println(msg.id);
    Serial.println(msg.data[4]);
    Serial.println(msg.data[5]);
    uint16_t result = msg.data[5] << 8 | msg.data[4];
    Serial.println(result);
1 Like

/4
:wink:

Das bekommt der TO selbst hin :smiley:

Vielen dank für die hilfestellung, funktioniert alles wunderbar

#include <Arduino_CAN.h>
static CanMsg msg;

unsigned int SOC, hTMP, lTMP, VCC;

void setup() {
  Serial1.begin(115200);
  CAN.begin(CanBitRate::BR_500k);
}

void loop(void) {
  gauge_display();

  if (CAN.available())
  {
    CanMsg const msg = CAN.read(); {
      switch (msg.id) {
        case 32:
          SOC = (float)(word(msg.data[0], msg.data[1]));
          hTMP = (float)(word(msg.data[2], msg.data[3]));
          lTMP = (float)(word(msg.data[4], msg.data[5]));
          break;
        case 33:
          VCC = (float)(word(msg.data[0], msg.data[1]));
          break;
      }
    }
  }
}

void gauge_display() {

  Serial1.print("n0.val=");
  Serial1.print(SOC);
  Serial1.write(0xff);
  Serial1.write(0xff);
  Serial1.write(0xff);

  Serial1.print("x3.val=");
  Serial1.print(hTMP * 10);
  Serial1.write(0xff);
  Serial1.write(0xff);
  Serial1.write(0xff);

  Serial1.print("x1.val=");
  Serial1.print(lTMP * 10);
  Serial1.write(0xff);
  Serial1.write(0xff);
  Serial1.write(0xff);


  Serial1.print("x4.val=");
  Serial1.print(VCC);
  Serial1.write(0xff);
  Serial1.write(0xff);
  Serial1.write(0xff);

}