Hallo,
bei der Ausgabe der Temperatur eines DS18b20 stehe ich vor der
Problematik die Nachkommastellen auszugeben, laut diesem Beitrag:
https://stackoverflow.com/questions/37815771/snprintf-not-working-as-expected-with-avr-gcc
Fehlten mir: -Wl,-u,vfprintf -lprintf_flt -lm
diese habe ich hier hinzugefügt:
CFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm
(Die Makefile kommt hier aus dem Forum, minimal verändert)
Hier der Code zur Ausgabe, es wird ein "?" gesendet. USART_end() sendet
'\r\n'.
char zeichen[15];
double myFloat2 = 2.2345;
sprintf(zeichen, "%.4f", myFloat2);
for (char *p = zeichen; *p; p++) {
USART_transmit(*p);
}
USART_end();
Der rest vom Code funktioniert, ein USART_transmit('a'); sendet dieses
ohne Probleme.
Sind die "Linker" Optionen richtig in den CFLAGS?
neuer_benutzer55 schrieb:> bei der Ausgabe der Temperatur eines DS18b20 stehe ich vor der> Problematik die Nachkommastellen auszugeben
Mit Float (single Precision) Datenformat hast du 24 Bit für den
Zahlenwert. Ein DS18B20 liefert dir maximal 12 Bit Auflösung bei einer
Genauigkeit von 0.5K, i.e. 8 1/2 Bit.
Was versprichst du dir dabei von der Verwendung von Double?
@Dirkb
CFLAGS += -Wl,-u,vfprintf
und:
LDFLAGS += -lprintf_flt -lm
so funktioniert es leider auch nicht :(
makefile: https://bpaste.net/show/WQn0
@Wolfgang
Bisher habe ich diesen Code für die Ausgabe verwendet:
1
int temp;
2
int temp2;
3
temp2 = temp / 16;
4
char buf[10];
5
itoa(temp2, buf, 10);
6
7
for (char *p = buf; *p; p++) {
8
USART_transmit(*p);
9
}
10
USART_end();
Warum durch 16 teilen? Weil dieses Library:
https://github.com/Jacajack/avr-ds18b20/wiki
den Wert mit 16 multipliziert, für eine einfachere Ausgabe weil die
Werte im Register des Sensors anders liegen sonst.
Durch die Integer Divsion kann natürlich auch nur ein Integer Wert
angezeigt werden. Darum bin ich auf double / float gekommen.
Zweiter Versuch mit double:
1
volatile double db1;
2
db1 = temp / 16;
3
char buf[20];
4
dtostrf(db1, 4, 3, buf);
5
for (char *p = buf; *p; p++) {
6
USART_transmit(*p);
7
}
8
USART_end();
Das liefert jetzt 20.000, 21.000 aber nie Werte dazwischen.
Wenn ihr da ein besserers Library habt immer her damit.
neuer_benutzer55 schrieb:> CFLAGS += -Wl,-u,vfprintf> und:> LDFLAGS += -lprintf_flt -lmneuer_benutzer55 schrieb:> CFLAGS += -Wl,-u,vfprintf> und:> LDFLAGS += -lprintf_flt -lm>> so funktioniert es leider auch nicht :(> makefile: https://bpaste.net/show/WQn0
Zeile 121 auskommentieren hätte gereicht.
Gefällt dir der Zahlenwert von sprintf nicht, oder kommt nur wirres Zeug
raus?
@Dirkb: Ahja, stimmt. 121 ist der passende Ort.
Die Zahlen können von meinem Bluetooth Terminal interpretiert werden und
passen auch, aber es wundert mich das ich bisher nur 20.000 oder 21.000
gesehen habe, in den Beispielen im Datenblatt gibt es auch; +25.0625.
Also 4 Nachkommastellen Präzision, da müsste ja irgendwann mal ein
anderer Wert gekommen sein.
neuer_benutzer55 schrieb:> db1 = temp / 16;
Wenn temp ein Integer ist, dann ist das Ergebnis der Division auch ein
Integer. Simple Lösung:
db1 = temp / 16.0
neuer_benutzer55 schrieb:> Darum bin ich auf double / float gekommen.
Double und Float haben völlig verschiedene Auflösung.
Nochmal: Warum Double und nicht Single/Float?
Wolfgang schrieb:> Soviel zum Thema Portierbarkeit von C ;-(>> Nichtmal auf die Auflösung der Zahlenformate für rationale Zahlen kann> man sich verlassen.
Der C-Standard gibt nur einen Mindeswertebereich für float und double
vor.
Und der ist identisch.
Also ist es Standardkonform, wenn float und double denselben
Wertebereich haben.
Dirk B. schrieb:> Also ist es Standardkonform, wenn float und double denselben> Wertebereich haben.
Trotzdem ist es Käse, wenn double ≠ IEEE double precision ist, weil
man dann keine portierbare Möglichkeit hat, gesichert mit /IEEE double
precision/ zu rechnen.
Wolfgang schrieb:> Trotzdem ist es Käse, wenn double ≠ IEEE double precision ist, weil> man dann keine portierbare Möglichkeit hat, gesichert mit /IEEE double> precision/ zu rechnen.
IEEE Unterstützung wird auch erst seit C11 gefordert.
Viele Systeme unterstützten das auch vorher.
Nur sollte man bei C nicht von dem Verhalten des eigenen System auf die
Allgemeinheit schließen.