double Ausgabe

Gast #5993765
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?
#5993879
Dieses Gehampel mit der Float/Double-Ausgabe hab ich umgangen indem ich 
die Funktion:
1
...
2
#include <stdlib.h>
3
...
4
dtostrf(float_variable,
5
        zahl_aller_stellen_incl_komma,
6
        zahl_der_nachkommastellen,
7
        stringvariable);
8
...
benutze. Vielleicht hilft das dir auch.
Gast #5993905
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?
Gast #5994208
@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.
#5994215
neuer_benutzer55 schrieb:
> CFLAGS += -Wl,-u,vfprintf
> und:
> LDFLAGS += -lprintf_flt -lm

neuer_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?
Gast #5994225
@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.
#5994315
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.
Gast #5994375
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.
#5994396
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.
#5994467
Auf einem 8-Bit uC hatte ich es mal sinngemäß so gemacht (hier als 
PC-Version zum ausprobieren)
1
#include <stdint.h>
2
#include <stdio.h>
3
#include <stdlib.h>
4

5
int
6
main (int argc, char *argv[])
7
{
8
   char    *bp, buf[42];
9
   int      bc, len;
10
   int32_t  temp;
11

12
   if (argc != 2) {
13
      printf ("usage: %s DS18B20-Datenwort\n", argv[0]);
14
      exit (EXIT_FAILURE);
15
   }
16
   temp = strtol (argv[1], NULL, 0);
17

18

19
   if (temp & 2048) {
20
      temp |= 0xfffff000UL;
21
   }
22
   len = snprintf (buf, sizeof buf, "%+06d", temp * 625);
23
   bp = buf;
24
   for (bc = 0; bc < 9 - len; bc++) {
25
      putchar (' ');
26
   }
27
   for (bc = 0; bc < len - 4; bc++) {
28
      putchar (*bp++);
29
   }
30
   putchar ('.');
31
   for (bc = 0; bc < 4; bc++) {
32
      putchar (*bp++);
33
   }
34
   putchar ('\r');
35
   putchar ('\n');
36
   return 0;
37
}
Gast #5994528
Wenn es dir nur um die Nachkommastellen, die durch die Division mit 16 
entstehen, geht, kannst du das auch ohne float/double erreichen:
1
    char buf[12];
2
    unsigned t = abs(temp);
3
    sprintf(buf, "%u.%03u", t/16, t%16 * 1000 / 16);
4
    if (temp < 0)
5
        USART_transmit('-');
6
    USART_transmit_string(buf);

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 7 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.