Forum: Mikrocontroller und Digitale Elektronik Integerwerte aus einem Array zerlegen und durch Schleifen laufen lassen


von Kolja L. (kolja82)


Lesenswert?

Guten Abend

Nachdem mir mein erster, dynamischer, Ansatz zu komplex ist,
würde ich es gerne erstmal so versuchen:
1
  const uint8_t lauflicht[18][2] = {
2
    {100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100},
3
    {010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010}
4
  };
5
6
  for (int j = 0; j <= 1; j++) {
7
    for (int i = 1; i <= 18; i++) {
8
9
      setPWM(j, lauflicht[i][j].substring(0, 1), lauflicht[i][j].substring(0, 1), lauflicht[i][j].substring(0, 1));
10
    }
11
   delay(1000);
12
  }

Was soll der Code machen?

Die Funktion setPWM() erwartet 4 Parameter.
Der erste ist die ID der RGB Leiste (1-18), die nächsten drei die 
Helligkeit der einzelnen Farben von 0-9.

So kann in dem Array ein "komplexes" Lauflicht programmiert werden.

Was macht der Code?
Nix, der Compiler (ArduinoIDE) meckert schon bei dem Array:
too many initializers for 'const uint8_t [2] {aka const unsigned char 
[2]}'

Dabei habe ich doch nur ein funktionierendes Array erweitert.

Könnte mir da jemand helfen?

von Johannes S. (Gast)


Lesenswert?

du hast die Initialisierung für ein Array
1
lauflicht[2][18]
definiert.

und substrings auf ein uint8_t geht auch nicht so wie du möchtest.

010 ist eine Konstante im Octalsystem.

von Kolja L. (kolja82)


Lesenswert?

OK, die Initialiesierung muss andersherum.
Das Beispiel war eine 3x3 Matrix ;-)

1
  int lauflicht[6][18] = {
2
    {100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100},
3
    {010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010},
4
    {100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100},
5
    {010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010},
6
    {100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100},
7
    {010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010}
8
  };
9
10
  for (int j = 0; j <= 1; j++) {
11
    for (int i = 1; i <= 18; i++) {
12
13
      setPWM(j, lauflicht[i][j].substring(0, 1), lauflicht[i][j].substring(0, 1), lauflicht[i][j].substring(0, 1));
14
    }
15
   delay(1000);
16
  }

So passt zumindest das Array :-)

Johannes S. schrieb:
> und substrings auf ein uint8_t geht auch nicht so wie du möchtest.

Stimmt!
Verstehe ich jetzt auch.

Muss ich die Zahl jetzt erst in ein String wandeln,
oder kann ich die "010" auch als Integer zerlegen?
Modulo fällt ja wegen der führenden Nullen weg...

Danke schomal

von Johannes S. (Gast)


Lesenswert?

Vorschlag: Array von Strukturelementen benutzen.
1
typedef  struct {
2
  uint8_t stripeIndex;
3
  uint8_t intensityRed;
4
  uint8_t intensityGreen;
5
  uint8_t intensityBlue;
6
} RGBITEM;
7
8
const RGBITEM rgbItems[] = {
9
  {0, 1, 0, 0 },
10
  {1, 255, 128, 42 }     // und noch viele mehr
11
};
12
13
void setRGBItem(uint16_t index) {
14
  setPWM(rgbItems[index].stripeIndex,
15
         rgbItems[index].intensityRed,
16
         rgbItems[index].intensityGreen,
17
         rgbItems[index].intensityBlue);
18
}

von Kolja L. (kolja82)


Lesenswert?

Johannes S. schrieb:
> Vorschlag: Array von Strukturelementen benutzen.

Das ist mir leider nicht anschaulich genug.
Aber prinzipiell verstehe ich , was du meinst.

Für das einfachere programmieren des Lichteffektes hätte ich gerne jeden 
Frame in einer Zeile.

Sollte ja auch funktionieren, wenn ich nur die "010" in R=0, G=1, B=0 
zerlegt bekommen würde.

Aber auch dir danke für die Idee!

von Dr. Sommer (Gast)


Lesenswert?

Kolja L. schrieb:
> Modulo fällt ja wegen der führenden Nullen weg...

Wieso, dann wird halt 0 übergeben:
1
setPWM(j, lauflicht[i][j] / 100, (lauflicht[i][j] / 10) % 10, lauflicht[i][j] % 10);
So werden die 3 Ziffern auseinander gedröselt und einzeln übergeben. Das 
ist allerdings ziemlich ineffizient, weil die meisten Prozessoren solche 
Divisionen nicht direkt können. Effizienter wäre z.B. so:
1
  uint16_t lauflicht[6][18] = {
2
    {0x100, 0x100, 0x100 ...},
3
    {0x010, 0x010, 0x010, ...},
4
    ...
5
  };
6
7
setPWM(j, lauflicht[i][j] / 256, (lauflicht[i][j] / 16) % 16, lauflicht[i][j] % 16);
Divisionen/Modulo mit 2-erPotenzen werden als Bits-Operationen 
kompiliert und sind viel schneller. Dazu werden die Zahlen hexadezimal 
definiert. Außerdem sollte man den Typ des Arrays als uint16_t 
definieren, damit er nicht unnötig groß ist (int kann z.B. auch 32bit 
groß sein, obwohl die Zahl nie größer 4095 wird), und um negative Zahlen 
ganz auszuschließen. Du könntest due setPWM Funktion so umbauen dass sie 
Zahlen von 0-15 nimmt; dann hast du gleich eine höhere Auflösung. Auf 
Computern im 10er-System zu rechnen ist generell nicht so optimal.
Alternativ kann man die 3 Farbwerte in 3 einzelne uint8_t packen, das 
braucht aber 50% mehr Speicher.
Warum speicherst du überhaupt zig mal die gleichen Werte im Array? Das 
ist sinnlos...

Als Schleifenzähler (i, j) sollte man size_t nehmen, weil dies 
vorzeichenlos ist und auf allen Plattformen groß genug für alle Arrays; 
"int" kann z.B. auf AMD64 zu klein sein.

von Johannes S. (Gast)


Lesenswert?

Kolja L. schrieb:
> Das ist mir leider nicht anschaulich genug.
> Aber prinzipiell verstehe ich , was du meinst.

Mit den Strukturelementen kann R,G, und B jeweils 0...255 sein. Man kann 
das auch in einen Hexadezimalwert schreiben, dann wäre es z.B. 
0xiirrggbb kodiert. Dann kann ii der Stripindex sein und der Rest die 
Farbwerte. Kommt aufs gleiche raus, aber mit der Struktur ist der 
Zugriff besser lesbar, aus dem uint32_t musst die Element maskieren und 
schieben, für rr z.B. ((value & 0x00ff0000) >> 16;

von Kolja L. (kolja82)


Lesenswert?

Dr. Sommer schrieb:
> uint16_t lauflicht[6][18] = {
>     {0x100, 0x100, 0x100 ...},
>     {0x010, 0x010, 0x010, ...},
>     ...
>   };

Das möchte ich, auch wenn es vielleicht albern ist,
der Übersichtlichkeit wegen nicht verwenden.

Dr. Sommer schrieb:
> setPWM(j, lauflicht[i][j] / 100, (lauflicht[i][j] / 10) % 10,
> lauflicht[i][j] % 10);

Wenn das funktionieren würde, ware ja super!

Leider gibt dieser Code:
1
void loop() {
2
3
  int lauflicht[6][18] = {
4
    {100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100},
5
    {010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010},
6
    {100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100},
7
    {010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010},
8
    {100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100},
9
    {010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010, 010}
10
  };
11
12
13
  for (int j = 1; j <= 6; j++) {
14
    
15
    for (int i = 1; i <= 18; i++) {     
16
      Serial.print("J:");      Serial.print(j);      Serial.print(" I: ");      Serial.print(i); 
17
      Serial.print(" R:");      Serial.print(lauflicht[j][i] / 100); 
18
      Serial.print(" G:");      Serial.print((lauflicht[j][i] / 10) % 10); 
19
      Serial.print(" B:");      Serial.println(lauflicht[j][i] % 10);      
20
      setPWM(j, lauflicht[j][i] / 100, (lauflicht[j][i] / 10) % 10, lauflicht[j][i] % 10);
21
    }
22
    
23
    delay(1000);
24
    
25
  }
26
27
28
  
29
} // loop

Diese Ausgabe:
1
J:1 I: 1 R:0 G:0 B:8
2
J:1 I: 2 R:0 G:0 B:8
3
J:1 I: 3 R:0 G:0 B:8
4
J:1 I: 4 R:0 G:0 B:8
5
J:1 I: 5 R:0 G:0 B:8
6
J:1 I: 6 R:0 G:0 B:8
7
J:1 I: 7 R:0 G:0 B:8
8
J:1 I: 8 R:0 G:0 B:8
9
J:1 I: 9 R:0 G:0 B:8
10
J:1 I: 10 R:0 G:0 B:8
11
J:1 I: 11 R:0 G:0 B:8
12
J:1 I: 12 R:0 G:0 B:8
13
J:1 I: 13 R:0 G:0 B:8
14
J:1 I: 14 R:0 G:0 B:8
15
J:1 I: 15 R:0 G:0 B:8
16
J:1 I: 16 R:0 G:0 B:8
17
J:1 I: 17 R:0 G:0 B:8
18
J:1 I: 18 R:1 G:0 B:0
19
J:2 I: 1 R:1 G:0 B:0
20
J:2 I: 2 R:1 G:0 B:0
21
J:2 I: 3 R:1 G:0 B:0
22
J:2 I: 4 R:1 G:0 B:0
23
J:2 I: 5 R:1 G:0 B:0
24
J:2 I: 6 R:1 G:0 B:0
25
J:2 I: 7 R:1 G:0 B:0
26
J:2 I: 8 R:1 G:0 B:0
27
J:2 I: 9 R:1 G:0 B:0
28
J:2 I: 10 R:1 G:0 B:0
29
J:2 I: 11 R:1 G:0 B:0
30
J:2 I: 12 R:1 G:0 B:0
31
J:2 I: 13 R:1 G:0 B:0
32
J:2 I: 14 R:1 G:0 B:0
33
J:2 I: 15 R:1 G:0 B:0
34
J:2 I: 16 R:1 G:0 B:0
35
J:2 I: 17 R:1 G:0 B:0
36
J:2 I: 18 R:0 G:0 B:8

Werde mir trotzdem nochmal die Modulo Funktion anschauen.

von Dr. Sommer (Gast)


Lesenswert?

Kolja L. schrieb:
> Diese Ausgabe:

Tja, weil die führende 0 die Zahl als Oktal-Zahl markiert, somit ist 
"010" dezimal der Wert 8.

von Johannes S. (Gast)


Lesenswert?

Weil 010 = 8 ist. Schrieb ich doch schon.
Heute ist irgendwie der Tag des nicht-Lesens...

von Kolja L. (kolja82)


Lesenswert?

Dr. Sommer schrieb:
> Kolja L. schrieb:
>> Modulo fällt ja wegen der führenden Nullen weg...
>
> Wieso, dann wird halt 0 übergeben:

Dann habe ich das falsch verstanden?

von Kolja L. (kolja82)


Lesenswert?

Aber so:
1
void loop() {
2
3
  uint16_t  lauflicht[2][18] = {
4
    {0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100},
5
    {0x010, 0x010, 0x010, 0x010, 0x010, 0x010, 0x010, 0x010, 0x010, 0x010, 0x010, 0x010, 0x010, 0x010, 0x010, 0x010, 0x010, 0x010}
6
  };
7
8
9
  for (int j = 1; j <= 2; j++) {
10
    
11
    for (int i = 1; i <= 18; i++) {     
12
      Serial.print("J:");      Serial.print(j);      Serial.print(" I: ");      Serial.print(i); 
13
      Serial.print(" R:");      Serial.print(lauflicht[j][i] / 256); 
14
      Serial.print(" G:");      Serial.print((lauflicht[j][i] / 16) % 16); 
15
      Serial.print(" B:");      Serial.println(lauflicht[j][i] % 16);      
16
      setPWM(j, lauflicht[j][i] / 256, (lauflicht[j][i] / 16) % 16, lauflicht[j][i] % 16);
17
    }
18
    
19
    delay(2000);
20
    
21
  }
22
23
24
  
25
} // loop

Funktioniert es leider auch nicht:

J:1 I: 1 R:0 G:1 B:0
J:1 I: 2 R:0 G:1 B:0
J:1 I: 3 R:0 G:1 B:0
J:1 I: 4 R:0 G:1 B:0
J:1 I: 5 R:0 G:1 B:0
J:1 I: 6 R:0 G:1 B:0
J:1 I: 7 R:0 G:1 B:0
J:1 I: 8 R:0 G:1 B:0
J:1 I: 9 R:0 G:1 B:0
J:1 I: 10 R:0 G:1 B:0
J:1 I: 11 R:0 G:1 B:0
J:1 I: 12 R:0 G:1 B:0
J:1 I: 13 R:0 G:1 B:0
J:1 I: 14 R:0 G:1 B:0
J:1 I: 15 R:0 G:1 B:0
J:1 I: 16 R:0 G:1 B:0
J:1 I: 17 R:0 G:1 B:0
J:1 I: 18 R:239 G:15 B:14
J:2 I: 1 R:254 G:14 B:15
J:2 I: 2 R:147 G:11 B:0
J:2 I: 3 R:63 G:15 B:14
J:2 I: 4 R:0 G:0 B:15
J:2 I: 5 R:0 G:0 B:0
J:2 I: 6 R:0 G:0 B:0
J:2 I: 7 R:0 G:0 B:0
J:2 I: 8 R:0 G:0 B:0
J:2 I: 9 R:0 G:0 B:0
J:2 I: 10 R:239 G:15 B:14
J:2 I: 11 R:254 G:14 B:15
J:2 I: 12 R:0 G:0 B:0
J:2 I: 13 R:0 G:0 B:0
J:2 I: 14 R:0 G:0 B:0
J:2 I: 15 R:0 G:0 B:0
J:2 I: 16 R:0 G:0 B:1
J:2 I: 17 R:0 G:0 B:0
J:2 I: 18 R:0 G:4 B:0


Vielleicht reden wir aneinander vorbei?

von Dr. Sommer (Gast)


Lesenswert?

Könnte vielleicht daran liegen, dass die Indices des äußeren Arrays 0-1 
sind, und du 1-2 iterierst... Lies doch mal ein Buch über C.

von Kolja L. (kolja82)


Lesenswert?

Dr. Sommer schrieb:
> Könnte vielleicht daran liegen, dass die Indices des äußeren
> Arrays 0-1
> sind, und du 1-2 iterierst... Lies doch mal ein Buch über C.

Danke, Tippfehler, sorry.

Ändert aber auch nichts.

von Dr. Sommer (Gast)


Lesenswert?

Kolja L. schrieb:
> Ändert aber auch nichts.

Unwahrscheinlich. Zeig den korrigierten Code.

von Kolja L. (kolja82)


Lesenswert?

Dr. Sommer schrieb:
> Unwahrscheinlich. Zeig den korrigierten Code.

Mea culpa, da war ein "j" wo ein "i" sein sollte...:
1
void loop() {
2
3
  uint16_t  lauflicht[2][18] = {
4
    {0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100},
5
    {0x010, 0x010, 0x010, 0x010, 0x010, 0x010, 0x010, 0x010, 0x010, 0x010, 0x010, 0x010, 0x010, 0x010, 0x010, 0x010, 0x010, 0x010}
6
  };
7
8
9
  for (int j = 0; j <= 1; j++) {
10
    
11
    for (int i = 0; i <= 17; i++) {     
12
      Serial.print("J:");      Serial.print(j);      Serial.print(" I: ");      Serial.print(i); 
13
      Serial.print(" R:");      Serial.print(lauflicht[j][i] / 256); 
14
      Serial.print(" G:");      Serial.print((lauflicht[j][i] / 16) % 16); 
15
      Serial.print(" B:");      Serial.println(lauflicht[j][i] % 16);      
16
      setPWM(i, (lauflicht[j][i] / 256) * 400, ((lauflicht[j][i] / 16) % 16) * 400, (lauflicht[j][i] % 16) *400);
17
    }
18
    
19
    delay(2000);
20
    
21
  }
22
23
24
  
25
} // loop

das funktioniert schon mal, Danke!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.