Forum: Mikrocontroller und Digitale Elektronik ADC Umrechnung Problem


von Jens-Frederik M. (elomt)


Lesenswert?

Hallo

Ich habe zur Zeit ein Problem mit der Umrechnung des ADC-Werts.
Ich will eine Spannung an ADC-PORT 0 messen und diese auf 3 
7-Segmentanzeigen ausgeben. Leider werden föllig falsche Zahlen 
ausgegeben. Wenn ich max. Spannung anlege, dann wird 049 angezeigt. Ich 
nutze die interne Ref.Spg.

Meine Umrechnung sieht so aus:
Als "#include" habe ich nur die "io.h" geladen.
1
void Batteriespg (void)
2
{
3
  uint16_t wert1, wert2, wert3;
4
  wert1 = (mittelwert * 256 / 1024);
5
  wert2 = (wert1 % 100);
6
  wert3 = (wert2 % 10);
7
  stelle1 = wert1 / 100;
8
  stelle2 = wert2 / 10;
9
  stelle3 = wert3;
10
  Ziffer();
11
}

Das Unterprogram "Ziffer" vergleicht den Inhalt von "stelle1-3" und gibt 
den entsprechenden Wert für die Anzeige aus. Dies funktioniert auch 
einwand frei. Also muss der Fehler wohl die Umrechnung sein.

Vielen Dank Jens

von Ralf (Gast)


Lesenswert?

Wenn du einen 10 bit A/D Wandler hast, muss diese Zeile:

>>  wert1 = (mittelwert * 256 / 1024);

so lauten:

  wert1 = (mittelwert * 256 / 1023);
                                 ^
                                 |

Da du Werte von 0 an hast. Das ist zwar wahrscheinlich
nicht der Fehler den du suchst, aber dennoch ist deine
Umrechnung nicht ganz richtig.

Ralf

von Peter II (Gast)


Lesenswert?

Ralf schrieb:
> Wenn du einen 10 bit A/D Wandler hast, muss diese Zeile:
> ...
> so lauten:

nein muss sie nicht, es ist dann nur viel langsamner und ändert nicht 
wirklich was am ergebniss.

Also bitte so lassen.

Aber wo hast du denn die Referenzspannung verrechnet, die taucht doch 
nirgends auf?

von Εrnst B. (ernst)


Lesenswert?

Ralf schrieb:
>>>  wert1 = (mittelwert * 256 / 1024);
>
> so lauten:
>
>   wert1 = (mittelwert * 256 / 1023);
>                                  ^

zum gefühlt 1000sten Mal: 1024 ist richtig.
1023 ist falsch (zwar nur ein wenig) und dazu auch noch viel aufwändiger 
zu berechnen.

Ralf schrieb:
> Da du Werte von 0 an hast

Genau deswegen. Du hast 1024 verschiedene Werte, der Höchste ist 1023.

von Peter II (Gast)


Lesenswert?

> wert1 = (mittelwert * 256 / 1024);
wenn der mittelwert > 256 ist, dann kommt es zu einem überlauf.

wert1 = mittelwert / 4;

macht das gleiche aber ohne den überlauf fehler.

von Uwe (de0508)


Lesenswert?

Hallo Jens,

wie immer fehlen wichtige Teile deines Programms:
1
#include <stdint.h>
2
<type> mittelwert;
3
 
4
// Annahme
5
uint8_t stelle1,stelle2,stelle3;

von Udo S. (urschmitt)


Lesenswert?

Was für einen Typ hat mittelwert?
Wenn der 16 bit hat dann überlege dir mal was passiert wenn du einen 
Wert größer 8 Bit (AD Wandlungswert?) mit 256 multiplizierst!

von Jens-Frederik M. (elomt)


Lesenswert?

Hallo

Die 256 ist doch meine Ref.Spanung.

Gruß Jens

von Karl H. (kbuchegg)


Lesenswert?

>   Ich nutze die interne Ref.Spg.

>   wert1 = (mittelwert * 256 / 1024);

Die 256 resultieren wohl aus der Referenzspannung.
Die interne Referenzspannung ist hauptsächlich eines: sie ist konstant. 
Aber sie ist NICHT exakt 2.56 Volt. Wie gross sie auf deinem konkreten 
µC wirklich ist, musst du dir ausmessen. Die kann ein paar Zehntelvolt 
von den 2.56V abweichen. Genaueres dazu erfährst du im Datenblatt.

Hast du dir schon mal deinen "mittelwert" vor der Umrechnung angesehen?
Lass dir den doch mal direkt ausgeben, ohne ihn umzurechnen. Wenn der 
Wert da drinn schon nicht stimmt, suchst du an der falschen Stelle.

von Jens-Frederik M. (elomt)


Lesenswert?

Hab den mittelwert zu klein deffiniert. Jetzt funktioniert hab nur noch 
eine ungenauigkeit von ca. 20mV. Aber das bekomme ich schon hin. Es sind 
doch immer wieder die besch... kleinen Flüchtigkeitsfehler die einem zum 
verzweifeln bringen.

Vielen Dank an alle.
Gruß Jens

von Karl H. (kbuchegg)


Lesenswert?

Jens-frederik Maug schrieb:
> Hab den mittelwert zu klein deffiniert. Jetzt funktioniert

Du hast jetzt aber nicht die Variable mittelwert zu einem uint32_t 
gemacht, oder?

> hab nur noch
> eine ungenauigkeit von ca. 20mV.

Das wird die Referenzspannung sein, die eben nicht 2.56V ist, sondern 
leicht davon abweicht.

von Ralf (Gast)


Lesenswert?

Deine Formel lautet doch

Wobei n die Aufloesung deines A/D Wandler ist.
zum besseren Verstaendnis. Du hast ein 3 bit A/D Wandler
der 5 V misst. Er kann die Werte darstellen :

     000 = 0 V
     001 = 0.714 V
     010 = 1.428 V
     011 = 2.142 V
     100 = 2.857 V
     101 = 3.571 V
     110 = 4.285 V
     111 = 4.999 ~ 5 V

Dadurch errechnet sich ein Bit zu

   5 V / (8 bit - 1) = 0.714

eben ein Bit weniger als die Gesamtaufloesung.

Ralf

von Jens-Frederik M. (elomt)


Lesenswert?

Hab die Variable mittelwert als uint32_t was soll den daran so schlimm 
sein ?

Meine Ref.Spg. ist 2,59V deshalb hab ich jetzt statt 256 -> 259 
eingetragen ändert aber nichts am Ergebnis. Hab gerade mal das Poti 
runter gedreht auf 34mV meine ANzeige gibt dan 10mV aus und wenn ich nur 
etwas unter 30mV drehe springt sie auf Null.

Gruß Jens

von Peter II (Gast)


Lesenswert?

Jens-frederik Maug schrieb:
> Hab die Variable mittelwert als uint32_t was soll den daran so schlimm
> sein ?

das es für dem µC viel komplizierter ist damit zu rechnen, wenn du genug 
resourcen übrig hast kann man es so machen - schön ist es aber nicht. 
Weil man es ohne Probleme umgehen könnte.

von Karl H. (kbuchegg)


Lesenswert?

Ralf schrieb:

> Wobei n die Aufloesung deines A/D Wandler ist.
> zum besseren Verstaendnis. Du hast ein 3 bit A/D Wandler
> der 5 V misst. Er kann die Werte darstellen :
>
>      000 = 0 V
>      001 = 0.714 V
>      010 = 1.428 V
>      011 = 2.142 V
>      100 = 2.857 V
>      101 = 3.571 V
>      110 = 4.285 V
>      111 = 4.999 ~ 5 V

Irrtum.
Der ADC sagt dir nicht in Absoluteinheiten wie gross deine Spannung ist, 
sondern er sagt dir in welchem Spannungsbereich sich deine zu messende 
Spannung wiederfindet.

Ein (hypotetischer) ADC, der 5 verschiedene Werte bringen kann und 5V 
messen soll, liefert dir

    Volt      ADC Wert
    0 .. 1      0
    1 .. 2      1
    2 .. 3      2
    3 .. 4      3
    4 .. 5      4



Ein ADC Wert von 4 (der größte mögliche Wert), sagt also nicht aus, dass 
die zu messende Spannung 5V groß gewesen wäre, sondern dass sich die zu 
messende Spannung irgendwo im Bereich 4 bis 5V bewegt hat.

Demenstprechend sagt dir ein ADC-Wert von 1023 auch nicht, dass die 
Spannung exakt VRef gewesen war, sondern dass sie im letzten Intervall 
gelegen ist. Die Breite eines Intervalls (in Volt) ist
  Referenzspannung / Anzahl_der_möglichen_Werte

von Karl H. (kbuchegg)


Lesenswert?

Jens-frederik Maug schrieb:
> Hab die Variable mittelwert als uint32_t was soll den daran so schlimm
> sein ?

Der Variablenname 'mittelwert' suggeriert, das sich dieser Wert aus 
einer Berechnung ergibt und nicht direkt ein einzelner ADC-Wert ist.
D.h. du zwingst an einer anderen Stelle dem µC 32 Bit Arithmetik auf, 
weil du hier

   wert1 = (mittelwert * 256 / 1024);

eine 32 Bit Multiplikation benötigen würdest, die du auch ganz einfach 
durch

   wert1 = (mittelwert * 256UL / 1024);

erreichen könntest

von Thomas E. (thomase)


Lesenswert?

Karl Heinz Buchegger schrieb:
> wert1 = (mittelwert * 256UL / 1024);

Oder man kürzt das:
wert1 = (mittelwert * 256UL / 1024) = mittelwert/4 = mittelwert >> 2.

Oder ganz einfach: ADMUX |= (1 << ADLAR);
Sollte für die Überwachung der Batteriespannung ausreichen.

mfg

von Jens-Frederik M. (elomt)


Lesenswert?

Hab jetzt auf uint16_t und dem 259UL geändert. Funktioniert auch aber 
ich bekomme die Ungenauigkeit nicht kleiner.
Wenn ich doch eine Ref.Spg. von 2,59V habe und der ADC 1024 
Einteilungen. Dann müsste ich doch auf 2,5mV genau messen können. Warum 
ist bei mir dieser Wert zehn mal schlechter.

Gruß Jens

von Udo S. (urschmitt)


Lesenswert?

Wie groß ist der Fehler seines Messgeräts?
Wie groß ist der systematische Fehler durch Messung (Innenwiderstand des 
Messgeräts
Wie groß ist der Fehler deines AD Wandlers? 2,5 mV ist die AUFLÖSUNG, 
nicht die Genauigkeit. Schau mal im Datenblatt.

von Karl H. (kbuchegg)


Lesenswert?

Jens-frederik Maug schrieb:

> Wenn ich doch eine Ref.Spg. von 2,59V habe

Wo hast du die 2.59V her?
Ist dein Messgerät genau genug, dass du der Hunderstelstelle trauen 
kannst?
Wie hast du die zu messende Spannung kontrolliert?
Ist auch dort dein unabhängiges Messgerät genau genug, dass du der 
Hunderstelstelle trauen kannst?
(Nur weil ein Baumarkt-Multimeter 2 Stellen nach dem Komma anzeigt, 
heißt das noch lange nicht, dass die auch stimmen. Auflösung ist nicht 
gleich Genauigkeit)

Hast du die Referenzspannung mit (wenigstens) einem Kondensator an VRef 
geblockt?

Wie hoch ist die Ausgangsimpedanz, von wo du die Messspannung abgreifst?

Hast du die ADC Frequenz auch nicht zu hoch oder zu niedrig angesetzt?

Wie weit streuen deine Einzelmessungen um den Mittelwert?

von Εrnst B. (ernst)


Lesenswert?

Jens-frederik Maug schrieb:
> Dann müsste ich doch auf 2,5mV genau messen können.

Die letzten ein, zwei Bits vom ADC-Ergebnis sind "für die Tonne".
=> Du kannst mit nem Mittelwert arbeiten, das machts ein bischen besser.

Und: Für gute Auflösung und Genauigkeit muss auch die Hardware 
stimmen, da können wir nix zu sagen.

von Unwissender (Gast)


Lesenswert?

Da du nicht schreibst was fuer ein Prozessor du benutzt,
gehe ich mal von einem Atmel Prozessor aus (wegen der
C Syntax).  Dort ist die Reihenfolge der A/D-Registerwerte
die du ausliest wichtig.

Ich glaube erst Low Byte dann High Byte. Vielleicht liegt
es daran.

Gruss

Unwissender

von Jens-Frederik M. (elomt)


Lesenswert?

Ich nutze ein ATMega16.
Mein Multimeter misst auf ein 1/1000 Volt.
Hab am VRef pin ein Kondensator.
Lese nicht die ADCL/ADCH sondern wie im AVR-GCC Beispiel den ADCW aus.
Prozessor läuft mit 1Mhz und ADC Teiler steht auf 16.

Gruß Jens

von Udo S. (urschmitt)


Lesenswert?

Jens-frederik Maug schrieb:
> Mein Multimeter misst auf ein 1/1000 Volt.

Unterschied zwischen AUFLÖSUNG und GENAUIGKEIT.
Hast du dir jetzt mal das Datenblatt angeschaut wg. Genauigkeit der A/D 
Wandler?
Wie lange wartest du nach dem Umschalten des Eingangsmultiplexers bis du 
die A/D Wandlung startest?
Wie niederohmig ist dein A/D Wandler-Eingang beschaltet?

Wer misst misst Mist!
Wer ohne Ahnung misst misst noch mehr Mist!

Karl Heinz hat dir alle notwendigen Tipps gegeben.

von Xenu (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:

>Ein (hypotetischer) ADC, der 5 verschiedene Werte bringen kann und 5V
>messen soll, liefert dir
>
>    Volt      ADC Wert
>    0 .. 1      0
>    1 .. 2      1
>    2 .. 3      2
>    3 .. 4      3
>    4 .. 5      4

Das stimmt aber nur für ADCs, deren erster Übergang beim 1 LSB ist. 
Viele ADCs aber (auch die der AVRs), haben ihren ersten Übergang bei 0,5 
LSB und ihren letzten bei Vmax(Vref) - 1,5 LSB.

Deine Tabelle würde dann so ausschauen:

    Volt        ADC-Wert
    0   .. 0.5     0
    0.5 .. 1.5     1
    1.5 .. 2.5     2
    2.5 .. 3.5     3
    3.5 .. 5       4

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.