Konvertierung in HEX

hallo,

kann mir bitte einmal jemand helfen bei sprintf?

DeviceAddress tempDeviceAddress;
sensors.getAddress(tempDeviceAddress, index)
sprintf(FullPage, "%s?id=%lu&adr=%s&val=%02X%02X%02X%02X%02X%02X%02X%02X&num=%i&cnt=%d", PAGE, mi, tempDeviceAddress[0], tempDeviceAddress[1], tempDeviceAddress[2], tempDeviceAddress[3], tempDeviceAddress[4], tempDeviceAddress[5], tempDeviceAddress[6], tempDeviceAddress[7], dsTemp, index, num);

ich lese die adresse eines ds18b20 aus, und will die als wert in einer url mitgeben. allerdings kommen da nicht die gleichen werte raus wie z.b. mit einem der vielen 1-wire-scanner wenn diese den wert direkt per serial und hex ausgeben.

gibt es eine "schönere" alternative zu dem sprintf um eine url entsprechend zusammenzupappen?

danke & grüße fly

Hmm... Warum zeigst du nicht die Quelldaten, die gewünschte Ausgabe und die fehlerhafte Ausgabe? So ist das nicht testbar.

Ich vermute mal, daß das byte/char(?) Array tempDeviceAddress direkt mit %16X ausgegeben werden kann. Ob dann die Reihenfolge stimmt, ist was anderes. Aber solange immer die gleiche Formatierung benutzt wird, ist die Reihenfolge ja egal.

Die Beschreibung von sprintf habe ich nicht gefunden, wo gibt's die denn für Arduino?

Falsch vermutet.

Das Format %16X erzeugt einen 16 bit Wert in einem 16 Char breiten Feld, in Hex, rechtsbündig, ohne führende Nullen, mit Großbuchstaben.

Dokumentation der AVR Implementation vfprintf.

combie:
Warum zeigst du nicht die Quelldaten, die gewünschte Ausgabe und die fehlerhafte Ausgabe?
So ist das nicht testbar.

a) weil ich dachte ich wäre bestimmt nicht der einzige auf der welt der das schon mal machen wollte
b) weiß ich nicht genau wie die adresse des 18b20 im roh-format aussieht, da jedes serial.print ja auch schon evtl. was verändert
c) ich davon ausging, dass diejenigen, die hier antworten, wissen wie eine ds18b20 adresse in hex hinterher aussieht.
d) warum ellenlangen-code schicken, wenn die 3 zeilen die frage aufwerfen? der rest hat mit dem eigentlichen problem nix zu tun.

ich habe eine funktion aus irgendeinem schnipsel:

void printAddress(DeviceAddress deviceAddress) {
  Serial.print(F("{0x"));
  for (uint8_t i = 0; i < 8; i++) {
    if (deviceAddress[i] < 16) Serial.print(F("0"));
    Serial.print(deviceAddress[i], HEX);
    if (i < 7) Serial.print(F(", 0x"));
  }
  Serial.println(F("}"));
}

die gibt die 16-stellige adresse in hex aus, aber, sie gibt sie eben aus und nicht in einer variablen zurück, das wäre die zweite variante die ich gern hätte. aber ich weiß nicht was in serial.print HEX passiert.

e) weil ich das vergessen habe:
Richtig: 28 8E 90 1E 00 00 80 F1
Falsch: CC 8E 1E 00 00 80 34 8E 2 (mit o.g. sprintf)
[die leerzeichen sind nur der lesbarkeit wegen drin]

vielen dank schonmal

Wenn die sprintf Ausgabe so wenig mit dem Original zu tun hat, dann würde ich diese Funktion nicht mehr verwenden. Aber vielleicht bringst Du ja die Speicherverwaltung durcheinander, so daß da wild überschrieben wird? Strings sollen auf einem Arduino ja nicht ganz unproblematisch sein.

Danke für das vprintf Link :-)

vielleicht vergaß ich zu sagen, das es mir nur um den adress-teil geht, alles andere funzt wie gewollt.
nur die adresse des ds18b20 wird da falsch reingefummelt.

Ich habe schon festgestellt, daß der Compiler ziemlich aggressiv optimiert, wenn globale Variablen nicht als "volatile" gekennzeichnet sind. Vielleicht hilft das auch hier?

Meine erste Vermutung wäre gewesen, dass eine Umwandlung der Daten passiert.
Wird beim Auslesen der Werte z.B. via Serial, char verwendet, so wird bei der Ausgabe in Hex nicht die Zahl darin, sondern der ASCII Wert verwendet.
Aber, da Dein Ergebnis einen Wert mehr aufweist, scheint dort ein grundsätzliches Problem zu herrschen!
(8 <> 9 Hex-Werten, oder hast Du Dich vertan?)

Und da Du keinen Datentyp angibst, auch nur geraten…

Um mir Hex-Werte auszugeben verwende ich folgende Funktion:

void PrintHex(uint8_t data) // prints 8-bit data in hex with leading zeroes
{
  if (data < 0x10)         
    BT.print("0");
  String str = String(data,HEX);
  str.toUpperCase();
  BT.print(str);
}

Und das Ganze andersherum:

byte GetByteFromHexString(String hexValue)
{
  return getVal(hexValue[1]) + (getVal(hexValue[0]) << 4);
}

byte getVal(char c)
{
   if(c >= '0' && c <= '9')
     return (byte)(c - '0');
   else
     return (byte)(c-'A'+10);
}

Ach.... Sprintf ist unschuldig! Die Speicherverwaltung auch! Ebenso die Compileroptimierungen! Zumindest kann ich dieses alles nicht sehen.

Tipp: Erst den Schuldigen benennen, wenn dessen Schuld erwiesen ist.

Nachweis: Die ersten 3 Parameter werden hier verbraucht: "%s?id=%lu&adr=%s" Die ersten 3 Parameter sind: "PAGE, mi, tempDeviceAddress[0]" Ein deutliches, klares, Problem mit den Parametern. Und darum unterscheidet sich auch der Wunsch, von der Realität.

Eigentlich sollte der Compiler schon ein Warning werfen, weil tempDeviceAddress[0] als %s formatiert werden soll.

Aktiviere mal die Ausgabe aller Warnings.

combie: Eigentlich sollte der Compiler schon ein Warning werfen, weil tempDeviceAddress[0] als %s formatiert werden soll.

Dachte eigentlich, dass das erst zur Laufzeit auffällt, aber es kommt bei sowas tatsächlich eine Warnung.

z.B.:

sketch_jun07a.ino: In function 'void loop()':
sketch_jun07a.ino:12:25: warning: format '%s' expects argument of type 'char*', but argument 3 has type 'int' [-Wformat=]

combie hatte recht, respekt. da ich zuerst versucht habe die adresse als string zu basteln, war %s ja auch richtig, aber als das dann nicht zum gewünschten ergebniss führte, musste der "lange weg" her und alle werte da rein, und dabei hab ich adr mit val verwechselt ... damn ...

merci everybody!

Danke für die Blumen. Und schön, dass es jetzt tut.

so sieht der server dann den aufruf (apache access.log)

01.php?id=2128102&adr=288E901E000080F1&val=26.1250&num=1&cnt=3

id = damit alle aufrufe in einer runde einen gleichen wert haben und man erkennen kann dass sie zusammengehören.
adr = die adresse des ds18b20
val = die temperatur
num = der index des sensors auf dem bus
cnt = die anzahl gefundener sensoren

und hier ncoch der missglückte versuch die adresse als string vorab aufzubereiten … :o

char dsHexAddress[17];
void printAddress(DeviceAddress deviceAddress)
{
  for (uint8_t i = 0; i < 8; i++)
  {
    if (deviceAddress[i] < 16)
      dsHexAddress[i * 2] = 0;
    dsHexAddress[i * 2] = deviceAddress[i];
  }
}