Forum: Mikrocontroller und Digitale Elektronik Festkomma Vorkomma- / Nachkommastelle aufteilen


von Uwe (Gast)


Lesenswert?

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

von Peter II (Gast)


Lesenswert?

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

von Teo D. (teoderix)


Lesenswert?

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 :)

von Teo D. (teoderix)


Lesenswert?

Teo D. schrieb:
> Vergiss das Komma, das gehört nur in deinen Kopf

Ohje, ich glaub ich leg mich wieder hin :)

von W.A. (Gast)


Lesenswert?

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.

von Uwe (Gast)


Lesenswert?

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

von W.A. (Gast)


Lesenswert?

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.

von Timo (Gast)


Lesenswert?

mit MOD und DIV also MOD 10 DIV 10
Mod 100 DIV 100
etc

von Falk B. (falk)


Lesenswert?

@ 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.

von Uwe (Gast)


Lesenswert?

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

von Chris F. (chfreund) Benutzerseite


Lesenswert?

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.

von W.A. (Gast)


Lesenswert?

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?

von Tommi (Gast)


Lesenswert?

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.

von Pandur S. (jetztnicht)


Lesenswert?

> 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.

von M. K. (sylaina)


Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

@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

von Uwe (Gast)


Lesenswert?

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

von Karl M. (Gast)


Lesenswert?

Hallo,

und du sendest ADCII Zahlen ?

sonst wäre die Angabe von 02 = 2 gleichwertig !

von Joachim B. (jar)


Lesenswert?

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
von Wolfgang (Gast)


Lesenswert?

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?

von Joachim B. (jar)


Lesenswert?

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
von Uwe (Gast)


Lesenswert?

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

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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.

von Wolfgang (Gast)


Lesenswert?

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?

von Uwe (Gast)


Lesenswert?

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

von eProfi (Gast)


Lesenswert?

> 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"

von eProfi (Gast)


Lesenswert?

oder gleich:
voltage = 5 + ((adc_wert * 2500L) >> 10);
vor  =  voltage / 1000;          // ganze Volt
nach = (voltage % 1000) / 10;

von Peter D. (peda)


Lesenswert?

Uwe schrieb:
> Ja, da stimmt. Zahlenformat mit zwei Nachkommastellen.
1
  sprintf( buffer, "%d,%02d", val / 100, val % 100);

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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
von Falk B. (falk)


Lesenswert?

@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.

von Marc V. (Firma: Vescomp) (logarithmus)


Angehängte Dateien:

Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

@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.

von Wolfgang (Gast)


Lesenswert?

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.

von eProfi (Gast)


Lesenswert?

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

von hp-freund (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.