Hallo zusammen,
ich versuche mich gerade ein wenig an Festkommaarithmetik im
Zusammenhang mit einem ADC.
Ich habe folgende Ausgangslage:
Referezspannung 2,5V
ADC: 10Bit
Nun bin ich folgendermaßen vorgegangen, wie im Artikel
Festkommaarithmetik von mikrocontroller.net:
alte Auflösung = 2,5V / 1024 = 2,44140625mV
neue Auflösung 1mV
Faktor = 2,44140625mV / 1mV = 2,44140625
Der Faktor wird dreimal mit 10 multipliziert und das Ergebnis auf 2441
gerundet. Die neue Auflösung wird dreimal durch 10 dividiert und beträgt
1μV.
Somit:
gemessene Spannung [µV] = ADCwert * Faktor
Soweit so gut, bzw. die Frage, ob das bis hierhin Sinn macht?
Nun möchte ich den Spannungswert in [V] umrechnen, in Vor- und
Nachkommastelle zerlegen inkl. Runden (auf die 2te Nachkommastelle) und
die beiden Zahlen in zwei Variablen speichern.
Ich weiß nun aber nicht, wie ich die Daten eben in Vor- und
Nachkommastelle zerlegen kann, wo ich da ansetzen soll.
Wäre folgendes ein Sinnvoll Ansatz oder geht es eleganter?
Vorkomma [V]= gemessene Spannung [µV] / 1000000
Nachkomma [V]= (gemessene Spannung [µV] - vorkomma * 1000000) / 10000
Danach müsste dann aber noch gerundet werden, man müsste sich also
nochmal die 3te nachkommastelle ansehen und dann gegebenenfalls die
Nachkomma- auch die Vorkommastelle noch
ändern.
Geht das geschickter?
Gruß
Uwe
Uwe schrieb:> Geht das geschickter?
ja, vorher etwas addieren.
wenn man 1,45 auf eine nachkomme stelle runden will. Dann Addiert man
0,05
1,45 + 0,05 = 1,5
Vergiss das Komma, das gehört nur in deinen Kopf und auf die Anzeige!
2,34V == 2340mV == 2340000µV ....
Kein Komma, nur genug Bits, damit die Ganzzahl da einpasst :)
Uwe schrieb:> Nun möchte ich den Spannungswert in [V] umrechnen
Warum willst du in V umrechnen. Gebe doch deine Daten in Einheiten von
z.B. 1mV aus und füge vor der dritten Stelle ein Komma/Punkt in dem
angezeigten String ein.
Hallo,
s geht nicht nur um die Ausgabe der Daten auf einem Display oder so.
Die Daten werden später noch weiterverarbeitet. Deswegen die Aufteilung
von Vor- und Nachkommastelle in zwei Variablen.
Die Daten können auch weiter in µV in den Variablen stehen. Das wäre
dann ja eine INterpretationssache.
Es geht halt darum, dass man hinterher zwei Variablen at, Vorkomma und
Nachkomma mit den etnspechenden Werten, gerundet.
Gruß
Uwe
Uwe schrieb:> s geht nicht nur um die Ausgabe der Daten auf einem Display oder so.> Die Daten werden später noch weiterverarbeitet. Deswegen die Aufteilung> von Vor- und Nachkommastelle in zwei Variablen.
Vor- und Nachkommastellen gibt es nur bei der Ausgabe. Intern sind das
alles nur ganzzahlige Bits im µC. Selbst bei Variablen vom Datentyp
Float setzt die Zahl sich intern aus der ganzzahligen Mantisse und dem
ganzzahligen 2er-Exponent zusammen.
@ Uwe (Gast)
>Die Daten werden später noch weiterverarbeitet. Deswegen die Aufteilung>von Vor- und Nachkommastelle in zwei Variablen.
Das würde ich lassen, das bringt nur Chaos. Speichere deine Daten in
einer sinnvollen Auflösung, z.B. 1mV
>Die Daten können auch weiter in µV in den Variablen stehen. Das wäre>dann ja eine INterpretationssache.
Also lass sie so.
>Es geht halt darum, dass man hinterher zwei Variablen at, Vorkomma und>Nachkomma mit den etnspechenden Werten, gerundet.
Das braucht man nur für die Ausgabe.
Hallo,
vielen Dank erst einmal.
Die Daten werden erst enmal nicht auf einem Display oder so ausgegeben.
Sie werden an eine Gegenstelle gesendet, welche zwei Werte erwartet,
einmal die Vorkommastelle und einmal die Nachkommastelle.
Diese Daten sollen dann auch getrennt gesendet werden. Deswegen eben die
Aufteilung. Somit bin ich durch die Gegenstelle im Moment festgelegt.
Hätte ich vielleicht vorher noch erwähnen sollen. Wenn man da so drin
steckt, sind viele Sachen selbstverständlich für einen selbst.
Die Gegenstelle erwartet nunmal zwei Werte, Vorkomma und Nachkomma.
Vielen Dank!
Gruß
Uwe
Uwe schrieb:> Die Daten werden erst enmal nicht auf einem Display oder so ausgegeben.> Sie werden an eine Gegenstelle gesendet, welche zwei Werte erwartet,> einmal die Vorkommastelle und einmal die Nachkommastelle.
Dann wandle das in BCD um und zerteile es vor dem Senden. Es bleibt
dabei: dieses Format wird nur für die Ausgabe benötigt. Ist doch egal ob
es eine Displayroutine oder "an eine Gegenstelle senden" ist.
Uwe schrieb:> Somit bin ich durch die Gegenstelle im Moment festgelegt.> Hätte ich vielleicht vorher noch erwähnen sollen. Wenn man da so drin> steckt, sind viele Sachen selbstverständlich für einen selbst.>> Die Gegenstelle erwartet nunmal zwei Werte, Vorkomma und Nachkomma.
Dann hat immerhin der Erfinder der Gegenstelle das Problem mit der
Übertragung von Dezimalzahlen (Welches Trennzeichen "."= Dezimalpunkt
oder Tausendertrennzeichen, ","= Dezimalkomma oder
Zifferngruppentrennung) erkannt und ihm fiel nichts blöderes ein, einen
Zahlenwert in zwei Zahlen zu trennen, die getrennt übertragen werden.
Damit stellt sich auch gleich die Frage nach der Synchronisation, i.e.
woher weiß die Gegenstelle, welche der zwei übertragenen Werte die
Vorkamma und welches die Nachkommazahlen sind.
Verrate doch einfach mal die tatsächlichen Anforderungen, z.B. indem du
zeigst, wie die Daten komplett aussehen müssen, die die Gegenstelle
erwartet.
Wird als Dezimaltrennzeichen jetzt etwa ein Leerzeichen verwendet und
was ist mit führenden Nullen. Wie soll das also wirklich aussehen?
Uwe schrieb:> Somit bin ich durch die Gegenstelle im Moment festgelegt.
Dann nimm die Umwandlung auch erst zum Senden vor. Mit DIV und MOD, wie
oben geschrieben.
> Die Gegenstelle erwartet nunmal zwei Werte, Vorkomma und Nachkomma.
Anmerkung.
Extrem schlechtes Design, da extrem schlecht zu skalieren.
Aussage : Ein Prototyp von Bastlern.
Ich lass Einheiten so gut es geht weg. Bei fachfremden Leuten brauchts
Einheiten nur bei vorstellbaren Groessen, zB Temperatur, aber nicht bei
Spannung.
Elektrische Groessen werden bei mir nur mit Einheiten angezeigt, wenn
der Benutzer die auch nachmessen kann/muss/soll.
Sonst Ganzzahlwerte mit irgendeiner Skalierung, bevorzugt waeren dann
ADC Einheiten.
Ein Regelalgorithmus wird mit ADC Einheiten gerechnet und auch so
angezeigt. Oder allenfalls mit linearisierten ADC Einheiten.
Ein Stellglied arbeitet fuer den Benutzer mit xx.x%, und dabei wird
nicht einmal exakt gerechnet. Wenn fuer den Benutzer das Stellglied als
Maximum wegen der einfacheren Berechnung 102% haben kann, ist das auch
gut.
Uwe schrieb:> Die Daten werden erst enmal nicht auf einem Display oder so ausgegeben.> Sie werden an eine Gegenstelle gesendet, welche zwei Werte erwartet,> einmal die Vorkommastelle und einmal die Nachkommastelle.
Wie schon gesagt wurde, ist es egal ob die Ausgabe an ein Display oder
eine Komunikationseinrichtung geht. Intern rechnet man immer mit
Ganzzahlen und erst die Ausgaberoutine formt dann die Ganzzahl so um wie
man sie haben will.
@Uwe (Gast)
>Die Daten werden erst enmal nicht auf einem Display oder so ausgegeben.>Sie werden an eine Gegenstelle gesendet, welche zwei Werte erwartet,>einmal die Vorkommastelle und einmal die Nachkommastelle.
OK. Dann halt so.
1
intvoltage,vor,nach;
2
3
voltage=(adc_wert*2500L)>>10;// Spannung in mV, rechung in long durch Faktor 2500L
4
vor=voltage/1000;// ganze Volt
5
nach=((voltage+5)%1000)/10;// Nachkomma mit 2 Stellen, 10mV Auflösung, gerundet
Hallo,
dass das alles nicht optimal ist, ist mir klar, aber im Moment ist das
nicht zu ändern.
Ich muss der Gegenstelle das liefern, was sie erwartet.
Die Daten werden in folgendem Format erwartet:
2,94
Vorkomma: 02
Nachkomma: 49
bzw.
0,49
Vorkomma: 00
Nachkomma: 49
Die Daten werden in getrennten Nachrichten hintereinander gesendet.
Somit ist bekannt, welcher Wert, welcher ist.
Tommi schrieb:> Dann nimm die Umwandlung auch erst zum Senden vor. Mit DIV und MOD, wie> oben geschrieben.
Das werde ich mal versuchen. Schaue mir das an, die Werte auf diesem
Wege zu zerlegen.
Gruß
Uwe
Uwe schrieb:> geht nicht nur um die Ausgabe der Daten auf einem Display oder so.> Die Daten werden später noch weiterverarbeitet. Deswegen die Aufteilung> von Vor- und Nachkommastelle in zwei Variablen.
wozu denn das?
rechne mit Ganzzahlen
µV
mV
cV
dV
V
kV
nach belieben, das Komma kannst du ja bei Bedarf in den String vor der
LCD Ausgabe einblenden
Uwe schrieb:> Die Daten werden in folgendem Format erwartet:>> 2,94> Vorkomma: 02> Nachkomma: 49
Interessant wäre z.B. der Fall 2.08
Wird das als "2,8" oder als "2,08" erwartet?
Wolfgang schrieb:> Interessant wäre z.B. der Fall 2.08>> Wird das als "2,8" oder als "2,08" erwartet?
nö total uninteressant, wer Nachkomma erwartet muss wissen wieviel
Komastellen es gibt
bei einer 1/10 -> 0/10
bei zwei 1/100 -> 8/100
bei drei 1/1000 -> 8/1000
bei 2.08 ist das eindeutig 8/100 oder 8 cV als Nachkommastelle
Hallo,
Wolfgang schrieb:> Interessant wäre z.B. der Fall 2.08>> Wird das als "2,8" oder als "2,08" erwartet?
Das würde als 2,08 erwartet.
Karl M. schrieb:> sonst wäre die Angabe von 02 = 2 gleichwertig !
Das wäre gleichwertig.
Gruß
Uwe
Uwe schrieb:> Das würde als 2,08 erwartet.
Also darf man daraus schließen, dass deine Gegenstelle ganz normale
Dezimalzahlen mit Dezimaltrennzeichen "," erwartet, evtl. eingeschränkt
auf ein Zahlenformat mit zwei Nachkommastellen?
Hallo,
Wolfgang schrieb:> Also darf man daraus schließen, dass deine Gegenstelle ganz normale> Dezimalzahlen mit Dezimaltrennzeichen "," erwartet, evtl. eingeschränkt> auf ein Zahlenformat mit zwei Nachkommastellen?
Ja, da stimmt. Zahlenformat mit zwei Nachkommastellen.
Gruß
Uwe
eProfi schrieb:> voltage = 5 + ((adc_wert * 2500L) >> 10);
Wie kommst du überhaupt auf 5 ?
Laut ATMEL ist:
Vin x 1024
ADC = ------------
VREF
Demzufolge ist:
ADC x VREF
Vin = -------------
1024
Multiplikation mit 1000 und anschliessendes Modulo ist natürlich OK,
aber irgendwelche Werte dazurechnen nur damit das Resultat genauer
aussieht ist falsch und unnötig.
Falk hat es wahrscheinlich wegen INT und aufrunden auf +/- 10 gemacht,
aber was du mit 5 bezwecken willst, ist mir unklar.
@Marc Vesely (Firma: Vescomp) (logarithmus)
>eProfi schrieb:>> voltage = 5 + ((adc_wert * 2500L) >> 10);> Falk hat es wahrscheinlich wegen INT und aufrunden auf +/- 10 gemacht,> aber was du mit 5 bezwecken willst, ist mir unklar.
Das ist die Rundung, das +5 muss natürlich VOR der Berechung der Vor-
und Nachkommastelle machen, da hat der eProfi schon recht.
Falk B. schrieb:> Das ist die Rundung, das +5 muss natürlich VOR der Berechung der Vor-> und Nachkommastelle machen, da hat der eProfi schon recht.
Insofern richtig, aber die 5 verlangsamt nur das Ganze ohne wesentlich
zur Genauigkeit beizutragen.
Der Fehler bleibt mit oder ohne Rundung innerhalb der 2 LSB Toleranz
von ATMEL.
Anbei deine Berechnung, von eProfi und von ATMEL.
@Marc Vesely (Firma: Vescomp) (logarithmus)
>> Das ist die Rundung, das +5 muss natürlich VOR der Berechung der Vor->> und Nachkommastelle machen, da hat der eProfi schon recht.> Insofern richtig,
Also was gibt es dann noch zu diskutieren?
> aber die 5 verlangsamt nur das Ganze ohne wesentlich> zur Genauigkeit beizutragen.
Mein Gott, wieviele Milliarden Umrechnungen will der OP wohl machen?
> Der Fehler bleibt mit oder ohne Rundung innerhalb der 2 LSB Toleranz> von ATMEL.> Anbei deine Berechnung, von eProfi und von ATMEL.
Das intertessiert nicht, der OP wollte runden. Fertig.
Ausserdem wurde an KEINER Stelle dieses Thread der Prozessor oder ADC
genannt, es kann durchaus auch ein NICHT-AVR sein.
Marc V. schrieb:> Der Fehler bleibt mit oder ohne Rundung innerhalb der 2 LSB Toleranz> von ATMEL.
Wenn du durch Weglassen der 5 einen zusätzlichen Offset rein bringst,
verschiebt sich das ganze Fehlerband um diesen Offset, so dass der
Gesamtfehler im ungünstigen Fall (ADC-Fehler in gleicher Richtung wie
Rundungsfehler) außerhalb des von ATMEL angegebenen Fehlerbandes landet.
Das MUSS man nicht provozieren.
Ich habe nicht alles durchgelesen, wenn es eine Rechenübung sein soll
ist das Problem ja schon gelöst.
Wenn es einfach sein soll, würde ich an Stelle der 2,5V eine 2,048V
Referenz nehmen.
So kann man sich das Leben öfter mal erleichtern.