Inhalte von struct suchen oder vergleichen

Hallo,
Ich bin relativ neu im Bereich Arduino und C/C++. Habe mich aber schon in Grundlegende Sachen eingearbeitet. Nach einigem Bit-Banging bin ich nun vollkommen an meine Grenzen gekommen und brauche eure Hilfe / Rat.

Ich lese die Daten eines I2C Buses von einem AS1115 Chip aus, der steuert eine dreistellige 7-Segment-Anzeige an.

Die mir angezeigten Daten sehen so aus:

     _A_
F|       |B      		   Bitfolge Binär      X  X  X   X  X  X  X  X          
  |_G_ |        		   Bit Ausgabe       DP  A  B  C  D  E  F  G          
  |       |                          
E|___  |C                        
      D        oDP                

Bitfolgen mit Zahlenzurodnung (Unvollständige Auflistung):
0. = 0B1111 1110

  1. = 0B1011 0000
  2. = 0B1110 1101
    3 = 0B0111 1001
    4 = 0B0011 0011
    5 = 0B0101 1011
    6 = 0B0101 1111
    7 = 0B0111 0000
    8 = 0B0111 1111
    9 = 0B0111 1011

Ich will in meinem Programm also die Bitfolge in eine Dezimal-Zahl wandeln, da ich aber Segmente (ABC…) auslese kann ich leider nicht direkt transferieren. Daher hatte ich die Idee es mit einem struct zu lösen, bin aber nicht sicher ob es geht. Ich wollte den struct mit meinen Bitfolgen füllen und dann vergleichen ob das erste Datenfeld (int Bitfolge) identisch ist mit meiner ausgelesenen Bitfolge ist. Wenn diese gleich ist soll die Zahl (int Zahl) weiter verwendet werden. An genau dieser Stelle komme ich nicht weiter, ich finde keine Anleitung oder ähnliches was mir die Suche innerhalb meines struct's erlaubt.

> typedef struct Bitfolge_zu_Zahlen {
>   int   Bitfolge;
>   int   Zahl;
>   bool  Punkt;
> }Bitfolge_zu_Zahlen;
> 
> Bitfolge_zu_Zahlen Null_Punkt = {
>   0b11111110,   // = 0.
>   0x00,
>   1};
> 
> Bitfolge_zu_Zahlen Null_Punkt = {
>   0b10110000,   // = 1.
>   0x01,
>   1};
> 
> Bitfolge_zu_Zahlen Null_Punkt = {
>   0b11101101,   // = 2.
>   0x02,
>   1};

Habt ihr evtl. einen Vorschlag oder einen link zu einem Tutorial, dass mir weiter hilft?

Grüße
Zippo

Sagen wir mal, das Feld Deiner Struktur heißt bzz dann kannst Du bzz[k].Bitfolge mit Deiner Vergleichsbitfolge in einer Schleife mit dem Schleifenindex ' k' vergleichen. Der Vergleich könnte auch Teil einer Methode sein.

Über Details wie Datentypen wäre noch zu reden :slightly_smiling_face:

Verstehe ich das richtig? Du möchstest anhand der Bitfolge für die Segmentanzeige ermitteln, welche Zahl dargestellt wird?

Das könnte man so lösen:

byte checkSegment(const byte* segmentArray, byte segment) {
  byte i{0};
  do {
    if (segmentArray[i] == segment) { return i; }
  } while(segmentArray[++i]);
  return 0xFF;   // Wenn übergebene Sequenz nicht im Array dann return 0xFF
}

void setup() {
  Serial.begin(115200);
  //                        0    1    2    3    4    5    6    7    8    9 ENDE 
  const byte segments[] {0xFE,0xB0,0xED,0x79,0x33,0x5B,0x5F,0x70,0x7F,0x7B,0x00};

  Serial.println(checkSegment(segments, 0x7B));
  Serial.println(checkSegment(segments, 0x7F));
  Serial.println(checkSegment(segments, 0x70));
  Serial.println(checkSegment(segments, 0x5F));
  Serial.println(checkSegment(segments, 0x5B));
  Serial.println(checkSegment(segments, 0x33));
  Serial.println(checkSegment(segments, 0x79));
  Serial.println(checkSegment(segments, 0xED));
  Serial.println(checkSegment(segments, 0xB0));
  Serial.println(checkSegment(segments, 0xFE));
  Serial.println(checkSegment(segments, 0xAB));
}

void loop() {}

Eine Switch Anweisung ginge auch...

Hallo und danke für eure Antworten.

@agmue
wenn ich es richtig verstehe ist dein Vorschlag genau, dass was Kai-R schreibt.

@Kai-R
Ich verstehe leider noch nicht so ganz wie das Ganze funktioniert.

byte checkSegment(byte* segmentArray, byte segment) {
  byte i{0};
  do {
    if (segmentArray[i] == segment) { return i; }
  } while(segmentArray[++i]);
  return 0xFF;   // Wenn übergebene Sequenz nicht im Array dann return 0xFF
}

Wird hier ein Array ohne konkrete Größe erstellt? Und da lege ich dann im setup die Daten ab und somit wird die Länge dann bestimmt?
Beim Rückfragen meiner Bitfolge gibt mir dann das Arry die Stelle im Array aus?

Sorry für die dämlichen Fragen, für erfahrene User ist das sicherlich banal. Habe aber Arrays bis jetzt noch nicht verstanden und wahrscheinlich nur zu oberflächlich eingelesen.

Grüße
Zippo

Eher nicht, denn er nutzt die prozedurale Lösung mit einem Feld, ich die OOP-Variante mit einer Struktur.

Der Stern gibt an, es handelt sich um einen Zeiger, der auf das bereits angelegte Feld zeigt.

Das Array wird in setup() erstellt byte segments[] {0xFE,0xB0,0xED,0x79,0x33,0x5B,0x5F,0x70,0x7F,0x7B,0x00};

An die Funktion byte checkSegment(byte* segmentArray, byte segment) wird die Startadresse des Arrays und ein Wert übergeben. In der Funktion wird das Array sequentiell durchlaufen und der Inhalt mit dem übergebenen Wert verglichen. Ist dieser Wert im Array enthalten, so wird die Position des identischen Wertes im Array zurück gegeben. Diese Position entspricht der auf der Segmentanzeige dargestellten Ziffer.

Ist der Wert nicht vorhanden wird der Wert 255 zurück gegeben. Sehr wichtig ist, dass das Array „segments“ als letzten Wert IMMER eine 0 hat. Daran wird erkannt, dass die do - while Schleife beendet werden muss, weil alle Positionen des Arrays durchgegangen wurden. Ist als letztes Element ein anderer Wert als 0, gibt es unschöne Programmfehler.

Wenn ich die Funktion + Array in eine Struktur packe, wäre das ja auch eher OOP, im Prinzip aber der gleiche Algorithmus. Wie würdest Du den die Beziehung zwischen Bitmuster und Ziffer herstellen?

Unter Berücksichtigung des Themas und ganz eng an Deinen Vorschlag angeleht, meine Idee als

Programm
struct Bitfolge_zu_Zahlen 
{
  byte   bitfolge;
  byte   zahl;
  bool   punkt;
};

Bitfolge_zu_Zahlen bzz[] =
{
  { 0b11111110, 0, 1},  // 0.
  { 0b10110000, 1, 1},  // 1.
  { 0b11101101, 2, 1},  // 2.
  { 0b01111001, 3, 0},  // 3 
  { 0b00110011, 4, 0},  // 4 
  { 0b01011011, 5, 0},  // 5 
  { 0b01011111, 6, 0},  // 6 
  { 0b01110000, 7, 0},  // 7 
  { 0b01111111, 8, 0},  // 8 
  { 0b01111011, 9, 0},  // 9 
  { 0b00000000, 0, 0},  // ENDE
};

byte checkSegment(Bitfolge_zu_Zahlen * segmentStruct, byte segment) {
  byte i{0};
  do {
    if (segmentStruct[i].bitfolge == segment) {
      return segmentStruct[i].zahl;
    }
  } while (segmentStruct[++i].bitfolge);
  return 0xFF;   // Wenn übergebene Sequenz nicht im Array dann return 0xFF
}

void setup() {
  delay(500);
  Serial.begin(115200);
  Serial.println("\nStart");
  //                  0     1     2     3     4     5     6     7     8     9     ENDE
  //byte segments[] {0xFE, 0xB0, 0xED, 0x79, 0x33, 0x5B, 0x5F, 0x70, 0x7F, 0x7B, 0x00};

  Serial.println(checkSegment(bzz, 0x7B));
  Serial.println(checkSegment(bzz, 0x7F));
  Serial.println(checkSegment(bzz, 0x70));
  Serial.println(checkSegment(bzz, 0x5F));
  Serial.println(checkSegment(bzz, 0x5B));
  Serial.println(checkSegment(bzz, 0x33));
  Serial.println(checkSegment(bzz, 0x79));
  Serial.println(checkSegment(bzz, 0xED));
  Serial.println(checkSegment(bzz, 0xB0));
  Serial.println(checkSegment(bzz, 0xFE));
  Serial.println(checkSegment(bzz, 0xAB));
}

void loop() {}

Die Struktur macht nur Sinn, wenn neben der Bitfolge und dem Index weitere Informationen wie hier die von mir nicht ausgewertete Variable punkt dazu kommen. Prozedural nutzt man mehrere Felder, deren Informationen über den Index zusammenfinden, während man bei einem Feld von Strukturen die Informationen in den Feldelementen zusammen hat.

Inweiweit das im Konzept des TOs einen Sinn ergibt, kann ich nicht beurteilen.

1 Like

Danke für Deine Variante und Erklärung :slightly_smiling_face: .

In #8 habe ich `const' vergessen.

Noch "mehr" OOP bekommt man mit privaten, also von außen nicht zugänglichen Variablen/Konstanten und Methoden für die Datenrückgabe.

Programm
struct Bitfolge_zu_Zahlen 
{
  private:
  const byte   bitfolge;
  const byte   zahl;
  const bool   punkt;
  public:
  Bitfolge_zu_Zahlen(const byte bitfolge, const byte zahl, const bool punkt) : bitfolge(bitfolge), zahl(zahl), punkt(punkt)
  {}
  bool vergleich(byte seg)
  {
    return bitfolge == seg;
  }
  byte getBitfolge()
  {
    return bitfolge;
  }
  byte getZahl()
  {
    return zahl;
  }
};

Bitfolge_zu_Zahlen bzz[] =
{
  { 0b11111110, 0, 1},  // 0.
  { 0b10110000, 1, 1},  // 1.
  { 0b11101101, 2, 1},  // 2.
  { 0b01111001, 3, 0},  // 3 
  { 0b00110011, 4, 0},  // 4 
  { 0b01011011, 5, 0},  // 5 
  { 0b01011111, 6, 0},  // 6 
  { 0b01110000, 7, 0},  // 7 
  { 0b01111111, 8, 0},  // 8 
  { 0b01111011, 9, 0},  // 9 
  { 0b00000000, 0, 0},  // ENDE
};

byte checkSegment(Bitfolge_zu_Zahlen * segmentStruct, byte segment) {
  byte i{0};
  do {
    if ( segmentStruct[i].vergleich(segment) ) {
      return segmentStruct[i].getZahl();
    }
  } while (segmentStruct[++i].getBitfolge());
  return 0xFF;   // Wenn übergebene Sequenz nicht im Array dann return 0xFF
}

void setup() {
  delay(500);
  Serial.begin(115200);
  Serial.println("\nStart");
  //                  0     1     2     3     4     5     6     7     8     9     ENDE
  //byte segments[] {0xFE, 0xB0, 0xED, 0x79, 0x33, 0x5B, 0x5F, 0x70, 0x7F, 0x7B, 0x00};

  Serial.println(checkSegment(bzz, 0x7B));
  Serial.println(checkSegment(bzz, 0x7F));
  Serial.println(checkSegment(bzz, 0x70));
  Serial.println(checkSegment(bzz, 0x5F));
  Serial.println(checkSegment(bzz, 0x5B));
  Serial.println(checkSegment(bzz, 0x33));
  Serial.println(checkSegment(bzz, 0x79));
  Serial.println(checkSegment(bzz, 0xED));
  Serial.println(checkSegment(bzz, 0xB0));
  Serial.println(checkSegment(bzz, 0xFE));
  Serial.println(checkSegment(bzz, 0xAB));
}

void loop() {}

Über die Sinnhaftigkeit von OOP auf AVRs wurde schon viel diskutiert, das muß man im Gesamtzusammenhang beurteilen, ich möchte nur die Möglichkeit aufzeigen.

Ich hoffe, Zippo hat auch was davon :slightly_smiling_face:

Ich in #3 auch :wink: . Hab's nachgetragen.

Ich habe hier noch eine etwas mehr C++ mäßige Variante, auch wenn keine Klasse/ Struct verwendet wird, aber die Vergleichsfunktion ist jetzt so aufgebaut, dass die abschließende 0 im Array nicht mehr notwendig ist. Das verringert das Risiko von Programmierfehlern.

//                          0    1    2    3    4    5    6    7    8    9  
const byte segments[10] {0xFE,0xB0,0xED,0x79,0x33,0x5B,0x5F,0x70,0x7F,0x7B};

template <size_t MAX> byte checkSegment(const byte (&segmentArray)[MAX], byte segment) {
  byte i{0};
  do {
    if (segmentArray[i] == segment) { return i; }
  } while(++i < MAX);
  return 0xFF;   // Wenn übergebene Sequenz nicht im Array dann return 0xFF
}

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

  // 
  // Gehe das Array mit den Bitmustern durch und 
  // vergleiche die Werte mit sich selbst (Demo -> Position = Ziffer)
  //
  for (byte seg : segments) {
    Serial.print(F("0x"));
    (seg < 0x10) ? Serial.print("0"): false;
    Serial.print(seg,HEX); Serial.print(F(" entpricht Ziffer: "));
    Serial.println(checkSegment(segments, seg));   // Vergleich als Parameter der Ausgabeanweisung
  }

  //
  // Zeige die Ausgabe eines nicht erfolgreichen Vergleichs 
  //
  Serial.print(F("0xAB nicht vorhanden: "));
  Serial.println(checkSegment(segments,0xAB));    // Vergleich als Parameter der Ausgabeanweisung
}

void loop() {}

Ich hoffe es verwirrt nicht zu sehr...

1 Like

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