int Arrays verknüpfen / verbinden zu neuen Array

Da sich Arrays irgendwie nicht so wie in den anderen Programmiersprachen verhalten die ich kenne,
suchte ich nach einer Lösung dieses ganze Array, ArrayGröße, Pointer, Speicherbereich-Dingens zu
verstehen, um mehrere Arrays miteinander zu verbinden, um dann Teile des Arrays auszutauschen.

Dabei bin ich auf diesen Beitrag:
https://forum.arduino.cc/index.php?topic=321002.15

gestoßen, der das eigentlich ganz einleuchtend erklärt und bei dem es auch zu funktionieren scheint.

also hab ich das als Grundlage genommen und wollte diese Konstrukt mit noch mehr Arrays erweitern.

Dann allerdings funktioniert es wieder nicht und die Ausgabe mixed den finalArray Array komisch zusammen...
Irgendwo muss also ein Fehler sein, den ich - vermutlich aus Unkenntnis und Unverständnis- nicht selbst finde
und deshalb auch nicht lösen kann.... hilfe wäre also sehr willkommen.

hier ist der dazu gehörige Code.
meine Arrays:

int CC_PerformerBank1[16]   = {74,21,73,28,75,24,77,29,71,27,72,25,76,23,22,26};
int CC_CenterPotis[12]      = {35,34,33,32,31,30,41,40,39,38,37,36};
int CC_ADSR_Env1[4]         = {14,13,12,11};
int CC_ADSR_Env2[4]         = {18,17,16,15};
int CC_ADSR_Env3[4]         = {95,94,93,92};
int CC_ADSR_Env4[4]         = {99,98,97,96};
int CC_Normalizer[12]       = {50,51,52,53,46,47,48,49,42,43,44,45};

int controllerArray[48];

void combineArrays(int* Array1,int arry1Size, int* Array2, int arry2Size, int* Array3,int arry3Size, int* Array4, int arry4Size, int* Array5,int arry5Size, int* finalArray)
{
   memcpy(&finalArray[0], Array1, arry1Size);
   memcpy(&finalArray[arry1Size/sizeof(Array1[0])], Array2, arry2Size);
   //memcpy(&finalArray[(arry2Size/sizeof(Array2[0]))+4], Array3, arry3Size);
   //memcpy(&finalArray[arry3Size/sizeof(int)], Array4, arry4Size);
   //memcpy(&finalArray[arry4Size/sizeof(int)], Array5, arry5Size);
  }

und mit

combineArrays(CC_PerformerBank1, sizeof(CC_PerformerBank1), CC_CenterPotis, sizeof(CC_CenterPotis), CC_ADSR_Env1, sizeof(CC_ADSR_Env1), CC_ADSR_Env2, sizeof(CC_ADSR_Env2), CC_Normalizer, sizeof(CC_Normalizer), controllerArray);

ruf dann die Funktion auf.
Also im Grunde, wenn ich nichts übersehen habe, alles wie in dem Beispiel vom oben genannten Beitrag.

Wie man sieht, sind in der Funktion memcpy 3,4 & 5 auskommentiert.
So erhalte ich das erwartete Ergebnis.

mit

Serial.println(" S T A R T ");
  for(int n=0; n < 48; n++)
    {
      Serial.println(controllerArray[n]);
    }
      Serial.println(" ");
      Serial.println("   E N D   ");
      Serial.println(" ");

prüfe ich das Ergebnis
und
Die Ausgabe ist dann wie erwartet
S T A R T
74
21
73
28
75
24
77
29
71
27
72
25
76
23
22
26
35
34
33
32
31
30
41
40
39
38
37
36
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0

E N D
sobald ich das dritte Array freischalte , da mischt sich das Ergebnis ganz merkwürdig und ich erhalte:
S T A R T
74
21
73
28
75
24
77
29
71
27
72
25
14
13
12
11
35
34
33
32
31
30
41
40
39
38
37
36
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0

E N D

... es wird also nicht an der richtigen Stelle hinzugefügt und auch nicht der komplette Array....

Als Übung zum Verstehen von Speicher und Zeigern ist das in Ordnung. In einer praktischen Anwendung solltest du dir aber sehr gut überlegen ob du das wirklich brauchst. Sehr oft missbrauchen Anfänger Arrays weil es die einzige Datenstruktur die sie kennen. Verschiedene Arrays kann man auch in Strukturen zusammenfassen und eine Struktur als einen Speicherbereich ansprechen wenn man z.B. etwas Byte-weise übertragen muss

Überlege dir außerdem ob die hier wirklich int brauchst. Für Zahlen zwischen 0 und 255 reicht Byte. Dann wird das auch etwas einfacher

int CC_PerformerBank1[16]   = {74, 21, 73, 28, 75, 24, 77, 29, 71, 27, 72, 25, 76, 23, 22, 26};
int CC_CenterPotis[12]      = {35, 34, 33, 32, 31, 30, 41, 40, 39, 38, 37, 36};
int CC_ADSR_Env1[4]         = {14, 13, 12, 11};
int CC_ADSR_Env2[4]         = {18, 17, 16, 15};
int CC_ADSR_Env3[4]         = {95, 94, 93, 92};
int CC_ADSR_Env4[4]         = {99, 98, 97, 96};
int CC_Normalizer[12]       = {50, 51, 52, 53, 46, 47, 48, 49, 42, 43, 44, 45};

int controllerArray[48];

void combineArrays(int* Array1, int arry1Size, int* Array2, int arry2Size, int* Array3, int arry3Size, int* Array4, int arry4Size, int* Array5, int arry5Size, int* finalArray)
{
  memcpy(&finalArray[0], Array1, arry1Size);
  memcpy(&finalArray[arry1Size / sizeof(Array1[0])], Array2, arry2Size);
  memcpy(&finalArray[(arry1Size / sizeof(Array1[0])+arry2Size/sizeof(Array2[0]))], Array3, arry3Size);
  //memcpy(&finalArray[arry3Size/sizeof(int)], Array4, arry4Size);
  //memcpy(&finalArray[arry4Size/sizeof(int)], Array5, arry5Size);
}

void setup() {
  Serial.begin(115200);
  Serial.println(F("Start...."));
  combineArrays(CC_PerformerBank1, sizeof(CC_PerformerBank1), 
  CC_CenterPotis, sizeof(CC_CenterPotis), 
  CC_ADSR_Env1, sizeof(CC_ADSR_Env1), 
  CC_ADSR_Env2, sizeof(CC_ADSR_Env2), 
  CC_Normalizer, sizeof(CC_Normalizer), 
  controllerArray);


}

void loop() {
  Serial.println(" S T A R T ");
  for (int n = 0; n < 48; n++)
  {
    Serial.println(controllerArray[n]);
  }
  Serial.println(" ");
  Serial.println("   E N D   ");
  Serial.println(" ");
  // put your main code here, to run repeatedly:
while(1);
}
15:34:08.547 -> Start....
15:34:08.547 ->  S T A R T 
15:34:08.547 -> 74
15:34:08.547 -> 21
15:34:08.547 -> 73
15:34:08.547 -> 28
15:34:08.547 -> 75
15:34:08.547 -> 24
15:34:08.547 -> 77
15:34:08.547 -> 29
15:34:08.547 -> 71
15:34:08.547 -> 27
15:34:08.547 -> 72
15:34:08.547 -> 25
15:34:08.547 -> 76
15:34:08.547 -> 23
15:34:08.547 -> 22
15:34:08.547 -> 26
15:34:08.547 -> 35
15:34:08.547 -> 34
15:34:08.547 -> 33
15:34:08.547 -> 32
15:34:08.547 -> 31
15:34:08.547 -> 30
15:34:08.547 -> 41
15:34:08.547 -> 40
15:34:08.547 -> 39
15:34:08.547 -> 38
15:34:08.547 -> 37
15:34:08.547 -> 36
15:34:08.547 -> 14
15:34:08.547 -> 13
15:34:08.547 -> 12
15:34:08.547 -> 11
15:34:08.547 -> 0
15:34:08.547 -> 0
15:34:08.547 -> 0
15:34:08.547 -> 0
15:34:08.547 -> 0
15:34:08.547 -> 0
15:34:08.547 -> 0
15:34:08.547 -> 0
15:34:08.547 -> 0
15:34:08.547 -> 0
15:34:08.547 -> 0
15:34:08.547 -> 0
15:34:08.547 -> 0
15:34:08.547 -> 0
15:34:08.547 -> 0
15:34:08.547 -> 0
15:34:08.547 ->  
15:34:08.547 ->    E N D

Du findest den Unterschied zu Deiner Version allein.

Wenn Du die Arrays so aneinanderhängen willst, musst Du den Offset auch immer weiter aufaddieren, und nicht nur den vom vorherigen Array nehmen.
Also z.B. beim 3. memcopy must der Offset die Länge von Array1+Array2 sein. Du setzt aber nur die Länge von Array2 als Offset ein. Beim 4. memcpy dann entsprechend die Länge von Array1+Array2+array3 usw.

Den Einwand von Serenifly solltest Du ernst nehmen. Vielleicht zeigst Du auch mal, wozu das Ganze am Ende gut sein soll.

Ahh danke für die schnellen Antworten, dann versteh ich den Fehler den ich gemacht habe.

Und bzgl Struct meld ich mich später nochmal und erkläre den geplanten Gebrauch - vielleicht ist Struct ja wirklich besser

denn
natürlich suche ich auch eine effiziente und auch eine übersichtliche nachvollziehbare Lösung.

masterheavy:
natürlich suche ich auch [...] eine übersichtliche [...] Lösung.

Schon beim Codeschreiben drauf achten...

void combineArrays(int* Array1, int arry1Size, int* Array2, int arry2Size, int* Array3, int arry3Size, int* Array4, int arry4Size, int* Array5, int arry5Size, int* finalArray)
{
  int meme=0;
  memcpy(&finalArray[meme], Array1, arry1Size);
  meme+=arry1Size / sizeof(Array1[0]);
  memcpy(&finalArray[meme], Array2, arry2Size);
  meme+=arry2Size/sizeof(Array2[0]);
  memcpy(&finalArray[meme], Array3, arry3Size);
  meme+=arry3Size/sizeof(Array3[0]);
  memcpy(&finalArray[meme], Array4, arry4Size);
  meme+=arry4Size/sizeof(Array4[0]);
  memcpy(&finalArray[meme], Array5, arry5Size);
}

masterheavy:
Und bzgl Struct meld ich mich später nochmal und erkläre den geplanten Gebrauch - vielleicht ist Struct ja wirklich besser
denn
natürlich suche ich auch eine effiziente und auch eine übersichtliche nachvollziehbare Lösung.

Ja, beschäftige Dich unbedingt mal mit den verschiedenen Möglichkeit zur Datenverwaltung. Das führt automatisch zu besserem Code. Und somit zu mehr Effizienz und Übersichtlichkeit.

Gruß

Gregor

my_xy_projekt:
Schon beim Codeschreiben drauf achten...

void combineArrays(int* Array1, int arry1Size, int* Array2, int arry2Size, int* Array3, int arry3Size, int* Array4, int arry4Size, int* Array5, int arry5Size, int* finalArray)

{
 int meme=0;
 memcpy(&finalArray[meme], Array1, arry1Size);
 meme+=arry1Size / sizeof(Array1[0]);
 memcpy(&finalArray[meme], Array2, arry2Size);
 meme+=arry2Size/sizeof(Array2[0]);
 memcpy(&finalArray[meme], Array3, arry3Size);
 meme+=arry3Size/sizeof(Array3[0]);
 memcpy(&finalArray[meme], Array4, arry4Size);
 meme+=arry4Size/sizeof(Array4[0]);
 memcpy(&finalArray[meme], Array5, arry5Size);
}




Na das sieht ja schon mal wenigstens ein bisschen übersichtlicher aus. Danke.

das aber memcpy immer den Offset dann plus das und plus das nächste erwartet, hätte man ja selber 
drauf kommen können, ist aber gleichzeitig natürlich schon doof.

So, bevor ich dann jetzt mal mein Programm auf das wesentliche runterbreche um es hier zu posten, bitte ich noch um etwas geduld. Ich muss das erstmal aussortieren, sonst erklärt sich das so schlecht und wird zu unübersichtlich. 
Im Grunde funktioniert nämlich alles und muss aber eben irgendwie optimiert werden.

So, also im Moment - die Version bevor memcpy die Arrays zusammen führen konnte - sieht es so aus:

ich hab einen Controller mit 48 Drehreglern und ein paar Knöpfen. Die Drehregler sind in Sektionen
aufgeteilt. Jeder Controller hat eine Controller Nummer. Die CNum hab ich in einem Array abgelegt.

Nun kann ich per Knopf einige dieser Sektionen in ihren Controllernummern ändern, andere wiederum
bleiben gleich.
Da das mit dem Array zusammenführen bisher nicht klappte, habe ich das Array einfach vervielfacht
und dabei die geänderten Controllernummern einfach direkt im Array abgelegt.
So hab ich also Bank 1, Bank 2, Bank 3, etc.
Das ist super doof wie man gleich sieht, weil ich ja dann immer auch die verschiedenen
Zustände berücksichtigen muss, wenn der eine Knopf gedrückt ist und der andere nicht und dafür
jeweils schon vorher separate Arrays brauche. genau so auch für "wenn beide gedrückt sind" etc.

Für die Endversion sollen noch 3 Bänke dazu kommen, das wären dann also nochmal 3 hoch 3
Kombinationen zusätzlich.

Das nachfolgende Illustriert den Wust, mit nur 2 Knöpfen, die jeweils nur insgesamt 2 x 4 Werte in
Mitten des Arrays ändern.
Sieht dann also so aus...

// basis Array mit Env 1 & Env 2
const int CC_Bank_01[]           = {74,21,73,28,  //performer CC1
                                     75,24,77,29, //
                                     71,27,72,25, //
                                     76,23,22,26, //
                                     35,34,33,32, // Center 
                                     31,30,41,40, //  potis 1-12
                                     39,38,37,36, //  (30 - 41)
                                     14,13,12,11, // Envelope 1
                                     50,51,52,53, // Normalizer 3
                                     46,47,48,49, // Normalizer 2
                                     42,43,44,45, // Normalizer 1 
                                     18,17,16,15  // Envelope 2
                                     };
// basis Array mit Env 3 & Env 2
const int CC_Bank_03_02[]            = {74,21,73,28, //  performer
                                        75,24,77,29,
                                        71,27,72,25,
                                        76,23,22,26,
                                        35,34,33,32, // Center 
                                        31,30,41,40, //  potis 1-12
                                        39,38,37,36, //  (30 - 41)
                                        95,94,93,92, // Envelope 3
                                        50,51,52,53, // Normalizer 3
                                        46,47,48,49, // Normalizer 2
                                        42,43,44,45, // Normalizer 1 
                                        18,17,16,15  // Envelope 2
                                        };
// basis Array mit Env 1 & Env 4
const int CC_Bank_01_04[]            = {74,21,73,28, // performer
                                        75,24,77,29,
                                        71,27,72,25,
                                        76,23,22,26,
                                        35,34,33,32, // Center 
                                        31,30,41,40, //  potis 1-12
                                        39,38,37,36, //  (30 - 41)
                                        14,13,12,11, // Envelope 1
                                        50,51,52,53, // Normalizer 3
                                        46,47,48,49, // Normalizer 2
                                        42,43,44,45, // Normalizer 1 
                                        99,98,97,96  // Envelope 4
                                        };
// basis Array mit Env 3 & Env 4
const int CC_Bank_03_04[]            = {74,21,73,28, // performer
                                        75,24,77,29,
                                        71,27,72,25,
                                        76,23,22,26,
                                        35,34,33,32, // Center 
                                        31,30,41,40, //  potis 1-12
                                        39,38,37,36, //  (30 - 41)
                                        95,94,93,92, // Envelope 3
                                        50,51,52,53, // Normalizer 3
                                        46,47,48,49, // Normalizer 2
                                        42,43,44,45, // Normalizer 1 
                                        99,98,97,96  // Envelope 4
                                        };


int ControllerNum_Ary[48]; 

bool ENV_3_isSelected     = false; 
bool ENV_4_isSelected     = false;

ToggleButton adsr_toggle1 = ToggleButton(_ADSR_BTN_Pins[0],false,25,false,false);
ToggleButton adsr_toggle2 = ToggleButton(_ADSR_BTN_Pins[1],false,25,false,false);

void Setup()
{
	Serial.begin(115200);
	Serial1.begin(31250);

	initializeBank(CC_Bank_01);
	
	adsr_toggle1.begin();
	adsr_toggle2.begin();
}

void loop ()
{
	adsr_toggle1.read();
	adsr_toggle2.read();
  
  	if(adsr_toggle1.changed()) ENV_3_isSelected = !ENV_3_isSelected;
	if(adsr_toggle2.changed()) ENV_4_isSelected = !ENV_4_isSelected;

	if(ENV_3_isSelected == true && ENV_4_isSelected != true)
	{
		initializeBank(CC_Bank_03_02);
	}
	else if (ENV_4_isSelected == true && ENV_3_isSelected != true)
      	{
          	initializeBank(CC_Bank_01_04);
      	}
	else if (ENV_4_isSelected == true && ENV_3_isSelected == true)
      	{
        	initializeBank(CC_Bank_03_04);
      	}else
      	{
        	initializeBank(CC_Bank_01);
      	}

	// potis lesen
  	for(int i = 0; i < 16; i++)
  	{
    		for(int j = 0; j < 4; j++)
    		{
        		digitalWrite(Mux_DATA_pins[j], bitRead(i,j));
		        delayMicroseconds(25);
    		}
    		readMux(i,poti_Pins[0]);
    		readMux(i+16,poti_Pins[1]);
    		readMux(i+32,poti_Pins[2]);
  	}


}

void initializeBank(int bankArray)
{
  memcpy(ControllerNum_Ary, bankArray, sizeof(ControllerNum_Ary));
}

void readMux(int count, int pin)
{
  potiValue[count] 	= glaetten(analogRead(pin), 8);
  CC_Val[count] 	= mapValue(potiValue[count], 1);

  if(CC_Val[count] != CC_Alt[count])
  {
    sendMidiToUSB(Midi_SendChannel, ControllerNum_Ary[count], CC_Val[count]);
    sendMidiCommand(Midi_SendChannel, ControllerNum_Ary[count], CC_Val[count]);
    printToDisplay(ControllerNum_Ary[count], CC_Val[count]);

    CC_Alt[count] = CC_Val[count];
    startMillis = millis();
  }
}

void sendMidiCommand(int command, int controllerNumber, int controllerValue) 
{
  Serial1.write(command);//send note on or note off command 
  Serial1.write(controllerNumber);//send pitch data
  Serial1.write(controllerValue);//send velocity data
 
}

wie man sieht hab ich, um das ganze ein bisschen im Rahmen zu halten, die Funktion initializeBank()
die dann immer bei Änderung des Buttonstates die jeweilige Bank in den masterArray(ControllerNum_Ary)
verschiebt, der dann später verwendet wird um die Controllernummern dem gedrehten Btn zuzuordnen
und die Daten zu übertragen.

wie gesagt, Sinn und Unsinn des Ganzen ist es verschiedene Gruppen des MasterArrays auszutauschen
bzw. zu ersetzen wenn ein gewisser Knopf bzw. zwei gedrückt wurde/n oder nicht gedrückt ist/sind.
Mit 2 Knöpfe habe ich in Ihrer Kombination 4 Zustände. AUS/AUS, AN/AUS, AN/AN oder AUS/AN.
wobei ich AUS/AUS weg lasse und dann nur die anderen benutze
allerdings,
muss natürlich die Kombination die oben schon gezeigt ist, auch berücksichtigt werden
und mit ENV1oderENV3 und ENV2oderENV4 ausgewertet werden - das könnte ich aber auch
separat abfragen.

erstmal noch fragen ? hab ich was vergessen ?

Ach so, und das ganze läuft auf einem Arduino Mega.

masterheavy:
wie gesagt, Sinn und Unsinn des Ganzen ist es verschiedene Gruppen des MasterArrays auszutauschen
bzw. zu ersetzen wenn ein gewisser Knopf bzw. zwei gedrückt wurde/n oder nicht gedrückt ist/sind.
Mit 2 Knöpfe habe ich in Ihrer Kombination 4 Zustände. AUS/AUS, AN/AUS, AN/AN oder AUS/AN.

Son array geht auch mehrdimensional....
CC_[Bank_nr][performer]

Ist einfacher und ohne jegliches umkopieren.
Du fragst den Bank-Auswahl-Taster ab, bei jedem Switch wird die Bank hochgezählt. Ist die höchste Bank erreicht, ist die nächste Bank 0.

Macht jeder Licht-/-Tonmixer :wink:

Oder so ähnlich:

struct CC_Bank
{        
  byte center[4];
  byte potis[4];
  byte normalizer[4];
};

CC_Bank banks[] =
{
  { 
    { 10, 11, 12, 13 },
    { 20, 21, 22, 23 },
    { 30, 31, 32, 33 }
  },
  {
    { 50, 51, 52, 53 },
    { 60, 61, 62, 63 },
    { 70, 71, 72, 73 }
  }
};

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

  byte* ptr = reinterpret_cast<byte*>(&banks);
  for (unsigned int i = 0; i < sizeof(banks); i++)
  {
    if (i > 0)
    {
      if (i % 4 == 0) Serial.println();
      if (i % sizeof(CC_Bank) == 0) Serial.println("---");
    }

    Serial.print(*ptr++);
    Serial.print(' ');
  }

}

void loop() 
{
}

Ausgabe:

10 11 12 13 
20 21 22 23 
30 31 32 33 
---
50 51 52 53 
60 61 62 63 
70 71 72 73

Geht auch anders. Arrays und Strukturen kann man beliebig ineinander verschachteln.

Aber man kann die einzelnen Arrays getrennt ansprechen um Daten zu ändern. Und an kann einzelne Strukturen oder das ganze Array aus Strukturen als Array aus Bytes behandeln um es zu versenden

Serenifly war schon schneller, aber geht eben auch mit Array... Ich hab das mal auf einen Eintrag für jede Bank gebrochen.

const byte maxBank = 4;
const byte maxPerform = 127;
bool taster1 = false;
bool taster2 = false;
byte CC_[maxBank][maxPerform] = {"\0"};


void Ausgabe()
{
  Serial.println(F("Gebe Werte aus: "));
  for (int i = 0; i < maxBank; i++)
  {
    Serial.print(CC_[i][0]);
    Serial.print("\t");
  }
}

void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start..."));
  byte banknummer;
  if (taster1 == false && taster2 == false)
  {
    banknummer = 0;
    Serial.println(F("Taster1 gedrückt - Taster2 nicht"));
    Serial.println(F("Schreibe in Bank / performer "));
    Serial.print(banknummer);
    Serial.print(" / 0 den Wert: ");
    CC_[banknummer][0] = 78;
    Serial.println(CC_[banknummer][0]);
    taster2 = true;
    Serial.println();
  }
  if (taster1 == false && taster2 == true)
  {
    banknummer = 1;
    Serial.println(F("Taster1 nicht gedrückt - Taster2 gedrückt"));
    Serial.println(F("Schreibe in Bank / performer "));
    Serial.print(banknummer);
    Serial.print(" / 0 den Wert: ");
    CC_[banknummer][0] = 36;
    Serial.println(CC_[banknummer][0]);
    taster2 = false; taster1 = true;
    Serial.println();
  }
  if (taster1 == true && taster2 == false)
  {
    banknummer = 2;
    Serial.println(F("Taster1 gedrückt - Taster2 nichtgedrückt"));
    Serial.println(F("Schreibe in Bank / performer "));
    Serial.print(banknummer);
    Serial.print(" / 0 den Wert: ");
    CC_[banknummer][0] = 18;
    Serial.println(CC_[banknummer][0]);
    taster2 = true;
    Serial.println();
  }
  if (taster1 == true && taster2 == true)
  {
    banknummer = 3;
    Serial.println(F("Taster1 gedrückt - Taster2 gedrückt"));
    Serial.println(F("Schreibe in Bank / performer "));
    Serial.print(banknummer);
    Serial.print(" / 0 den Wert: ");
    CC_[banknummer][0] = 89;
    Serial.println(CC_[banknummer][0]);
  }
  Ausgabe();
}


void loop()
{
}

Ausgabe:

22:47:43.545 -> Start...
22:47:43.545 -> Taster1 gedrückt - Taster2 nicht
22:47:43.545 -> Schreibe in Bank / performer 
22:47:43.578 -> 0 / 0 den Wert: 78
22:47:43.578 -> 
22:47:43.578 -> Taster1 nicht gedrückt - Taster2 gedrückt
22:47:43.578 -> Schreibe in Bank / performer 
22:47:43.578 -> 1 / 0 den Wert: 36
22:47:43.578 -> 
22:47:43.578 -> Taster1 gedrückt - Taster2 nichtgedrückt
22:47:43.578 -> Schreibe in Bank / performer 
22:47:43.578 -> 2 / 0 den Wert: 18
22:47:43.578 -> 
22:47:43.578 -> Taster1 gedrückt - Taster2 gedrückt
22:47:43.578 -> Schreibe in Bank / performer 
22:47:43.578 -> 3 / 0 den Wert: 89
22:47:43.578 -> Gebe Werte aus: 
22:47:43.578 -> 78	36	18	89

Serenifly:
Oder so ähnlich:

  byte* ptr = reinterpret_cast<byte*>(&banks);

Wozu ist bitte das notwendig ?
Und wenn ich das richtig gesehen habe, auch aus anderen Beispielen zu struct, dann ist das sowas wie Objekte in
anderen Sprachen ?

Den Rest, also beides, das mit den Arrays und dem Struct, muss ich mir dann in Ruhe mal aneignen, und ausprobieren
und größere Zahlenkolonnen benutzen, damit ich sehe ob das mein Programm übersichtlicher macht oder ob ich das
dann vielleicht in eine externe Klasse gießen sollte um den Zahlenwust aus meinem Mainprogramm rauszuhalten.

und @my_xy_projekt - das du "banknummer" nicht global angelegt hast, war jetzt nur
weil es sich um ein Beispiel handelt oder ?

cheerz

Wozu ist bitte das notwendig ?

Weil banks etwas ganz anderes ist als eine unstrukturierte Sammlung von Bytes. Serenifly will es dennoch so verwenden.
(Die eigentliche Frage ist: "Warum das?")

Kann sein dass ich zu blöd bin und deswegen immer verwechsle welcher Index jetzt genau wofür ist, daher ist mein Mantra:
Mehrdimensionale Arrays sind immer ein Design-Fehler.

masterheavy:
Wozu ist bitte das notwendig ?

Weil ich die Struktur nicht als Struktur sondern als ein Byte Array behandeln wollte. Deshalb der Cast auf einen Zeiger auf Byte. Den kann kann dann im Prinzip wie ein Array verwenden. Und so die Struktur an eine Methode übergeben die mit der Struktur gar nicht umgehen kann.

Ist das bei jeder Anwendung nötig? Nein. Manchmal machen das Bibliotheken schon selbst. z.B. wenn eine Methode einen void* als Parameter hat kann man direkt alles übergeben. Der Cast auf byte findet dann intern statt. Das ist z.B. bei memcpy() so. In anderen Fällen gibt es aber nur Methoden für byte* die eigentlich ein Array möchten; z.B. Serial.write().

Wenn du nie die Struktur an einem Stück versenden möchtest brauchst du das hier auch nicht. Du scheinst da auch immer noch andere Informationen zu senden die die Daten beschreiben. Und/oder du entscheidest erst mal welcher Teil genau gesendet wird.

Aber es ist trotzdem praktisch zu wissen. Auf dem Arduino gibt es viele Kommunikations-Anwendungen wo man tatsächlich komplette Daten senden möchte, aber die Bibliothek schluckt nur Arrays. z.B. eine Ansammlung an Sensoren. Man hat einen Temperatur- und einen Feuchte-Sensor. Da ist es jetzt blöd ein Array zu haben in dem die zwei Werte eigentlich verschiedene Dinge sind. Eine Struktur erlaubt es zwei richtig benannte Variablen zusammenfassen. Diese Variablen können dann auch unterschiedliche Typen wie int und float haben. Und mit einem Trick kann man sie immer noch als ein Array behandeln.

Und ich brauchte in dem Test-Programm einfach einen Weg das schnell auszugeben ohne die Bestandteile einzeln anzufassen :slight_smile:

ob ich das
dann vielleicht in eine externe Klasse gießen sollte um den Zahlenwust aus meinem Mainprogramm rauszuhalten.

Strukturen und Klassen sind in C++ fast das gleiche. Der einzige Unterschied ist dass die Elemente einer Struktur automatisch public sind und die einer Klasse private.
Strukturen verwendet man normal wenn man nur eine Ansammlung von Daten und vielleicht einen Konstruktor hat. Und macht eine Klasse daraus wenn Methoden vorhanden sind. Aber eigentlich geht beides.

Für mein schlichtes Gemüt ist mir das irgendwie zu "mehrdimensional" :grin:

Ich würde für Konstanten immer den Programmspeicher in Erwägung ziehen und lieber mit Zahlen denn mit Zeigern hantieren. Hier mein prozeduraler Ansatz, basierend auf #2, getestet mit Mega2560:

const byte g_PerformerBank1        = 16;
const PROGMEM byte CC_PerformerBank1[g_PerformerBank1] = {74, 21, 73, 28, 75, 24, 77, 29, 71, 27, 72, 25, 76, 23, 22, 26};
const byte g_CenterPotis           = 12;
const PROGMEM byte CC_CenterPotis[g_CenterPotis]       = {35, 34, 33, 32, 31, 30, 41, 40, 39, 38, 37, 36};
const byte g_ADSR_Env1             = 4;
const PROGMEM byte CC_ADSR_Env1[g_ADSR_Env1]           = {14, 13, 12, 11};
const byte g_ADSR_Env2             = 4;
const PROGMEM byte CC_ADSR_Env2[g_ADSR_Env2]           = {18, 17, 16, 15};
const byte g_ADSR_Env3             = 4;
const PROGMEM byte CC_ADSR_Env3[g_ADSR_Env3]           = {95, 94, 93, 92};
const byte g_ADSR_Env4             = 4;
const PROGMEM byte CC_ADSR_Env4[g_ADSR_Env4]           = {99, 98, 97, 96};
const byte g_Normalizer            = 12;
const PROGMEM byte CC_Normalizer[g_Normalizer]         = {50, 51, 52, 53, 46, 47, 48, 49, 42, 43, 44, 45};

byte controllerNum (byte envA, byte envB, byte pos)
{
  byte wert = 0;
  if (pos < g_PerformerBank1)
  {
    wert = pgm_read_byte_near(CC_PerformerBank1 + pos);
  }
  else if (pos < g_PerformerBank1 + g_CenterPotis)
  {
    wert = pgm_read_byte_near(CC_CenterPotis + pos - g_PerformerBank1);
  }
  else if (pos < g_PerformerBank1 + g_CenterPotis + g_ADSR_Env1)
  {
    if (envA == 1) wert = pgm_read_byte_near(CC_ADSR_Env1 + pos - g_PerformerBank1 - g_CenterPotis);
    if (envA == 2) wert = pgm_read_byte_near(CC_ADSR_Env2 + pos - g_PerformerBank1 - g_CenterPotis);
    if (envA == 3) wert = pgm_read_byte_near(CC_ADSR_Env3 + pos - g_PerformerBank1 - g_CenterPotis);
    if (envA == 4) wert = pgm_read_byte_near(CC_ADSR_Env4 + pos - g_PerformerBank1 - g_CenterPotis);
  }
  else if (pos < g_PerformerBank1 + g_CenterPotis + g_ADSR_Env1 + g_Normalizer)
  {
    wert = pgm_read_byte_near(CC_Normalizer + pos - g_PerformerBank1 - g_CenterPotis - g_ADSR_Env1);
  }
  else if (pos < g_PerformerBank1 + g_CenterPotis + g_ADSR_Env1 + g_Normalizer + g_ADSR_Env1)
  {
    if (envB == 1) wert = pgm_read_byte_near(CC_ADSR_Env1 + pos - g_PerformerBank1 - g_CenterPotis - g_ADSR_Env1 - g_Normalizer);
    if (envB == 2) wert = pgm_read_byte_near(CC_ADSR_Env2 + pos - g_PerformerBank1 - g_CenterPotis - g_ADSR_Env1 - g_Normalizer);
    if (envB == 3) wert = pgm_read_byte_near(CC_ADSR_Env3 + pos - g_PerformerBank1 - g_CenterPotis - g_ADSR_Env1 - g_Normalizer);
    if (envB == 4) wert = pgm_read_byte_near(CC_ADSR_Env4 + pos - g_PerformerBank1 - g_CenterPotis - g_ADSR_Env1 - g_Normalizer);
  }
  return wert;
}

void setup() {
  Serial.begin(115200);
  Serial.println(F("Start...\n\t00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 "));
}

void loop() {
  Serial.print("1 - 2\t");
  for (int n = 0; n < 48; n++)
  {
    Serial.print(controllerNum(1, 2, n)); Serial.print(' ');
  }
  Serial.println(" ");
  Serial.print("3 - 2\t");
  for (int n = 0; n < 48; n++)
  {
    Serial.print(controllerNum(3, 2, n)); Serial.print(' ');
  }
  Serial.println(" ");
  Serial.print("1 - 4\t");
  for (int n = 0; n < 48; n++)
  {
    Serial.print(controllerNum(1, 4, n)); Serial.print(' ');
  }
  Serial.println(" ");
  Serial.print("3 - 4\t");
  for (int n = 0; n < 48; n++)
  {
    Serial.print(controllerNum(3, 4, n)); Serial.print(' ');
  }
  Serial.println(" ");
  Serial.println("   E N D   ");
  Serial.println(" ");
  // put your main code here, to run repeatedly:
  while (1);
}

Die Ausgabe sieht für mich plausibel aus.

Jetzt auch noch PROGMEM, das ist mit den Klassen und der Mehrdimensionalität in diesem Thema leider etwas durcheinander, aber ich bin halt gerade fertig geworden.

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