Forum: Mikrocontroller und Digitale Elektronik Multiplikation mit Kommazahl


von MaxMüller (Gast)


Lesenswert?

Im Rahmen der Weiterverarbeitung einer vom ADC eines Atmega8 gewandelten 
Spannung muss ich den eingelesenen Wert mit einer recht kleinen 
Kommazahl multiplizieren. Also in der Art:

Ergebnis = ADC-Wert * 0,000000071351753

In Bascom ist das ja kein Problem. Nur muss ich das leider in Assembler 
lösen. Allerdings fehlt mir da im Moment ein gescheiter Lösungsansatz. 
Kann mir da jemand evtl. weiterhelfen?

von Benedikt K. (benedikt)


Lesenswert?

Du kannst Ergebnis=0 schreiben, wenn du mit 16bit Ganzzahlen rechnest.

Beschreib doch mal was du vorhast. Es gibt bestimmt eine einfachere 
Lösung die auch funktioniert.

von Walter (Gast)


Lesenswert?

in welcher Zahlendarstellung soll denn das Ergebnis sein, wie wird es 
weiterverarbeitet?

von RT (Gast)


Lesenswert?

Ein word mal diese Konstante gibt nicht mehr sehr viel. Versuch doch mal 
ADC*71351753, behalte *0,000000000000001

RT

von MaxMüller (Gast)


Lesenswert?

Es geht hierbei um die Aufloesung eines Polynoms 6. Grades, welches die 
nichtlineare Kennlinie eines Sensors beschreibt.

Also ich muss da nicht nur einmal ADC*0.0000000xxxxx rechnen sondern im 
Prinzip so:

Ergebnis = ADC*0.0000000xxxxxxxx
Ergebnis = Ergebnis - 0.000000xxxxxxxx
Ergebnis = Ergebnis * ADC
Ergebnis = Ergebnis + 0.00000000xxxxxxxx
Ergebnis = Ergebnis * ADC
Ergebnis = Ergebnis - 0.00000xxxxxxxx
Ergebnis = Ergebnis * ADC
Ergebnis = Ergebnis + 0.000xxxxxxxx
Ergebnis = Ergebnis * ADC
Ergebnis = Ergebnis - 0.0xxxxxxxx
Ergebnis = Ergebnis * ADC
Ergebnis = Ergebnis + 0.0xxxxxxxx

von Benedikt K. (benedikt)


Lesenswert?

Brauchst du dabei wirklich 8 Stellen Auflösung ?
Der ADC liefert doch gerade mal 3 Stellen, da kannst du eigentlich 
spätestens  ab der 5. Stelle aufhören ohne dass sich am Ergebnis 
wirklich was ändert.

von MaxMüller (Gast)


Lesenswert?

Das kann man evtl. schon machen, da muss ich noch mal schauen. Mir geht 
es aber halt darum, wie ich die Multiplikationen möglichst effizient 
hinbekomme. Und da fehlt mit irgendwie immer noch der richtige Ansatz.

von Axel R. (Gast)


Lesenswert?

>>0,000000071351753

das ist 15 Stellen, nur hiterm Komma. Kann man sicher irgentwie anders 
rum interpretieren (Float?)

/XlR.

von Peter D. (peda)


Lesenswert?

Mach doch erstmal ne Genauigkeitsabschätzung, wieviel Iterationen 
überhaupt nen Sinn ergeben.

Aus 0..1023 kannst Du doch nie 8 Digits rauskitzeln !

Maximal 3 Digits, eher noch weniger je nach Nichtlinearität, dann ist 
Ende der Fahnenstange.

Wenn ich das in Assembler machen müßte, würde ich mit Excel ne Tabelle 
von etwa 50 Stützwerten ausrechnen lassen und dazwischen einfach linear 
interpolieren.


Peter

von Detlef _A (Gast)


Lesenswert?

Max, Deine kleinste Zahl ist ~10e-8, die größte ~10-2, macht 6 
Zehnerpotenzen Dynamik, das entspricht 20Bit, 10Bit AD Wandler macht 
nochmal 10Bit, zusammen 30, da muß Du in Integer schon mit 64Bit 
rechnen, 32 reichen da nicht mehr. Oder Du muß in Assembler und float 
rechnen. Beides nicht so schön.

Ich schließe mich meinen Vorrednern an: Die Genauigkeit, die Du 
anstrebst, brauchst Du sicher nicht. 20Bit Rechendynamik bei 10Bit AD 
Wandler  Eingangsdynamik ist bullshit, das geht immer anders. Die 
Genauigkeitsanforderungen solltest Du nochmal überdenken.

Cheers
Detlef

von Jörg R. (Firma: Rehrmann Elektronik) (j_r)


Lesenswert?

@Max:
Ein Polynom 6. Grades sieht normalerweise so aus:
Ergebnis = a0 + a1*ADC + a2*ADC^2 + a3*ADC^3 + ... + a6*ADC^6
Im Prinzip geht das immer mit einfacher Festkommaarithmetik. Das ist in 
Assembler nicht so schwierig. Die sehr kleinen Werte, z.B. a6, werden 
vermutlich mit den Polynomtermen höheren Grades multipliziert, sodass 
das die einzelnen Terme am Ende immer einen "normalen" Wert ergeben. 
I.d.R. reicht dann eine 32-Bit-Festkommaarithmetik, z.B. mit 16 
Vorkomma- und 16 Nachkommastellen oder auch 24 Vorkomma- und 8 
Nachkommastellen. Wenn Du jetzt z.B. den Term a6*ADC^6 wie folgt 
aufspaltest
a6*ADC^6 = a6^(1/6)*ADC * a6^(1/6)*ADC * ... * a6^(1/6)
bleibst Du idealerweise immer in Deinem 32-Bit-Zahlenbereich. Du mußt 
Dir halt vorher überlegen, in welchem Wertebereich der ADC liegt, damit 
eine 32-Bit x 32-Bit-Multiplikation ein vernünftiges Ergebnis liefert. 
Du mußt ja nach der Multiplikation, die 64 Bits liefert, immer 32 Bits 
abschneiden können, ohne das Ergebnis nennenswert zu verfälschen. 
Sinnvollerweise verschiebt man die Binärzahlen vor der Multiplikation 
soweit nach links, dass die MSBs möglichst aufgefüllt werden und teilt 
das Produkt entsprechend wieder durch Rechtsschiebung. Dadurch erreicht 
man maximale Rechengenauigkeit. Bei komplizierten Formeln würde ich dann 
aber lieber eine Fließkommaarithmetik verwenden.

Jörg

von Falk (Gast)


Lesenswert?

@Peter Dannegger

>Mach doch erstmal ne Genauigkeitsabschätzung, wieviel Iterationen
>überhaupt nen Sinn ergeben.
>Aus 0..1023 kannst Du doch nie 8 Digits rauskitzeln !

Klar, sogar 10! Allerdings nur binäre ;-)

MFG
Falk

von Wolfram (Gast)


Lesenswert?

>Bei komplizierten Formeln würde ich dann aber lieber eine >Fließkommaarithmetik 
verwenden
Du hast ihm gerade nachgewiesen, das er auch bei 32Bit Festkomma 
arithmetik aufpassen muss, das er nichts verliert. Ein float (und auch 
double) auf dem AVR hat 32Bit, 8 Bit Exponent, Mantisse: 23 Bit
Mit deiner Mantisse von 23Bit wird die Situation wohl nur noch 
verschlechtert.
Obwohl bei:
>Ergebnis = ADC-Wert * 0,000000071351753
also wenn BASCOM nicht mit 64bit double rechnet wird es wohl kaum 
schlechter.
Stichwort: Maschinengenauigkeit

Mach es wie Peter vorschlägt mit einer Tabelle und Interpolation, selbst 
mit nur 50 Stützwerten würde ich davon ausgehen das das schon genauer 
ist, als dein jetziges BASCOM Programm. Warum muss das eigentlich 
unbedingt in Assembler sein?

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.