Hex Farbwert 0xFF0000 von String zurück zu long konvertieren

Hallo zusammen

Mein Problem ist das Konvertieren eines Farbwertes in Hex z.B. 0xFF00FF, welcher via Serial.write von Processing ans Arduino geschickt wird und dort als chars ankommt, zu einem long zurück.

Ich habe zwar schon ein Paar Artikel gefunden, funktioniert hats aber bis jetzt noch nicht :frowning:

ich habe es z.B. so probiert: long hexColor = strtol(color.c_str(),NULL,16);

Kann mir da jemand einen guten Rat geben?

Vielen Dank
Mischa

Und wieso geht das nicht? Was ist der Fehler?
Korrekter wäre vielleicht strtoul() für unsigned long. Da das aber nur ein 24 Bit Wert ist sollte beides gehen.

c_str() bedeutet dass colors ein String Objekt wäre. Das ist etwas anderes als "als chars ankommt". Aber mit c_str() kommt man auch an der interne char Array des Objekts.

EDIT:
Dein Fehler könnte vielleicht Serial.write() sein. Zumindest auf dem Arduino schickt write() Binärdaten. print() sendet ASCII. Weiß nicht ob das auch in Processing unterschieden wird.

void setup() {
  Serial.begin(115200);
  Serial.print(F("strtol(\"0x12345678\", NULL, 0)  ergibt 0x"));
  Serial.println(strtol("0x12345678", NULL, 0), 16);
  Serial.print(F("strtol(\"0x12345678\", NULL, 16) ergibt 0x"));
  Serial.println(strtol("0x12345678", NULL, 16), 16);
  Serial.print(F("strtol(\"12345678\", NULL, 16)   ergibt 0x"));
  Serial.println(strtol("12345678", NULL, 16), 16);
}
void loop() {}
strtol("0x12345678", NULL, 0)  ergibt 0x12345678
strtol("0x12345678", NULL, 16) ergibt 0x12345678
strtol("12345678", NULL, 16)   ergibt 0x12345678

Vielen Dank für die raschen Antworten!

Das Rezept von Whandall kommt dem Ganzen schon ziemlich nahe, leider verstehe ich das mit dem F( nicht ganz.

mein Code sieht so aus:

if(Serial.available() > 0){
char c = Serial.read();

if( c == ',' ){
long hexColor = strtol(color.c_str(),NULL,16);
//leds[pixelCounter] = hexColor;
Serial.print(hexColor + "\n");
color = "";
pixelCounter ++;
}else{
color += c;
}
}

Wenn ich println(strtol(color.c_str(),NULL,16), 16); ergibt mir das FF0000
aber wie kriege ich jetzt das 0x noch hin? und das letzte ,16 kann ich ja da:
long hexColor = strtol(color.c_str(),NULL,16); auch nicht mehr anhängen :frowning:

Vielen Dank
Mischa

Willst du mehrere Werte per Komma getrennt empfangen? Das kann man so machen:

const int MAX_VALUES = 5;
unsigned long leds[MAX_VALUES];

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  int valuesRead = readSerial(Serial);
  if (valuesRead > 0)
  {
    for (int i = 0; i < valuesRead && i < MAX_VALUES; i++)
    {
      Serial.print(F("0x"));  Serial.println(leds[i], HEX);
    }
    Serial.println(F("---"));
  }
}

int readSerial(Stream& stream)
{
  static byte charIndex;    //Index für Zeichen im String
  static byte valueIndex;   //Index im Zahlen-Array
  static char buffer[11];     //Platz für "0x" + 8 Hex Ziffern + Terminator

  while (stream.available())
  {
    char c = stream.read();
    
    if (c == '\n')     //Ende
    {
      buffer[charIndex] = '\0';        //String terminieren
      parseSerial(buffer, valueIndex); //String konvertieren und abspeichern
      valueIndex++;   //Index erhöhen
      charIndex = 0;  //Zeichen-Index zurücksetzen
      
      int temp = valueIndex;
      valueIndex = 0;
      return temp;    //Anzahl der eingelesen Zahlen zurückgeben
    }
    else if (c > 32)   //wenn kein Steuerzeichen
    {
      if (c == ',')    //wenn Komma
      {
        buffer[charIndex] = '\0';
        parseSerial(buffer, valueIndex);
        valueIndex++;
        charIndex = 0;
      }
      else if (charIndex < sizeof(buffer) - 1)   //wenn noch Platz im Array ist
      {
        buffer[charIndex++] = c;    //Zeichen abspeichern und Index inkrementieren
      }
    }
  }

  return - 1;   //melden das Ende noch nicht erreicht
}

void parseSerial(char* str, byte valueIndex)
{
  if (valueIndex < MAX_VALUES)
    leds[valueIndex] = strtoul(str, NULL, 16);
}

Das liest hier bis zu 5 Werte ein. Aber mehr geht auch wenn man MAX_VALUES größer macht

Wichtig ist dass du am Ende ein Linefeed/Newline sendest! Sonst geht es nicht. Einzelne Werte werden mit einem Komma getrennt und ein LF meldet dass die Übertragung zu Ende ist.

Nur grob gesteset

F() bedeutet dass der String im Flash Speicher steht und kein RAM belegt

@Serenifly
Vielen Dank! Es funktioniert jetzt.
Gruss
Mischa