www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Das 0 Grad Problem


Autor: René (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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é

Autor: Rufus T. Firefly (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du rundest nicht, sondern schneidest Nachkommastellen ab.

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

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Du rundest nicht, sondern schneidest Nachkommastellen ab.

Offenbar nicht:

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

Autor: René (Gast)
Datum:

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

Autor: dave (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: René (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
@ dave

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

Danke René

Autor: Marcus Maul (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Zotteljedi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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%.

Autor: Marcus Maul (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Zotteljedi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Daniel Jelkmann (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Zotteljedi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?).

Autor: Daniel Jelkmann (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: René (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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é

Autor: Zotteljedi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 :-/

Autor: Philipp Sªsse (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Marcus Maul (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Zotteljedi (Gast)
Datum:

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

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

Eigenwillige Definition von Division. :-)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.