Forum: Mikrocontroller und Digitale Elektronik Das 0 Grad Problem


von René (Gast)


Lesenswert?

Hallo Alle

Ich habe ein kleines Problem. Ich messe mit meinem Mega 16 über ADC
eine Temperatur und lasse diese ohne Kommastellen auf meinem Display
ausgeben nachdem ich sie fließkommazahlmäßig ausgerechnet habe. Wenn
der Controller 17,6 Grad berechnet hat schreibt er 18 aufs Display, was
ja auch richtig ist. Rechnet er hingegen 17,4 aus schreibt er 17 hin,
ist ja auch ok. Nur wenn er 0,99 ausrechnet schreibt er 0 hin, und wenn
er -0,99 ausrechnet schreibt er auch 0 hin, und das ist falsch. Weiß
jemand warum er so etwas tut??

Ciao und Danke im Voraus

René

von Rufus T. Firefly (Gast)


Lesenswert?

Du rundest nicht, sondern schneidest Nachkommastellen ab.

Um daraus eine Rundung zu machen - addiere 0.5 vor dem Abschneiden der
Nachkommastellen.

von Sebastian (Gast)


Lesenswert?

> Du rundest nicht, sondern schneidest Nachkommastellen ab.

Offenbar nicht:

> Wenn der Controller 17,6 Grad berechnet hat schreibt er 18 aufs
> Display

von René (Gast)


Lesenswert?

Genau, überhalb und unterhalb von 0 funktioniert das Runden, nur halt um
0 nicht...

von dave (Gast)


Lesenswert?

Haste vielleicht nen Stück Code?

Ich könnte mir vorstellen, dass es irgendwie (wenn es so gemacht wurde)
an dem Übergang zwischen 0 und 255 ist.

dave

von René (Gast)


Angehängte Dateien:

Lesenswert?

@ dave

habe dir eine Mail geschrieben, aber hier im Anhang ist es halt auch
noch mal....

Danke René

von Marcus Maul (Gast)


Lesenswert?

Hallo René,

erstmal eine kleine Anmerkung, da ein Float relativ langsam in der
Berechnung ist, versuche die Zahl 0,134 durch 6/19 zu ersetzen, der
Fehler liegt bei 2% und das ist wohl im Bereich des Fehlers des ADC.

Mir ist leider im Moment nicht klar von welchen Typ temp1 ist.
Zudem wandelt itoa einen Int um und keinen Float. Somit wird der Float
vor dem Komma abgeschnitten. Verwende lieber:

float temp1=((0.314*v3)-162.3);  //hier berechne ich die Temperatur
"temp1" wobei v3 der 10 bit Samplewert vom ADC ist

char temp1str[6];
sprintf(temp1str,"%ddd.d", temp1);

Gruß Marcus

von Zotteljedi (Gast)


Lesenswert?

> erstmal eine kleine Anmerkung, da ein Float relativ langsam in der
> Berechnung ist, versuche die Zahl 0,134 durch 6/19 zu ersetzen, der
> Fehler liegt bei 2% und das ist wohl im Bereich des Fehlers des ADC.

Aber vor Integer-Division aufpassen, (6/19) ist 0. Dann ist der Fehler
'ne Spur größer als 2%.

von Marcus Maul (Gast)


Lesenswert?

Hallo Zotteljedi,

sollte natrülich heißen:

float temp1=((v3*9/16)-162.3);

Da hierbei normalerweise zuerst 9*v3 gerechnet und dann erst durch 16
geteilt wird geht das schon okay. Natürlich hast Du recht, wenn ich
diesen Wert einem signed int zuweise passiert wieder das obig.

Gruß Marcus

von Peter D. (peda)


Lesenswert?

"Nur wenn er 0,99 ausrechnet schreibt er 0 hin, und wenn
er -0,99 ausrechnet schreibt er auch 0 hin, und das ist falsch. Weiß
jemand warum er so etwas tut??"

Weil es eben nicht falsch ist !!!

Du rundest ja nicht, sondern wandelst nur von float nach int um und das
bedeutet, daß der Rest abgeschnitten wird.
Das Ergebnis ist dann immer die betragsmäßig größte nicht größere
Ganzzahl.

Wenn Du runden willst, kannst Du das z.B. so machen:

int round( float val )
{
  return val + ((val < 0) ? -0.5 : 0.5);
}


Peter

von Zotteljedi (Gast)


Lesenswert?

Um Sebastian zu zitieren:

>> Du rundest nicht, sondern schneidest Nachkommastellen ab.
>
> Offenbar nicht:
>
>> Wenn der Controller 17,6 Grad berechnet hat schreibt er 18 aufs
>> Display

von Daniel Jelkmann (Gast)


Lesenswert?

Hi,

>> Du rundest nicht, sondern schneidest Nachkommastellen ab.
>
> Offenbar nicht:
>
>> Wenn der Controller 17,6 Grad berechnet hat schreibt er 18 aufs
>> Display

Kann ich mir gerade mal garnicht vorstellen.
itoa() verlangt ja bekanntlich einen int, daher muss temp1 wohl vom Typ
int sein.
Meinetwegen wird nun der Wert 17,6 berechnet, aber da die Variable vom
Typ int ist, schneidet der Compiler hier die Nachkommastellen ab.
Meiner Meinung nach kann damit bei einer 17,6 keine 18 auf dem Display
erscheinen.
Und wenn doch, dann möge mir das mal bitte einer erklären.
Ich würde daher auch sagen, addier eine -+0.5 drauf, dann wird der Wert
gerundet, so wie Peter das schon geschrieben hat.

Bye
  Daniel Jelkmann

von Zotteljedi (Gast)


Lesenswert?

@Daniel: Du willst also mit anderen Worten sagen, daß René lügt?

Fände ich etwas sonderbar, wenn er hier denn Hilfe sucht. Er hat einen
Versuch gemacht (17,6 auszugeben), er hat eine Beobachtung gemacht (auf
dem Display steht 18), und eine Erklärung vom Format "kann gar nicht
sein" wäre etwas unwissenschaftlich. Gerade bei etwas, das
reproduzierbar sein müsste (wobei wir davon nichts wissen), weil nur
von digitallogischer Verarbeitung abhängig, scheidet da eine
Interpretation, die mit "Meiner Meinung nach" anfängt, aus.

Vielleicht meldet sich René ja nochmal, und gibt uns Typ von temp1 und
Inhalt von v3 an (der erschliesst sich mir mangels Arbeit mit dem ADC
noch nicht so ganz, muß man nicht irgendwie ein Bezugssystem angeben,
damit eine Einteilung Sinn macht?).

von Daniel Jelkmann (Gast)


Lesenswert?

Hi,

nein, ich möchte nicht behaupten, dass René lügt.
Ich kann mir nur nicht vorstellen, dass es so ist, wie er es
beschreibt. Vielleicht verpeile ich das ganze ja auch, deswegen habe
ich ja geschrieben, dass man es mir in diesem Fall bitte erklären möge.
Vielleicht hat René sich ja auch irgendwo vertan. Zum Lügen gehört
meiner Ansicht nach, dass man bewusst nicht die Wahrheit sagt, und das
ist das letzte, was ich hier jemandem unterstellen möchte. Wenn der
obige Text von mir so verstanden wird, bitte ich um Entschuldigung.

Bye
 Daniel Jelkmann

von René (Gast)


Lesenswert?

Hallo Alle

Wie auch immer, ich habe jetzt die Rundungsfunktion von Peter verbaut
und damit klappt es nun.

Vielen Dank für eure Hilfe

René

von Zotteljedi (Gast)


Lesenswert?

OK, dann war es ein Mißverständnis; aber es hat sich ja nun erledigt,
wie's scheint. Schade, dann werden wir unsere Neugier nie befriedigen
können :-/

von Philipp Sªsse (Gast)


Lesenswert?

> versuche die Zahl 0,134 durch 6/19 zu ersetzen, der
> Fehler liegt bei 2% und das ist wohl im Bereich des
> Fehlers des ADC.

(Nehmen wir die 0,134 als Tippfehler und rechnen mit 0,314.)

1. Der Fehler liegt bei einem halben Prozent, wenn ich mich sehr irre.

2. Selbst 0,5 % Fehler wären sehr viel für einen AD-Wandler; das wäre
ja nicht einmal 8 Bit Auflösung

3. Warum um alles in der Welt sollte man 6/19 nehmen, obwohl 5/16 einen
kleineren Fehler liefert und gleichzeitig noch einmal erheblich
einfacher zu berechnen ist (Bitshift statt Division).

Nur einmal so als Anmerkung zur Anmerkung.

von Marcus Maul (Gast)


Lesenswert?

Hallo Philipp,

eins gleich vorweg, eine Division ist binär IMMER ein bitshift nach
links!
Nun nochmal zur 0,134 oder 0,314.
Diese Zahl läßt sich binär nicht so genau darstellen, da 0b0,1 = 0,5
ist. Mit anderen Worten eine Zahl läßt sich nur so darstellen:
c*2^2+b*2^1+a*2^0+z*2^-1+y*2^-2+x*2^-2
Somit muß der compiler 0,134 / 0,314 durch 1/2, 1/4, 1/16 usw.
darstellen. Dabei entsteht in jedem Fall ein kleiner Fehler und zudem
braucht ein 8bit µC dafür relativ lange, denn diese Darstellung sind
IMHO bei einem float 16bit.
Bei dem Wert 6/19 hab ich mich ja echt verhauen. Sorry!

0,134 häßt sich aber sehr gut durch 32/239 darstellen:
32/239 = 0,1338912; delta x = -0,000109; Abweichung = 0,0812%.
Die ist aber wirklich schon im Rahmen des erlaubten.

Zumal die maximale Abweichung (worst case) 0,134 * 1024 bei 0,1116
liegt, also nur 0,1°C ausmachen würde. Meines wissens liegt dieser
Fehler aber genau in dem Bereich des Fehlers des Messfühlers und somit
würde sich schlimmstenfalls eine Abweichung von 0,2°C ergeben, falls
man nur diesen Rechenfehler und den Fehler des Temperaturfühlers
berücksichtigt, die Nichtlinearität und den Umwandlungsfehler des
AD-Wandlers lasse ich dabei außen vor, genauso wie die Nichtlinearität
der analogen Beschaltung. Der Fehler wird dann noch größer.

So long

Marcus

von Zotteljedi (Gast)


Lesenswert?

> eins gleich vorweg, eine Division ist binär IMMER ein bitshift nach
> links!

8 << 1 == 16
50 << 1 == 100

Eigenwillige Definition von Division. :-)

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.