Forum: Mikrocontroller und Digitale Elektronik Gedankliches Problem beim Normieren


von Rahul (Gast)


Lesenswert?

Moin,
immer wieder gibt es die Diskussion, ob man bei der Umrechnung u.a. der
ADC-Werte duch 1023 oder durch 1024 teilen soll.
Die einen meinen, da es sich ja um 1024 mögliche Werte handelt, müsste
man auch durch 1024 teilen.
Diese Meinung kann ich aus für mich sehr logischen Gründen nicht
teilen:
1. der grösste vorkommende Wert ist 1023. Da es sich bei Umrechnungen
von ADC-Werten in Spannungen ja eigentlich immer darum dreht, eine
Normierung (Messwert/Maximalwert) mit einer Konstanten zu
multiplizieren (Nämlich der maximalen Spannung), kann bei einer
Division durch 1024 nie ein Wert von 1 herauskommen.
Dass es da gewisse Fehler gibt (maximale Auflösung 1LSB...), streite
ich nicht ab, aber durch die Berechnung mit 1024 entsteht meiner
Meinung nach noch ein Fehler.

2. das Teilen durch 1024 (0x400) könnte man auch durch Verschieben des
Wertes (2Byte bzw. 16Bit) um 10 bit nach rechts realisieren.
Bei einem Höchstwert von 0x3FF hat man dann nur noch 0x000...

3. Hätte man einen Datenbreite von 9 Bit also einen Wertebereich von
0x000 bis 0x3FF, dann käme in diesem Wertebereich gar keine 0x400 vor.
Ich gehe ja auch nicht hin, und teile ein Integer (Höchstwert 0xFFFF)
durch 0x10000, bloß weil das die Anzahl der möglichen Wert
(Mächtigkeit?) dieser Zahlenmenge ist.

Das snd halt die Gründe, warum sich mir immer die Nackenhaare
aufstellen, wenn ich solche Divisionen sehe. (Bei 8Bit Werten würde man
ja von char noch int wechseln...)
Ich lasse mich gerne davon überzeugen, dass ich falsch liege, nur
momentan bin ich der Meinung, dass andere Leute den Fehler machen,
falsch zu rechen.
Ich bin mir auch darüber im Klaren, dass man bei Integerberechnungen
erst multipliziert und dann dividiert.

von peter dannegger (Gast)


Lesenswert?

Die meisten ADCs arbeiten nach dem SAR-Prinzip, d.h. Uref wird
stufenweise durch 2 geteilt: Uref/2, Uref/4, Uref/8 usw.

Bei einem 10Bit-ADC ist also Umax = Uref/1024 * 1023.

Uref durch 1024 zu teilen ist also richtig.


Peter

von johnny.m (Gast)


Lesenswert?

Hallo

Ich muss auch immer wieder drüber nachdenken, ob das so stimmen kann.
Bin aber mittlerweile glaub ich auf dem richtigen Dampfer:

Ein Successive-Approximation-ADC (wie er z.B. in den AVRs drinsteckt)
arbeitet folgendermaßen:
1. Das MSB wird gesetzt und über den DAC gibts am Komparator die halbe
Referenzspannung (d.h. die Referenzspannung muss 2 * MSB sein, also bei
10 Bit Auflösung 2 * 512 = 1024!)
2. Ist der Wert am Messeingang größer als der vom DAC ausgegebene,
bleibt das Bit gesetzt, andernfalls wird es wieder gelöscht.
3.... Das geht mit jedem Bit so weiter (Bei 10 Bit also 10 mal das
ganze)

Das bedeutet auch, dass der Wert VREF nicht gemessen werden kann. Es
bleibt immer ein LSB 'übrig'. VREF wird zwar durch 1024 geteilt
(allgemein durch 2^n), aber der höchste Digital-Wert der ausgegeben
werden kann ist 1023 oder 2^n - 1!

Deshalb heißt der ADC auch 'Successive Approximation' weil er eben
eine sukzessive Annäherung des Wertes durchführt. Die Anzahl der
auflösbaren Schritte muss eine Potenz von 2 sein.

Gruß

Johnny

von Karl H. (kbuchegg)


Lesenswert?

Ich denke, der Schluessel zum Ganzen liegt darin, dass man
sich mal klarmacht, wass denn die Ausgabe bedeutet:
Der ADC gibt dir ja nicht eine 'Punktausgabe' sondern
eine Bereichsausgabe. Eine Angabe von 287 bedeutet nicht,
dass die Spannung genau am Wert 287 liegt, sondern dass sie
irgendwo im Bereich 287 bis 288 gemessen wurde. Wo genau
in diesem Bereich laesst sich nicht genauer sagen, aber irgendwo
in diesem Bereich war es. Folgerichtig bedeutet eine ADC Ausgabe
von 1023, dass der richtige Wert irgendwo im Intervall 1023 bis
1024 war.

von johnny.m (Gast)


Lesenswert?

Müsste so stimmen. 1023 bedeutet, alle Bits sind gesetzt, inkl. das LSB,
das zuletzt überprüft wurde. D.h. die Spannung am Messeingang war GRÖßER
als oder GLEICH der vom DAC ausgespuckten (ansonsten wäre das LSB ja
wieder gelöscht worden) --> U_mess >= 1023 * U_ref/1024 !

Gruß

Johnny

von Hagen (Gast)


Lesenswert?

Johnny hat es schon auf den Punkt gebracht

U_mess >= ADC Wert * U_ref / 2^ADC Auflösung.

Also bei 10 Bit ADC mit 5 Volt:

U_mess >= ADC Wert * 5 / 1024;

Oder umgestellt dann

U_mess >= ADC Wert / 1024 + 5.

Man dividiert also durch 1024 und nicht 1023.

Gruß Hagen

von Hagen (Gast)


Lesenswert?

Möchte man U_mess normieren auf  ADC_wert -1 < U_mess < ADC_Wert +1 dann
wird man so rechnen

U_mess ~= (ADC_Wert * U_ref + U_ref / 2) / 1024;

oder vereinfachte Rechnung mit

U_mess ~= (ADC_Wert +1) * U_ref / 1024;

Statt als nun mit 1023 zu dividieren muß man immer noch mit 1024 = ADC
Auflösung dividieren, dafür aber den ADC Wert vorher im Meßbereich um
0.5 LSB verschieben.

Gruß Hagen

von Rahul (Gast)


Lesenswert?

der Teiler bezieht sich also auf die Referenz-Spannung und nicht auf die
vom ADC gelieferten Wert?
Wieder was gelernt. Danke.

von johnny.m (Gast)


Lesenswert?

@hagen:
> U_mess >= ADC Wert / 1024 + 5 ???

Gehe mal von einem Tippfehler aus... U_mess >= (ADC / 1024) * 5 V
allerdings auch:
U_mess < ((ADC + 1) / 1024) * 5 V
(Der Vollständigkeit halber:-)

Das Wichtigste ist eben, dass U_ref selber nicht gemessen werden kann.
Ein Schritt, also 1 LSB, fehlt eben.

@Rahul:
Genau. Das hängt eben damit zusammen, dass immer die Hälfte dazugegeben
wird, dann wieder die Hälfte von der Hälfte...

Und 1023 lässt sich so furchtbar schwer ganzzahlig halbieren:-)

Gruß

Johnny

von Hagen (Gast)


Lesenswert?

Ich persönlich arbeite immer mit

U_mess = (ADC_Wert * U_ref) / 1024 oder eben

U_mess = (ADC_Wert * U_ref +-U_Ref/2) / 1024.

Das verhindert Ungenauigkeiten bei der Berechnung der Divisionen ohne
Rest wie auf einer MCU üblich wenn man rechnet U_mess = (ADC_Wert /
1024) * U_ref.

Bei einem 10 Bit ADC ist ADC_Wert 10 Bit groß und V_Ref meistens 5V = 4
Bit. Man kommt also ohne Probleme mit 16 Bit Berechnungen ohne
Fließkomma aus.

Ich weis das ist im Grunde alles trivial, aber leider nicht jedem
bewusst.

Gruß Hagen

PS: @johnny, ja war ein Tippfehler. Auch der Normierung im Meßbereich
um +- 0.5 LSB ist ein Fehler drinnen, muß +-0.5 U_ref heisen je nachdem
ob man auf/abrunden möchte.

von Hagen (Gast)


Lesenswert?

>>der Teiler bezieht sich also auf die Referenz-Spannung und nicht auf
>> die vom ADC gelieferten Wert?

Nicht korrekt ;)

Der Teiler bezieht sich nur auf das verwendete Verfahren und dessen
Auflösung. U_ref ist unbekannt, bzw. eine einfache Variable aus Sicht
des Verfahrens. Die 1024 ist einfach der Wertebereich und Genauigkeit
des benutzten Meßverahrens.

Ergo bezieht sich die 1024 nur auf den Meßwert ADC_Wert und eben NICHT
auf U_ref.

Angenommen wir benutzen kein binäres SAR, sondern trinäres.

Dann ergäbe sich

U_mess = U_ref * ADC_Wert / 3^ADC_Auflösung.

U_Mess -> U_Ref;
ADC_Wert -> 3^ADC_Auflösung;

Die 1024 bei 2^10 Bit ADC ergibt sich also auf grund des binären SAR
Meßverharens im ADC und der ADC_Wert ist davon direkt abhängig.

U_ref ist einzigst eine Variable, sowohl im Meßverfahren wie auch in
der mathematischen Berchnung. U_Ref ist dementsprechend absolut
unabhängig von der ADC Auflösung, sprich den 1024.

Gruß Hagen

von Hagen (Gast)


Lesenswert?

Beispiel:

Wir messen eine Spannung die 1 Volt hat. Als erstes an einem AVR mit 5
Volt Vcc und U_ref = Vcc und mit 8 Bit ADC Auflösung:

U_mess = U_ref * ADC_Wert / 2^8.

ADC_Wert = U_mess / U_ref * 2^8;

51 = 1 Volt / 5 Volt * 256;

Wir bekommen also einen ADC Wert von 51, ergibt

0.996 Volt = 51 * 5 Volt / 256;


Nun messen wir wieder 1 Volt, aber mit 10 Bit ADC und 5 Volt externe
U_ref.

U_mess = U_ref * ADC_Wert / 2^10;
ADC_Wert = U_mess / U_Ref * 2^10;
205 = 1 Volt / 5 Volt * 1024;
1 Volt = 205 * 5 Volt / 1024;


Nun 1 Volt mit 2.56 Volt interner U_ref und 10 Bit Auflösung:

U_mess = U_ref * ADC_Wert / 2^10;
ADC_Wert = U_mess / U_ref * 2^10;
400 = 1 Volt / 2.56 Volt * 1024;
1 Volt = 400 * 2.56 Volt / 1024;


Du siehst das die Berechnungen immer unabhängig von U_ref sind und der
ADC_Wert, bei gleicher U_mess Spannung von 1 Volt, immer direkt von der
ADC Auflösung von jeweils 8 Bit  (256) und 10 Bit (1024) abhängig ist.

Gruß Hagen

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.