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
voidBatteriespg(void)
2
{
3
uint16_twert1,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
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
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?
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.
> 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.
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!
> 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.
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
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.
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
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
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.
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
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
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
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
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.
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?
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.
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
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
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.
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