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 :)
Teo D. schrieb: > Vergiss das Komma, das gehört nur in deinen Kopf Ohje, ich glaub ich leg mich wieder hin :)
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.
mit MOD und DIV also MOD 10 DIV 10 Mod 100 DIV 100 etc
@ 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 | int voltage, 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
Hallo, und du sendest ADCII Zahlen ? sonst wäre die Angabe von 02 = 2 gleichwertig !
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
:
Bearbeitet durch User
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
:
Bearbeitet durch User
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
Falk B. schrieb:
> OK. Dann halt so.
1 | int voltage, 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 |
Das ist wahrscheinlich der schnellste und kürzeste Weg, nur:
1 | (voltage + 5) |
Ist unnötig, MEGA hat sowieso einen Fehler von typisch 2 LSB, sind für mich +/- 7.4mV, da machen die +5 auch nicht viel aus.
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
> vor = voltage / 1000; Falk, das haut nicht ganz hin, da z.B. bei ADC 408 und 409 0,0 herauskäme: 408 * 2500 / 1024 = 996 996 / 1000 = 0 ((996+5) mod 1000) /10 = 0 richtig ist vor = (voltage+5)/1000; N.B. 2008 hatte ich die Idee mit der Umwandlung mittels zweier Tabellen: Beitrag "ADC-Wert z.B. in Spannung umrechnen und dezimal ausgeben mittels Tabellen, auch Linearisieren"
oder gleich: voltage = 5 + ((adc_wert * 2500L) >> 10); vor = voltage / 1000; // ganze Volt nach = (voltage % 1000) / 10;
Uwe schrieb: > Ja, da stimmt. Zahlenformat mit zwei Nachkommastellen.
1 | sprintf( buffer, "%d,%02d", val / 100, val % 100); |
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.
:
Bearbeitet durch User
@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.
Es geht noch einfacher: voltage = ((adc_wert + 2)* 250L) >> 10; vor = voltage / 100; // ganze Volt nach = voltage % 100; Habe gerade nachgerechnet: von allen ADC-Werten (0 bis 1023) unterscheidet sich in nur 12 Fällen das Ergebnis um ein Digit. meine erste Formel meine zweite Formel Schwelle ADC mV vor nach cV vor nach 0,205078 84 205 0 21 20 0 20 0,415039 170 415 0 42 41 0 41 0,625000 256 625 0 63 62 0 62 0,725098 297 725 0 73 72 0 72 0,935059 383 935 0 94 93 0 93 1,145020 469 1145 1 15 114 1 14 1,455078 596 1455 1 46 145 1 45 1,665039 682 1665 1 67 166 1 66 1,875000 768 1875 1 88 187 1 87 1,975098 809 1975 1 98 197 1 97 2,185059 895 2185 2 19 218 2 18 2,395020 981 2395 2 40 239 2 39 Autor: Joachim B. (jar) Datum: 24.06.2016 13:00 Ich schlage noch daV (Dekavolt), hV (Hektovolt) und MV (Megavolt) vor ;-). Ich wunderte mich früher bei österreichischen Kochrezepten, was dag bedeutet: Dekagramm oder kurz Deka. https://de.wikipedia.org/wiki/Dekagramm https://de.wikipedia.org/wiki/Vors%C3%A4tze_f%C3%BCr_Ma%C3%9Feinheiten#SI-Pr.C3.A4fixe
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.