Forum: Compiler & IDEs Double Werte übergeben


von loki81 (Gast)


Lesenswert?

Hey,

Ich versuche gerade wieder einmal werte meines ADW an ein Display zu 
übergeben. So wqeit klappt auch alles nur die Berechnung de Spannung 
will nicht so ganz. Ich denke es liegt irgendwie an den Variablen Typen 
hoffe ich....

Ich habe folgendes:

int AD_WERT;
double ADCOUT;

ADCOUT = (5*AD_WERT/1023);
lcd_putd(ADCOUT);

Wenn ich "lcd_putd(234.567)" aufrufe geht es einwandfrei.
Wenn ich "ADCOUT = (5*515/1023)" aufrufe geht es nicht und ich bekomme 
nur die Anzeige 2.000V.

Hat jemand nen Tipp für mich?

loki

von Jemand anderes (Gast)


Lesenswert?

Ersetze mal
1
ADCOUT = (5*AD_WERT/1023);
durch
1
ADCOUT = (5.0*AD_WERT/1023.0);

Im ersten Falle wird eine Integermultiplikation und -Division 
durchgeführt, und erst das Ergebnis zu einem double konvertiert.
Das sieht in der anderen Version anders aus.

von Εrnst B. (ernst)


Lesenswert?

Und wenn du eh schon am Ändern bist, ersetze 1023.0 durch 1024.0, dann 
stimmt dein Ergebnis sogar noch.

von loki81 (Gast)


Lesenswert?

@all
Lieben Dank zusammen....

Hab das so geändert und siehe da es funst. Naja jedenfalls halb.

Double is immer signed oder? denn bis 565 alles super nur dann fängt 
meine Ausgabe wieder bei 0 an und zählt hoch.... Aber kommt Zeit kommt 
rat.

loki

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

> Double is immer signed oder?

Double ist ein floating-Point-Format.

von loki81 (Gast)


Lesenswert?

Hey ich noch mal....

Ich hab immer noch probleme und keinen Durchblick wo ich anfangen soll 
was nachzulesen.....

Also wie schon beschrieben fängt meine Anzeige immer wieder bei Null an 
wenn der ADC_wert über 556 geht. WARUM?

das Program sieht folgendermaßen aus:

in Main:
unsigned int adcrohw
double VOUT, RH

                        lcd_putn(adcrohw);

                        VOUT = ((5000.0*(adcrohw))/1023.0);
      RH = (0.03892*VOUT-41.98);

      lcd_putfl(RH);

in lcd_putfl:

void lcd_putfl( double f )
{
    char Buffers[10];
    unsigned int i;

  i= (unsigned int)(f*1000);
  sprintf( Buffers, "%d.%03d", i / 1000, i % 1000 );
  lcd_puts( Buffers );

}

MCU mega32
Der ADC läuft mit externen Vref = VCC
ADMUX = 0x00 und prescaler 32

Ich habe schon alle anderen datentypen versucht und keinen Plan woran es 
liegen könnte.....

von Karl H. (kbuchegg)


Lesenswert?

In lcd_putfl:

    i= (unsigned int)(f*1000);

i ist ein unsigned int. 16 Bit. Maximalwert also 65535.
Wie gross darf daher dein f maximal sein, damit diese
Berechnung nicht überläuft?

   sprintf( Buffers, "%d.%03d", i / 1000, i % 1000 );

%d ist das Formatkennzeichen für einen signed int.
Daher kriegst du dann das negative Vorzeichen.

von loki81 (Gast)


Lesenswert?

Leute ihr seid die größten!!!

@Karl Heinz
jepp genau so geht es. Danke

Meine C Zeiten sind schon was her hab mein altes Skript gestern raus 
geholt und das sagt uint =32Bit naja dem war dann wohl nicht so.

könnte ich denn uint_32 aus der inttypes benutzen? das müsste ja dann 
funsen denn mein f geht nur bis maximal 100.

naja vielen Dank noch mal

von Εrnst B. (ernst)


Lesenswert?

loki81 wrote:

>                         VOUT = ((5000.0*(adcrohw))/1023.0);

Das 1023.0 ist immernoch falsch, da gehört 1024.0 hin.
Ist zwar nur ein kleiner Fehler, aber ein komplett unnötiger.

Wenn du 5 € auf drei Leute verteilen sollst, gibst du doch auch nicht 
jedem 2,50 €.

von loki81 (Gast)


Lesenswert?

@Ernst

Klar hast recht mit dem 1024. Hatte ich erst so und dann dachte ich 
vielleicht ist das ja der Grund für den überlauf und hab 1023 draus 
gemacht. Wenn man man mal richtig überlegen würde teile ich ja durch 
1024. Da kann gar kein Überlauf draus entstehen.
Ja aber wenn man schon 3 Std nach so nem dummen Fehler sucht wird man 
zum Hirsch... Hab das bestimmt 20 mal von 23 auf 24 und wieder zurück 
geproggt...

Aber ich finde den Einsatz echt klasse (zweiDaumenHoch)

loki

von Johannes M. (johnny-m)


Lesenswert?

loki81 wrote:
> Meine C Zeiten sind schon was her hab mein altes Skript gestern raus
> geholt und das sagt uint =32Bit naja dem war dann wohl nicht so.
Das ist plattformabhängig! Auf einer 32-Bit-CPU ist int meist 
tatsächlich 32 Bit breit, aber bei einer 8-Bit-Plattform sieht das 
anders aus.

Der C-Standard schreibt für int lediglich eine Mindestbreite von 16 
Bit vor. Im Normalfall entspricht int der "natürlichen" Breite des 
Systems, was bei einem 8-Bit-µC aber nicht geht, wegen der vorgegebenen 
Mindestbreite. Deshalb macht es gerade bei µCs oft Sinn, die Typen aus 
der stdint.h zu benutzen, weil man da immer sofort sieht, wie lang der 
Datentyp tatsächlich ist.

Und man muss eben bei Berechnungen dran denken, dass die in int 
durchgeführt werden, wenn nichts anderes angegeben ist bzw. wenn keiner 
der beteiligten Operanden größer als int ist (OK, in diesem Falle 
nützt einem die stdint.h nichts).

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.