- SF800 Solar Speicher Tutorial         
Ergebnis 1 bis 10 von 63

Thema: Farben nach R,G,B umwandeln in 4-stell. hex-code?

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    18.03.2018
    Beiträge
    2.669
    Spuckt genau dasselbe aus.

    Falls der Controller nur 8 Bit beherrschen würde, müsste man die 16-Bit-Farbwerte getrennt in Low- und High-Byte (MSB und LSB) ablegen und anders rechnen.

    Code:
    Hauptprogramm vor Aufruf:
    col16=0
    r=255
    g=102
    b=78
    
    Hauptprogramm nach rgb zu col16-Berechnung (rgb gelöscht):
    col16=64297
    r=0
    g=0
    b=0
    
    Unterprogramm color16 zu RGB:
    color16=64297
    R=248
    G=100
    B=72
    
    Hauptprogramm nach col16 zu rgb:
    col16=64297
    r=248
    g=100
    b=72

  2. #2
    HaWe
    Gast
    Der Grund ist doch klar:
    ein 16bit Integer dividiert durch 2048 ist gleich >>11, und damit immer ein 5bit Wert, und passt damit immer in ein 8bit Byte.

    warum sollte die MCU nur 8 bit beherrschen? die 8bit AVRs rechnen bis zu int32_t, und die 32bit MCUs bis int64_t.
    Ich bin mal auf Ceos' Lösung gespannt, aber ist ja eh nicht so schrecklich eilig.

  3. #3
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    18.03.2018
    Beiträge
    2.669
    Im Übrigen war es die falsche Schreibweise, die zu den merkwürdigen Ergebnissen führte:

    Code:
          
       R = (uint8_t)(color16 / 2048)*8; ;
       G = (uint8_t)(color16 & 2016)/8;;
       B = (uint8_t)(color16 & 31)*8;
    was immer die Schreibweise (uint8_t) bewirken sollte. Hier hast Du offenbar uint8_t nur auf die Folgeausdrücke angewandt. Also:
    Code:
    uint8_t(color16 & 2016)
    und das dann durch 8 dividiert. Du stampfst
    Code:
    (color16 & 2016)
    auf 8 Bit ein (obwohl Du an der Stelle noch 16 Bit brauchst - eigentlich nur 11). Richtig wäre die Schreibweise und Funktion, die Du wolltest, so:

    Code:
       R = uint8_t((color16 / 2048)*8);
       G = uint8_t((color16 & 2016)/8);
       B = uint8_t((color16 & 31)*8);
    Allerdings habe ich woanders gelesen, dass man statt uint8_t() lieber byte() verwenden soll. Wäre der bessere Stil (kann man sehen wie man möchte):

    "An unsigned char data type that occupies 1 byte of memory. It is the same as the byte datatype. The unsigned char datatype encodes numbers from 0 to 255. For consistency of Arduino programming style, the byte data type is to be preferred."
    Arduino: Difference in “Byte” VS “uint8_t” VS “unsigned char”
    Geändert von Moppi (10.09.2018 um 21:56 Uhr)

  4. #4
    HaWe
    Gast
    nein, das stimmt doch nicht, was du schreibst:
    ich habe deine gesammelten Codes in allen erdenklichen Klammerungen getestet, auch der obigen, und es hat nie funktioniert. Da du nie vollständigen Code gepostet hast, habe ich das tatsächlich hier und da ggf missverstanden, aber deine andere Klammerung von oben per
    R = uint8_t((color16 / 2048 )*8 );
    G = uint8_t((color16 & 2016)/8 );
    B = uint8_t((color16 & 31)*8 );
    hat ja auch nicht funktioniert.

    Wenn du allerdings einen funktionierenden, kompilierfähigen Arduino-Sketch hast, selber von dir getestet, stelle ihn gerne ein, ich bin sehr gespannt.

    byte ist i.Ü.auch nicht "besser", es ist einfach nur Arduino Kauderwelsch,
    hingegen uin8_t usw. sind die stdint-Dateitypen u.a. auch für C++11 ,
    und weil Arduino den gpp mit C++11 verwendet, funktioniert das selbstverständlich 100% standardgemäß.

    Und das funktioniert dann auch ohne weiteres auf dem Raspi mit gcc/g++, wenn man will - im Gegensatz zu byte, das müsste man dann erst mal neu definieren als #define byte uint8_t.

    übrigens heißt es nicht
    uint8_t ((color16 / 2048 )*8 );
    sondern
    (uint8_t) ((color16 / 2048 )*8 );
    denn für type casting schreibt man in C den Ziel-Datentyp in runde Klammern.
    Aber auch DAS habe ich getestet, ebenfalls leider mit falschem Ergebnis, aber trotzdem herzlichen Dank für deine Ideen!

    Und wie gesagt, ich freue mich auf einen funktionierenden, kompilierfähigen Arduino-Sketch von dir, vorher selber von dir getestet...

  5. #5
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    18.03.2018
    Beiträge
    2.669
    Ich habe gestern Abend ja noch diese Varianten ausprobiert.

    Die Eine:
    Code:
    void Color16bit2colorRGB(uint16_t color16, uint16_t &R, uint16_t &G, uint16_t &B) {
    
       R = (uint8_t)((color16 / 2048)*8);
       G = (uint8_t)((color16 & 2016)/8);
       B = (uint8_t)((color16 & 31)*8);
       
       Serial.println("");
       Serial.println("Unterprogramm color16 zu RGB:");
       Serial.println( (String)"color16="+(String)color16);
       Serial.println( (String)"R="+(String)R);
       Serial.println( (String)"G="+(String)G);
       Serial.println( (String)"B="+(String)B); 
    }
    und die Andere:
    Code:
    void Color16bit2colorRGB(uint16_t color16, uint16_t &R, uint16_t &G, uint16_t &B) {
    
       R = uint8_t((color16 / 2048)*8);
       G = uint8_t((color16 & 2016)/8);
       B = uint8_t((color16 & 31)*8);
       
       Serial.println("");
       Serial.println("Unterprogramm color16 zu RGB:");
       Serial.println( (String)"color16="+(String)color16);
       Serial.println( (String)"R="+(String)R);
       Serial.println( (String)"G="+(String)G);
       Serial.println( (String)"B="+(String)B); 
    }
    Beide liefern dasselbe Ergebnis (sogar heute Morgen noch):
    Code:
    Hauptprogramm vor Aufruf:
    col16=0
    r=255
    g=102
    b=78
    
    Hauptprogramm nach rgb zu col16-Berechnung (rgb gelöscht):
    col16=64297
    r=0
    g=0
    b=0
    
    Unterprogramm color16 zu RGB:
    color16=64297
    R=248
    G=100
    B=72
    
    Hauptprogramm nach col16 zu rgb:
    col16=64297
    r=248
    g=100
    b=72
    Dasselbe Ergebnis erzielst Du auch mit:
    Code:
    void Color16bit2colorRGB(uint16_t color16, uint16_t &R, uint16_t &G, uint16_t &B) {
    
       R = (uint8_t)(color16 / 2048)*8;
       G = (uint8_t)((color16 & 2016)/8);
       B = (uint8_t)(color16 & 31)*8;
       
       Serial.println("");
       Serial.println("Unterprogramm color16 zu RGB:");
       Serial.println( (String)"color16="+(String)color16);
       Serial.println( (String)"R="+(String)R);
       Serial.println( (String)"G="+(String)G);
       Serial.println( (String)"B="+(String)B); 
    }
    habe ich auch gerade probiert. Und funktioniert erwartungsgemäß. Hier ist die Frage dann, warum soll das so funktionieren? Das liegt daran, dass bei der Berechnung von R schon nach der ersten Operation - color16 geteilt durch 2048 - nur noch 8 Bit benötigt werden und dieser Ausdruck ist geklammert. Bei der Berechnung von G funktioniert es nicht mehr, weil nach der Rechnung - color16 UND 2016 - 11 Bit übrig bleiben, die erst mit dem Teilen durch 8 auf 8 Bit reduziert werden. Bei der Berechnung von B - color16 UND 31 - geht es nur um die untersten 5 Bit, die hier maskiert werden und durch die Multiplikation mit 8 dann auf 8 Bit erweitert werden.

    Gestern war der Kopf schon etwas voll, vom ganzen Hin und Her.
    Um das Ergebnis und nicht einzelne Rechenschritte umzuwandeln, hätte man gleich die Klammerung der gesamten Rechnung versuchen sollen
    Code:
    G = (uint8_t)(....);
    Zumal Du das an anderer Stelle ja auch schon von Anfang an gemacht hast, nämlich hier:
    Code:
    uint16_t ColorRGB216bit(uint16_t R, uint16_t G, uint16_t B) {
    
       return  (uint16_t)((R/8)*2048) | (uint16_t)((G/4)*32) | (uint16_t)(B/8);
    }
    Um das alles richtig zu verstehen, muss man Bit-Rechnung verinnerlicht haben. Einfach mal so da was zu übernehmen, sich nicht bewusst sein, was es bedeutet und deshalb nicht die richtigen Schlüsse ziehen können, ist eben nicht der richtige Ansatz. Aber ausreichend erklärt sollte ich es nun haben, denke ich.

    Leider hast Du noch nicht geschrieben, ob das Ergebnis nun so ist wie Du es benötigst. Ich kann nur davon ausgehen - tue ich jetzt auch. Denn Ceos kam zum selben Ergebnis von R=248,G=100,B=72. So dass der Rechenweg hier nicht falsch war, wie Du es zwischenzeitlich angenommen hast.
    Geändert von Moppi (11.09.2018 um 07:18 Uhr)

  6. #6
    HaWe
    Gast
    hallo,
    der Grund für die verschiedenen Ergebnisse mit verschiedener Klammerung ist mir ja klar, ich hatte ja auch beide getestet - aber mit anderem Ergebnis als das, das du oben listest. Bisher hatte es nie gestimmt bei mir.

    Ich bin nun auch kein C++ Spezialist, aber ich vermute, dass
    uint8_t((color16 / 2048 )*8 )
    kein legaler C/C++ Code ist und nur zufällig (!) hier das gleiche liefert wie
    (uint8_t) ((color16 / 2048 )*8 )

    Wo ist denn dein kompletter Sketch Code, fertig zum Kompilieren? Ich will nicht wieder was falsch einfügen.

    Ich kopiere den kompletten Code noch mal und compiliere ihn neu, wenn ich ihn habe, vlt hat irgendwo anders was nicht gestimmt bei meinen Versuchen. Es gingen ja auch sehr viele verschiedene Versionen durcheinander.

    Melde mich dann, wenn ichs habe, habe grade keinen Arduino.

  7. #7
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    18.03.2018
    Beiträge
    2.669
    Zum Optimieren habe ich dann mal diesen Entwurf:
    Code:
    uint16_t ColorRGB216bit(uint16_t R, uint16_t G, uint16_t B) {
    
       return  (R>>3<<11) | (G>>2<<5) | (B>>3);
    }
    
    
    void Color16bit2colorRGB(uint16_t color16, uint16_t &R, uint16_t &G, uint16_t &B) {
    
       R = (uint8_t) (color16 >> 11) << 3;
       G = (uint8_t)((color16 & 2016) >> 3);
       B = (uint8_t) (color16 & 31) << 3;
       
       Serial.println("");
       Serial.println("Unterprogramm color16 zu RGB:");
       Serial.println( (String)"color16="+(String)color16);
       Serial.println( (String)"R="+(String)R);
       Serial.println( (String)"G="+(String)G);
       Serial.println( (String)"B="+(String)B); 
    }
    Ausgabe:
    Code:
    Hauptprogramm vor Aufruf:
    col16=0
    r=255
    g=102
    b=78
    
    Hauptprogramm nach rgb zu col16-Berechnung (rgb gelöscht):
    col16=64297
    r=0
    g=0
    b=0
    
    Unterprogramm color16 zu RGB:
    color16=64297
    R=248
    G=100
    B=72
    
    Hauptprogramm nach col16 zu rgb:
    col16=64297
    r=248
    g=100
    b=72
    Mann kann R>>3<<11 und G>>2<<5 übrigens nicht zusammenfassen zu R<<8 und G<<3, weil durch die jeweils erste Shift-Operation die untersten Bit gelöscht werden - was wichtig ist. Man müsste dann zusätzlich wieder ein UND anhängen, um die untersten Bits zu löschen, damit wird der Ausdruck nicht kürzer. Beim Verschieben nach Rechts werden die unteren Bits ins Nirvana verschoben und beim Verschieben nach Links werden Nullen eingefügt. Das sind Standardoperationen, wo das Überlaufbit immer gelöscht ist, bzw. nicht berücksichtigt wird. Für bestimmte Zwecke gibt es das auf Maschinenspracheebene auch noch mit Berücksichtigung des Überlaufbits - ist hier nicht wichtig.
    Geändert von Moppi (11.09.2018 um 08:49 Uhr)

Ähnliche Themen

  1. String nach Array umwandeln (?)
    Von slavezero im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 3
    Letzter Beitrag: 07.06.2012, 17:21
  2. Chips die nach Seriell umwandeln
    Von dundee12 im Forum Elektronik
    Antworten: 13
    Letzter Beitrag: 12.08.2010, 09:08
  3. word nach byte umwandeln
    Von magic33 im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 10
    Letzter Beitrag: 21.02.2007, 16:04
  4. C-Code in hex umwandeln
    Von elkokiller im Forum C - Programmierung (GCC u.a.)
    Antworten: 2
    Letzter Beitrag: 16.02.2006, 09:41
  5. PAL-Videosignal irgendwie nach seriell umwandeln?
    Von Trabukh im Forum Elektronik
    Antworten: 39
    Letzter Beitrag: 14.09.2005, 13:15

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

LiFePO4 Speicher Test