Pages: [1] 2   Go Down
Author Topic: Kann man diesen Code vereinfachen?  (Read 1379 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
God Member
*****
Karma: 0
Posts: 696
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo,

ich möchte auf meinem LCD Display 20x4 den Status der LEDs anzeigen, indem jder einzelnen (von 18) LEDs eine Spalte mit drei Zeilen zugeordnet wird. Also wie bei einem Equalizer geht dann ein Balken über drei Zeilen hoch. Dazu habe ich folgende Chars definiert:
Code:
byte level2[8] = {B00000, B00000, B00000, B00000, B00000, B00000, B11111, B11111};
byte level3[8] = {B00000, B00000, B00000, B00000, B00000, B11111, B11111, B11111};
byte level4[8] = {B00000, B00000, B00000, B00000, B11111, B11111, B11111, B11111};
byte level5[8] = {B00000, B00000, B00000, B11111, B11111, B11111, B11111, B11111};
byte level6[8] = {B00000, B00000, B11111, B11111, B11111, B11111, B11111, B11111};
byte level7[8] = {B00000, B11111, B11111, B11111, B11111, B11111, B11111, B11111};
byte level8[8] = {B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11111};

level1 ist der Standard "_", so spare ich mir ein weiteres Zeichen auf.
Später rufe ich dann diese FUnktion auf:
Code:
void showLEDlevels() {
    lcd.setCursor(0,0);
    lcd.print("bbbbbbwwwwwwrrggvm");
    for (int c=0; c<18; c++) {
      switch (brightness[c]) {
        case 0:
          lcd.setCursor(c,3);
          lcd.print("_");
          lcd.setCursor(c,2);
          lcd.print(" ");
          lcd.setCursor(c,1);
          lcd.print(" ");
          break;
        case 1:
          lcd.setCursor(c,3);
          lcd.write(1);
          lcd.setCursor(c,2);
          lcd.print(" ");
          lcd.setCursor(c,1);
          lcd.print(" ");
          break;      
        case 2:
          lcd.setCursor(c,3);
          lcd.write(2);
          lcd.setCursor(c,2);
          lcd.print(" ");
          lcd.setCursor(c,1);
          lcd.print(" ");
          break;
        case 3:
          lcd.setCursor(c,3);
          lcd.write(3);
          lcd.setCursor(c,2);
          lcd.print(" ");
          lcd.setCursor(c,1);
          lcd.print(" ");
          break;
        case 4:
          lcd.setCursor(c,3);
          lcd.write(4);
          lcd.setCursor(c,2);
          lcd.print(" ");
          lcd.setCursor(c,1);
          lcd.print(" ");  
          break;      
        case 5:
          lcd.setCursor(c,3);
          lcd.write(5);
          lcd.setCursor(c,2);
          lcd.print(" ");
          lcd.setCursor(c,1);
          lcd.print(" ");
          break;
        case 6:
          lcd.setCursor(c,3);
          lcd.write(6);
          lcd.setCursor(c,2);
          lcd.print(" ");
          lcd.setCursor(c,1);
          lcd.print(" ");
          break;
        case 7:
          lcd.setCursor(c,3);
          lcd.write(7);
          lcd.setCursor(c,2);
          lcd.print(" ");
          lcd.setCursor(c,1);
          lcd.print(" ");
          break;
        case 8:
          lcd.setCursor(c,3);
          lcd.write(7);
          lcd.setCursor(c,2);
          lcd.print("_");
          lcd.setCursor(c,1);
          lcd.print(" ");
          break;
        case 9:
          lcd.setCursor(c,3);
          lcd.write(7);
          lcd.setCursor(c,2);
          lcd.write(1);
          lcd.setCursor(c,1);
          lcd.print(" ");
          break;
        case 10:
          lcd.setCursor(c,3);
          lcd.write(7);
          lcd.setCursor(c,2);
          lcd.write(2);
          lcd.setCursor(c,1);
          lcd.print(" ");
          break;
        case 11:
          lcd.setCursor(c,3);
          lcd.write(7);
          lcd.setCursor(c,2);
          lcd.write(3);
          lcd.setCursor(c,1);
          lcd.print(" ");
          break;
        case 12:
          lcd.setCursor(c,3);
          lcd.write(7);
          lcd.setCursor(c,2);
          lcd.write(4);
          lcd.setCursor(c,1);
          lcd.print(" ");
          break;
        case 13:
          lcd.setCursor(c,3);
          lcd.write(7);
          lcd.setCursor(c,2);
          lcd.write(5);
          lcd.setCursor(c,1);
          lcd.print(" ");
          break;
        case 14:
          lcd.setCursor(c,3);
          lcd.write(7);
          lcd.setCursor(c,2);
          lcd.write(6);
          lcd.setCursor(c,1);
          lcd.print(" ");
          break;
        case 15:
          lcd.setCursor(c,3);
          lcd.write(7);
          lcd.setCursor(c,2);
          lcd.write(7);
          lcd.setCursor(c,1);
          lcd.print(" ");
          break;
        case 16:
          lcd.setCursor(c,3);
          lcd.write(7);
          lcd.setCursor(c,2);
          lcd.write(7);
          lcd.setCursor(c,1);
          lcd.print("_");
          break;
        case 17:
          lcd.setCursor(c,3);
          lcd.write(7);
          lcd.setCursor(c,2);
          lcd.write(7);
          lcd.setCursor(c,1);
          lcd.write(1);
          break;
        case 18:
          lcd.setCursor(c,3);
          lcd.write(7);
          lcd.setCursor(c,2);
          lcd.write(7);
          lcd.setCursor(c,1);
          lcd.write(2);
          break;
        case 19:
          lcd.setCursor(c,3);
          lcd.write(7);
          lcd.setCursor(c,2);
          lcd.write(7);
          lcd.setCursor(c,1);
          lcd.write(3);
          break;
        case 20:
          lcd.setCursor(c,3);
          lcd.write(7);
          lcd.setCursor(c,2);
          lcd.write(7);
          lcd.setCursor(c,1);
          lcd.write(4);    
          break;      
        case 21:
          lcd.setCursor(c,3);
          lcd.write(7);
          lcd.setCursor(c,2);
          lcd.write(7);
          lcd.setCursor(c,1);
          lcd.write(5);
          break;
        case 22:
          lcd.setCursor(c,3);
          lcd.write(7);
          lcd.setCursor(c,2);
          lcd.write(7);
          lcd.setCursor(c,1);
          lcd.write(6);
          break;
        case 23:
          lcd.setCursor(c,3);
          lcd.write(7);
          lcd.setCursor(c,2);
          lcd.write(7);
          lcd.setCursor(c,1);
          lcd.write(7);
          break;
      }
    }

Brightness wird vorher durch mapping definiert:
Code:
brightness[pinCount]=map(i[pinCount], 0, 255, 0, 23);
(pinCount ist auch ne schleife von 0-17)

Irgendwie finde ich das recht viel Code für diese banale Geschichte und frag mich, ob das einfacher geht?
Hat jemand ne Idee?

Gruß
« Last Edit: November 07, 2011, 06:24:32 pm by currymuetze » Logged

Munich/Germany
Offline Offline
God Member
*****
Karma: 9
Posts: 642
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Nicht getestet und nicht auf Tippfehler geprüft:
Code:
void showLEDlevels() {
    lcd.setCursor(0,0);
    lcd.print("bbbbbbwwwwwwrrggvm");
    for (int c=0; c<18; c++) {
      lcd.setCursor(c,3);
      if (brightness[c] == 0)
        lcd.print("_");
      else if (brightness[c] < 7)
        lcd.write(brightness[c]);
      else
        lcd.write(7);

      lcd.setCursor(c,2);
      if (brightness[c] < 8)
        lcd.print(" ");
      else if (brightness[c] == 8)
        lcd.print("_");
      else if (brightness[c] < 15)
        lcd.write(brightness[c] & 7);
      else
        lcd.write(7);

      lcd.setCursor(c,1);
      if (brightness[c] < 16)
        lcd.print(" ");
      else if (brightness[c] == 16)
        lcd.print("_");
      else if (brightness[c] < 23)
        lcd.write(brightness[c] & 7);
      else
        lcd.write(7);
      }
    }
Logged

_______
Manfred

Munich/Germany
Offline Offline
God Member
*****
Karma: 9
Posts: 642
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Es geht aber auch noch etwas kürzer:
Code:
void showLEDlevels() {
    lcd.setCursor(0,0);
    lcd.print("bbbbbbwwwwwwrrggvm");
    for (int c=0; c<18; c++) {
      lcd.setCursor(c,3);
      if (brightness[c] == 0)
        lcd.print("_");
      else
        lcd.write((brightness[c] < 7) ? brightness[c] : 7);

      lcd.setCursor(c,2);
      if (brightness[c] <= 8)
        lcd.print((brightness[c] == 8) ? "_" : " ");
      else
        lcd.write((brightness[c] < 15) ? (brightness[c] & 7) : 7);

      lcd.setCursor(c,1);
      if (brightness[c] <= 16)
        lcd.print((brightness[c] == 16) ? "_" : " ");
      else
        lcd.write((brightness[c] < 23) ? (brightness[c] & 7) : 7);
      }
    }
Logged

_______
Manfred

Munich/Germany
Offline Offline
God Member
*****
Karma: 9
Posts: 642
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Damit dürfte die Grenze weitestgehend erreicht sein:
Code:
void showLEDlevels() {
    int8_t bt;
    lcd.setCursor(0, 0);
    lcd.print("bbbbbbwwwwwwrrggvm");
    for (int c = 0; c < 18; c++) {
      for (int e = 0; e < 3; e++) {
        bt = e * 8;
        lcd.setCursor(c, 3 - e);
        if (brightness[c] <= bt)
          lcd.print((brightness[c] == bt) ? "_" : " ");
        else
          lcd.write((brightness[c] < (bt + 8 - 1)) ? (brightness[c] & 7) : 7);
        }
      }
    }
Logged

_______
Manfred

Offline Offline
God Member
*****
Karma: 0
Posts: 696
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
sieht gut aus, schön kurz - muss wohl noch ne Menge lernen.
Danke, werds mal heut abend testen

Gruß
Logged

NRW
Offline Offline
Sr. Member
****
Karma: 1
Posts: 372
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Und das vom cuerrymuetze im ersten Post gezeigte und das was MaFu gezeigt hat macht das selbe?
Das kann man ja fast garnicht glauben!
Ich hätte mit meinen Kentnissen wohl auch eher cuerrymuetzes Version raus bekommen.

Wie schön das es Leute gibt dies einfach drauf haben!
An dieser Stelle auch mal ein DANK von mir an die, die hier nicht müde werden deppen wie mir immer wieder mir Rat zur seite zu stehen.
Ich kenne das auch anders.

Danke
Thorsten
Logged

0
Offline Offline
Faraday Member
**
Karma: 19
Posts: 3420
20 LEDs are enough
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Das IF statement

Code:
        if (brightness[c] <= bt)
          lcd.print((brightness[c] == bt) ? "_" : " ");
        else
          lcd.write((brightness[c] < (bt + 8 - 1)) ? (brightness[c] & 7) : 7);
        }

könnte man zunächst nochmal komprimieren:

Code:
     lcd.write( (brightness[c] <= bt)? ((brightness[c] == bt) ? "_" : " ")
                                                    : ((brightness[c] < bt + 8 - 1) ? (brightness[c] & 7) : 7) );       

Bei scharfem Hinschauen fällt dann auf, daß c nur 18 Werte und bt nur 3 Werte annehmen kann (die direkt von e abhängen). Also könnte man das Ergebnis vorberechnet in einem Array "precomputed_value" ablegen und dann einfach schreiben.

Code:
    lcd.write(precomputed_value[c+18*e]);
Logged

Check out my experiments http://blog.blinkenlight.net

Offline Offline
God Member
*****
Karma: 0
Posts: 696
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Udo,
das if statement ersetzen hat leider nicht geklappt, da hab ich nen Fehler bekommen.
Könnt ihr mir mal den Operator ? erklären?
Was genau passiert hier: lcd.print((brightness[c] == bt) ? "_" : " ");

Leider finde ich dazu keinerlei Informationen, vermutlich weil ich nicht genau weiss wonach ich suchen muss, aber in dieser Übersicht taucht das ? leider nicht auf: http://arduino.cc/en/Reference/HomePage

Gruß
Logged

Munich/Germany
Offline Offline
God Member
*****
Karma: 9
Posts: 642
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Der Fragezeichen/Doppelpunkt-Operator ist ein sehr elegantes Konstrukt der Sprache C. Leider führt er oft auch dazu, dass der Code schwerer lesbar wird.
Im Prinzip entspricht er einer IF...ELSE Anweisung mit gleichzeitiger Wertübergabe. Das Konstrukt vor dem Fragezeichen ist die Abfrage und muss ein boolsches Ergebnis liefern. Ist das Ergebnis wahr, wird der Wert nach dem Fragezeichen (und vor dem Doppelpunkt) zurückgeliefert, bei Falsch der Wert nach dem Doppelpunkt.

Code:
ergebnis = (irgendeinwert >= 20) ? 5 : 10;
ist gleichzusetzen mit folgender IF-Konstruktion:
Code:
if (irgendeinwert >= 20)
    ergebnis = 5;
else
    ergebnis = 10;
Logged

_______
Manfred

0
Offline Offline
Faraday Member
**
Karma: 19
Posts: 3420
20 LEDs are enough
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ob "?" Code schwerer lesbar macht oder nicht ist Ansichts- und Gewohnheitssache. Auch IF Statements und geschachtelte Ausdrücke können beliebig unlesbar sein. Das hängt mehr vom Entwickler ab als von spezifischen Statements.

Ein Unterschied zwischen IF und ? der gerne übersehen wird ist, daß ? ein Operator ist und IF eine Anweisung. D.h. ? liefert einen Wert zurück, IF nicht. Das führt dazu, daß ? unter Umständen zur Compilezeit schon aufgelöst werden kann. Sowas kann man ausnutzen um Berechnungen in den Makroprozessor zu schieben. Ob man das immer tun sollte kann man diskutieren.

Hier ein Beispiel für einen in Python geschriebenen Generator:
http://blog.blinkenlight.net/experiments/removing-flicker/glowing-bounce/

Und hier ein ähnliches Beispiel ohne Python dafür mit Makros und "?"
http://blog.blinkenlight.net/experiments/removing-flicker/knight-rider-no-flicker/

In beiden Varianten wird man mit IF Anweisungen nicht annähernd die gewünschte Performance hinkriegen. Allerdings muß man sich klar sein, daß diese Technik bei längeren Dingen recht schnell noch komplexer wird. Siehe hier:
http://blog.blinkenlight.net/experiments/removing-flicker/multiple-modes-without-flicker/.

Von den Schwierigkeiten beim Debuggen ganz zu schweigen. D.h. nicht zur Nachahmung empfohlen, außer man hat Performanceprobleme und will nicht "von außen generieren". Die Alternative sind Template Metaprogramme, die sind auch nicht besser smiley-wink
Logged

Check out my experiments http://blog.blinkenlight.net

Offline Offline
Jr. Member
**
Karma: 0
Posts: 58
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Habe ich das jetzt richtig verstanden?

Der ?-Code kann zur Compilezeit aufgelöst werden, wenn das Ergebnis feststeht.
Damit kann ich mir Schreibarbeit ersparen.
?-Code funktioniert dann wie ein intelligentes #define (unter obiger Voraussetzung).

Wenn das Ergebnis nicht feststeht wie beim Abfragen eines Pins, bringt mir der ?-Code dann Vorteile? Ist er schneller als If .. else?

Ich habe ein paar einfachste Zeitmessungen gemacht und keinen Unterschied feststellen können.

Logged

0
Offline Offline
Faraday Member
**
Karma: 19
Posts: 3420
20 LEDs are enough
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Wenn Du es genau wissen willst musst Du Dir den generierten Maschinencode anschauen. In der Regel ist es eine schlechte Idee auf Verdacht auf Performance zu optimieren. Programme sollten so geschrieben werden, daß sie leicht lesbar und gut wartbar sind. Performance optimiert man an den Stellen an denen es Probleme gibt, den Rest zu optimieren ist Zeitverschwendung. Was im Einzelfall schneller ist kann man nicht sagen weil moderne Compiler Optimierungen berechnen.
« Last Edit: November 10, 2011, 04:08:31 pm by Udo Klein » Logged

Check out my experiments http://blog.blinkenlight.net

Berlin
Offline Offline
Jr. Member
**
Karma: 0
Posts: 91
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Blöde frage, wo kann man sich den Maschinencode bei Arduino anschauen?
Logged

Nothing is impossible ^^

Forum Moderator
BZ (I)
Offline Offline
Brattain Member
*****
Karma: 234
Posts: 20218
+39 349 2158303
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Der Maschinencode wird in einem File .HEX gespeichert. (wenn Du während du den Kompilierknopf dückst die SHIFT Taste gedrückt hälst compiliert IDE mit allen Komentaren. Darin findest Du dann den Path des -hex-Files). Das hilft Dir aber nicht weiter da es nur Zahlen sind. Um auf Mnemonics zu kommen ( die Abkürzungen der Maschienenbefehle) bedarf es eines Disassemblers für den jeweiligen Controller.
Dann hast Du aber immernoch jede Menge Code durchzuarbeiten. Das einfach BLINK-Beispiel erzeugt ja schon fast 1KB an code obwohl es gerade mal eil LEd ein und ausschaltet.

Viele Grüße Uwe

Logged

0
Offline Offline
Faraday Member
**
Karma: 19
Posts: 3420
20 LEDs are enough
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Das HEX File enthält nur den Maschinencode. Was man sich eigentlich anschaut ist das .elf File. Das Program um die Files anzuschauen ist avr-objdump. Die Details wurden hier schon mal breit getreten: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1241117308/0#0
« Last Edit: November 11, 2011, 11:28:58 am by Udo Klein » Logged

Check out my experiments http://blog.blinkenlight.net

Pages: [1] 2   Go Up
Jump to: