Array auswerten aber wie

Ich habe ein Array.
Nun möchte ich vergleich ob es zu einem meiner anderen Arrays passt.
In der Praxis habe ich also von einem Can Bus eine Nachricht ausgelesen und möchte gucken ob die Nachricht mit einer meiner festgelegten Nachrichten übereinstimmt.

Ich habe hier schon 2 Varianten Probiert.
Die erste ist auskommentiert, da nicht exakt auf die komplette Nachricht geprüft wird sondern immer nur Teil für Teil. So kann es vorkommen, dass er manchmal in Nachricht1(vergleich) und manchmal in Nachricht2(vergleich2) fündig wird.

Variante 2 gibt mir eine Zahl aus, die nicht mehr viel mit der Tatsächlichen Nachricht gemein hat. Das macht das ganze recht umständlich.

void loop()
{
  unsigned char len = 0;
  unsigned char buf[8];
  unsigned char vergleich[8] = {9, 9, 9, 9, 255, 25, 255, 255};
  unsigned char vergleich2[8] = {0, 0, 0, 0, 255, 255, 255, 255};
  long value = 5;
  int Sperren = 5;
  if (CAN_MSGAVAIL == CAN.checkReceive())           // check if data coming
  {
    CAN.readMsgBuf(&len, buf);    // read data,  len: data length, buf: data buf

    unsigned int canId = CAN.getCanId();

    Serial.println("-----------------------------");
    //Serial.print(buf[6]);
    Serial.print("Get data from ID: ");
    Serial.println(canId, HEX);

    for (int i = 0; i < len; i++) // print the data
    {
      value *= 10;
      value += buf[i];
      //value += (buf[i]*pow(10,i));


      /*if(buf[i] == vergleich[i] || buf[i] == vergleich2[i]){
        Serial.print(buf[i], HEX);
        Serial.print("\t");
        Sperren=0;
        }else
        {
        Serial.print("Stop");
        Sperren=1;
        break;
        }*/
    }
    //Serial.print("Sperren= ");
    //Serial.print(Sperren);
    Serial.print("Ergebnis= ");
    Serial.print(value);
    Serial.println();
  }
}

Um Arrays zu vergleichen gibt es memcmp()

http://www.cplusplus.com/reference/cstring/memcmp/

Super Tip, ich habs nun so gelöst, danke.

unsigned char vergleich[3][8] = {{0, 0, 0, 0, 255, 255, 255, 255}, {9, 9, 9, 9, 255, 255, 255, 255} , {1, 0, 0, 0, 255, 255, 255, 255} };

for (int i = 0; i < 3; i++) // print the data
    {
      if (memcmp ( buf, vergleich[i], 8) != 0) {
        Serial.print("FEHLER ");
      }else {Serial.print("Übereinstimmung ");}
    }

Kann ich die CAN ID unsigned int canId = CAN.getCanId(); noch irgendwie vorne in die ausgelesen Nachricht in buf[] schieben?

Brauchst du das wirklich im Array? Das vernünftigste bei sowas ist ein struct aus den Variablen die zusammen gehören. Also z.B. ein struct aus einem Integer und dem Array

Ich weiß gerade nicht wie du das meinst.
Bin noch nicht so fit im Programmieren.
Ich brauche kein Array das ist nur das, was mir mein Can Bus raus gibt.

Also du könntest es auch umständlicher (aber für dich vielleicht besser zu verstehen) machen:

Du vergleichst immer die Werte der Array einzeln.

int Array1[3] = { 3,9,6};

int Array2[3] = { 4,9,7};

void loop()
{
for(int i=0; i > 3; i++)
  {
     if(Array1[i] == Array2[i])
     {
         //Werte sind gleich jetzt muss und jetzt muss du nur noch ausrechnen wie viele Werte gleich sind
     }
  }
}

bdorer:
Also du könntest es auch umständlicher (aber für dich vielleicht besser zu verstehen) machen:

Du vergleichst immer die Werte der Array einzeln.

int Array1[3] = { 3,9,6};

int Array2[3] = { 4,9,7};

void loop()
{
for(int i=0; i > 3; i++)
  {
    if(Array1[i] == Array2[i])
    {
        //Werte sind gleich jetzt muss und jetzt muss du nur noch ausrechnen wie viele Werte gleich sind
    }
  }
}

Das habe ich oben ja schon gelöst.
Nur fehlt da die Can Id. Dies würde ich gerne vor die Nachricht stellen.
Nun sollte das Programm noch möglichst schnell laufen.

aggro600:
Bin noch nicht so fit im Programmieren.

Dann lerne Grundlagen. Arrays und structs sind grundlegende Dinge die man immer wieder braucht

Das hat Google mit "C++ Struktur" sofort ausgespuckt (wobei der deutsche Fachbegriff allerdings "Verbund" ist):

Diese Seite ist generell ziemlich gut wenn du mal was nachschlagen musst, deckt aber nur einen Teil ab

Das kannst du genauso wie ein Array mit memcmp() vergleichen. Und sizeof() liefert dir hier auch die Größe eines structs in Bytes zurück

Nun hab ich ein wenig rumprobiert, aber naja.
Die ID und Nachricht konnte ich noch nicht zusammenführen.
Und so wie es jetzt ist macht das Programm nen komischen Fehler.
Ich sende 3 Nachrichten. 2 mal kommt alles richtig und 1 mal nicht.

// demo: CAN-BUS Shield, receive data with check mode
// send data coming to fast, such as less than 10ms, you can use this way
// loovee, 2014-6-13


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


 struct GesamteNachricht
  {
    int                     ID;
    unsigned char           Message[8];
  };

struct GesamteNachricht Nachricht;


unsigned char vergleich[8] = {0,0,0,0,255,255,0,0};
unsigned char vergleich2[8] = {5,5,5,5,5,5,5,5};
unsigned char vergleich3[8] = {5,5,5,5,5,5,5,5};


// 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 = 10;

MCP_CAN CAN(SPI_CS_PIN);                                    // Set CS pin

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

  while (CAN_OK != CAN.begin(CAN_200KBPS))              // 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!");

 
}


void loop()
{
  unsigned char len = 0;
  unsigned char buf[8];




  if (CAN_MSGAVAIL == CAN.checkReceive())           // check if data coming
  {
    CAN.readMsgBuf(&len, buf);    // read data,  len: data length, buf: data buf

    unsigned int canId = CAN.getCanId();
    //char canId = CAN.getCanId();


    Serial.println("-----------------------------");
    Serial.print("Get data from ID: ");
    Serial.println(canId);

    for (int i = 0; i < len; i++) // print the data
    {
      Serial.print(buf[i], HEX);
      Serial.print("\t");
    }
    Serial.println();
    
    //strcpy( Nachricht.ID, canId );
    Nachricht.ID = canId;
    //Nachricht.Message = buf;
    strcpy( Nachricht.Message, buf );
    
    Serial.print("ID: ");
    Serial.println(Nachricht.ID);
    Serial.println("Message: ");
    for (int j = 0; j < len; j++) // print the data
    {
    //Serial.print(j);
    //Serial.print("=");
    Serial.print(Nachricht.Message[j], HEX);
    Serial.print("\t");
    }
    Serial.println("");



      if (memcmp ( Nachricht.Message, vergleich3, 8) != 0) {
        Serial.println("FEHLER ");
        
      }else {Serial.println("Übereinstimmung "); }
    
    
  }
}

/*********************************************************************************************************
  END FILE
*********************************************************************************************************/

Das kommt dabei raus:

-----------------------------
Get data from ID: 682
5	5	5	5	5	5	5	5	
ID: 682
Message: 
5	5	5	5	5	5	5	5	
Übereinstimmung 
-----------------------------
Get data from ID: 2047
0	0	0	0	FF	FF	0	0	
ID: 2047
Message: 
0	5	5	5	5	5	5	5	
FEHLER 
-----------------------------
Get data from ID: 622
9	9	9	9	FF	FF	FF	FF	
ID: 622
Message: 
9	9	9	9	FF	FF	FF	FF	
FEHLER 
-----------------------------
Get data from ID: 682
5	5	5	5	5	5	5	5	
ID: 682
Message: 
5	5	5	5	5	5	5	5	
Übereinstimmung

Hier sieht man, dass die Empfangende Nachricht nicht die ist die in Nachricht.Message steht.

Get data from ID: 2047
0	0	0	0	FF	FF	0	0	
ID: 2047
Message: 
0	5	5	5	5	5	5	5	
FEHLER

Das Einlesen der Nachricht ist schon Käse. Wieso legst du einen extra Puffer dafür an? Übergebe doch einfach das Array im struct an CAN.readMsgBuf(). Dafür ist es da

Es gibt memcpy() um Speicher zu kopieren. strcpy() ist wie der Name sagt für C Strings (string copy)! Das erwartet einen Null-Terminator am Ende und bricht ab wenn 0 kommt. Lies dir die Doku der Funktion durch! Aber wie gesagt ist das Kopieren völlig unnötig

Auch hier hast du eine unnötige Variable:

unsigned int canId = CAN.getCanId();

Ja, du kannst das erst mal zwischenspeichern und dann in das struct kopieren. Oder du macht gleuch nachricht.ID = CAN.getCanId();

Gewöhne dir ab irgendwie Code Schnippsel zusammenkopieren. Du musst verstehen was da gemacht wird

Serenifly:
Gewöhne dir ab irgendwie Code Schnippsel zusammenkopieren. Du musst verstehen was da gemacht wird

Sehr wichtig! Sonst wird es vielleicht mal funktionieren, wenn du Glück hast aber wenn nicht kannst von vorne beginnen.

Hat geklappt und nun soll ich dann meine Nachricht.ID und Nachricht. Massage in ein Array speichern um es dann zu vergleichen?

nun soll ich dann meine Nachricht.ID und Nachricht. Massage in ein Array speichern um es dann zu vergleichen?

Wieso? Du hast schon ein Array in dem struct!

Außerdem kannst du auch ganze structs vergleichen. Ich habe doch schon gesagt, dass memcmp() alles vergleichen kann. Sieht man auch an der Funktion. Die hat einen void Zeiger als Parameter. Da werden einfach so viele Bytes verglichen wie man angibt. Egal was der Datentyp ist. Und die Größe des structs (als 3. Parameter) bekommst du mit sizeof():
http://en.cppreference.com/w/cpp/language/sizeof

Oder vergleiche nur das Array mit memcmp() und mache einen zweiten Vergleich für die ID

Ich habe jetzt

Nachricht.ID = canId;
memcpy( Nachricht.Message, buf, len );

und vergleiche hier

if (memcmp (Nachricht.Message, vergleich3, len) != 0) {
      Serial.println("FEHLER ");
} else {
      Serial.println("Übereinstimmung ");
    }

ich muss Nachricht.Message ja als Nachricht.Message + Nachricht.ID haben. Oder als GesamteNachricht bzw. nur Nachricht das Gesamte struct vergleichen.
Nun habe ich schon alles was mir eingefallen ist eingeben:

  • GesamteNachricht
  • GesamteNachricht[0]
  • Nachricht
  • Nachricht[0]
  • Nachricht.Message, Nachricht.ID

memcpy( Nachricht.Message, buf, len );

Wieso willst du immer den Puffer da hin kopieren? Mach einfach das:

CAN.readMsgBuf(&len, Nachricht.Message);

Lese die Nachricht direkt aus der CAN Klasse in das Array im struct. Der extra Puffer ist überflüssig

Zwei Optionen für den Vergleich:

struct Nachricht
{
  unsigned int ID;
  byte message[8];
};

Nachricht nachricht =  { 10, { 0, 0, 0, 0, 255, 255, 255, 255 } };
Nachricht vergleich1 = { 10, { 0, 0, 0, 0, 255, 255, 255, 255 } };
Nachricht vergleich2 = { 1, { 0, 0, 0, 0, 255, 255, 255, 255 } };

//Funktionsprotypen waren bei mir nötig. Kann an meiner alten Arduino Version liegen
void vergleichV1(Nachricht& nachricht, Nachricht& vergleich);
void vergleichV2(Nachricht& nachricht, Nachricht& vergleich);
void printNachricht(Nachricht& nachricht);

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

  printNachricht(nachricht);
  printNachricht(vergleich1);
  printNachricht(vergleich2);
  Serial.println();

  vergleichV1(nachricht, vergleich1);
  vergleichV1(nachricht, vergleich2);

  vergleichV2(nachricht, vergleich1);
  vergleichV2(nachricht, vergleich2);

}

void loop()
{
}

//ganzes struct vergleichen
void vergleichV1(Nachricht& nachricht, Nachricht& vergleich)
{
  if (memcmp(&nachricht, &vergleich, sizeof(nachricht)) == 0)
  {
    Serial.println("Uebereinstimmung");
  }
  else
  {
    Serial.println("Fehler");
  }
}


//Array und ID getrennt vergleichen
void vergleichV2(Nachricht& nachricht, Nachricht& vergleich)
{
  if (memcmp(nachricht.message, vergleich.message, sizeof(nachricht.message)) == 0 && nachricht.ID == vergleich.ID)
  {
    Serial.println("Uebereinstimmung");
  }
  else
  {
    Serial.println("Fehler");
  }
}

void printNachricht(Nachricht& nachricht)
{
  Serial.print(nachricht.ID);
  for (byte i = 0; i < sizeof(nachricht.message); i++)
  {
    Serial.print(' ');
    Serial.print(nachricht.message[i]);
  }
  Serial.println();
}

nachricht ist was du von CAN bekommst. Das ist hier als Test (und nur als Test!) fest vorgegeben. vergleich1/2 sind die festen Vergleichswerte

Wobei V2 eigentlich besser ist. Auf dem Arduino geht auch V1, aber auf anderen System ist nicht immer garantiert dass der Compiler da keine Padding Daten einfügt damit die Variablen nach Wort-Grenzen ausgerichtet sind (z.B. 8 Bit Variablen auf 32 Bit Systemen)

Vielen dank für deine Mühe, läuft bestens.