Forum: Compiler & IDEs float auf display anzeigen


von Patrick H. (absynthe666)


Lesenswert?

hallo.
ich habe da ein problem. ich möchte eine double variable auf einem lcd 
display anzeigen lassen. das ganze wurde für einen atmega32 geschrieben.
die funktion funktioniert soweit, aber da sind ungenauigkeiten drin.
zB. will ich die zahl 2.000001 anzeigen lassen. da zeigt er mir 2.000000 
an.

ich hoffe, dass ihr mir helfen könnt. ich hab keine idee woran es 
scheitert.

edit: der übergabewert cpoint besagt, wieviel stellen nach dem komma ich 
angezeigt haben möchte. maximal sind in dieser funktion 6 
nachkommastellen geplant.
1
void lcd_put_float(double dnumber, char cpoint) 
2
{
3
  char cz=0; //Schleifenzähler
4
  char cbuffer[7]={0,0,0,0,0,0,0};
5
  double dnach=0;
6
  long lz=0; //Zwischenspeicher
7
  if(dnumber<0)  //Wenn die Zahl negativ ist, schreibe ein - und wandel die zahl ins positive
8
  {
9
    lcd_putc('-');    
10
    dnumber=dnumber*(-1);
11
  }
12
  lz=dnumber; //Berechnung vorkomma
13
  lcd_put_number(lz), lcd_putc('.'); //Anzeige Vorkomma
14
  dnach=lz;
15
  dnumber=dnumber-dnach;
16
  lz=dnumber*pow(10,cpoint);
17
  cz=cpoint-1;
18
  while(cz<=5)
19
  {
20
    cbuffer[cz]=lz%10;
21
    lz=lz/10;
22
    --cz;
23
  }
24
  for(cz=0;cz!=cpoint;++cz)
25
  {
26
    lcd_putc(cbuffer[cz]+0x30);
27
  }
28
}

: Bearbeitet durch User
von Klaus (Gast)


Lesenswert?

Ich wühle mich nun nicht durch den Code, denn da sind mir ein wenig zu 
wenig Kommentare enthalten und das Rad wird vermutlich auch nicht mehr 
wesentlich runder.

Du hast aus meiner Sicht zwei Probleme:

- Die Ausgabe von double: Das geht mit sprintf bzw. einer der "dtoa" 
implementierungen (fast) ganz schmerzlos. Nur fast schmerzlos, weil 
die Implementierungen auf den AVR ziemlich umfangreich sind und daher 
viel Platz im Flash-Speicher wegnehmen. Aber machen kann man es so.
(Falls Du aus "akademischen" Gründen wirklich darauf Wert legst das 
selbst zu implementieren ist das eine andere Frage.

- Die Abweichung der Ausgabe von erwarteten Wert: Dafür enthält der 
Beitrag zu wenig Information. Falls Du wirklich 2.000001 ausgeben willst 
und 2.000000 erhälst, so stellt sich die Frage ob eine Double die Zahl 
2.000001 überhaupt so speichern kann. Dazu gibt es genügend Seiten im 
Netz. Falls das so gespeichert werden kann (was ich mal ad-hoc mal nicht 
als gegeben nehme), dann trace einfach durch Deinen Code und guck was 
schief geht. Falls nicht, dann musst Du damit leben.

von Heiko L. (drcaveman)


Lesenswert?

Warum rufst du nach
1
lz=dnumber*pow(10,cpoint);
 nicht einfach noch einmal
1
lcd_put_number(lz)
 auf?

von Dirk B. (dirkb2)


Lesenswert?

Heiko L. schrieb:
> Warum rufst du nach
1
lz=dnumber*pow(10,cpoint);
 nicht einfach noch
> einmal
1
lcd_put_number(lz)
 auf?

Wel da dann nur ein 1 oder 0 ausgegeben wird und keine 00001 oder 00000

es ist schon ein Unterschied zwischen 2.1 oder 2.00001

von Falk B. (falk)


Lesenswert?

@ Patrick Höfler (absynthe666)

>ich habe da ein problem. ich möchte eine double variable auf einem lcd
>display anzeigen lassen. das ganze wurde für einen atmega32 geschrieben.

Auf dem avr gcc sind double = float = einfache Genauigkeit mit 5-6 
Dezimalstellen. Somit gibt es die 2.000001 einfach nicht, so genau kann 
nicht aufgelöst werden.

>void lcd_put_float(double dnumber, char cpoint)

Warum neu erfinden? Sowas gibt es schon, sei es mit sprintf() oder 
ftoa().

von Heiko L. (drcaveman)


Lesenswert?

Dirk B. schrieb:

> es ist schon ein Unterschied zwischen 2.1 oder 2.00001

Kommt hin.

Die Erklärung hat Falk ja jetzt gegeben.

von Timmo H. (masterfx)


Lesenswert?

Patrick Höfler schrieb:
> das ganze wurde für einen atmega32 geschrieben.
Bei 32 KB Flash würde ich auch eher zu sprintf raten. Die lib nimmt mit 
float glaub ich so 1,5 KB an Flash. Dafür trägt es ungemein zur 
Leserlichkeit/Wartbarkeit deines Programms bei, und wenn man das dann 
auch öfter nutzt sind die 1,5 KB Flash gut investiert. Deine putint, 
puthex funktionen für das LCD kannst du dann auch komplett weg lassen.
Via vsprintf kannst du dir dann auch eine eigene lcd_printf(xpos,ypos, 
*format, ...)-Funktion schreiben.
Nur auf kleinen Tinys oder so würde ich auf printf verzichten, da der 
Flash-Speicher dort oftmals schon knapp bemessen ist.

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

@ Timmo H. (masterfx)

>Nur auf kleinen Tinys oder so würde ich auf printf verzichten, da der
>Flash-Speicher dort oftmals schon knapp bemessen ist.

Dort, und auch auf größeren uCs, nimmt man meist besser 
Festkommaarithmetik.

von Timmo H. (masterfx)


Lesenswert?

Falk Brunner schrieb:
> @ Timmo H. (masterfx)
>
>>Nur auf kleinen Tinys oder so würde ich auf printf verzichten, da der
>>Flash-Speicher dort oftmals schon knapp bemessen ist.
>
> Dort, und auch auf größeren uCs, nimmt man meist besser
> Festkommaarithmetik.
Jeder wie er es mag. Aber ich nehme, wenn ich genug Platz habe, lieber 
die Standard Librarires. Wenn ich schnell rechnen muss (imu etc.) ist 
das was anderes, aber für formatierte Ausgaben via uart oder LCD tue ich 
mir diese Klimmzüge nicht mehr an. Da schreibt man je nach Komplexität 
meist mehr Funktionen als nötig wo es mit printf etc. doch viel 
einfacher, verständlicher und portabler ist.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.