Forum: Mikrocontroller und Digitale Elektronik AD Wandler ungenaue Messung


von Hansi L. (fabian87)


Lesenswert?

Hi,

wie schon im Betreff zu lesen ist habe ich ein Problem mit einer 
ungebauen AD Messnung.
Ich messe einfach die Spannung über einem Poti und gebe damit die 
Potieinstellung von 0 - 100 % auf dem Display aus. Nun ist es aber so, 
dass die Messnung zwischen zwei prozentwerten hin und her springt (z.b. 
64 und 65 %) ohne das ich den Poti drehe oder berühre. Das ist bei fast 
allen möglichen potieinstellungen so.
Suche nun den Grund hierfür, denn bei einer 10 bit AD Wandler 
genauigkeit macht das ja mehr als 10 digit pro prozentwert, d.h. schon 
recht große Abweichungen. Bin momentan am rumrätseln, an was es liegen 
könnte:

1) der Versuchsaufbau auf dem Breadboard?
2) vielleicht ist der überlastete spannungregler (7805) dran schuld, der 
hat nur noch eine Spannung von 4,94 Volt, da er doch ziemlich gefordert 
wird (mc zeug + -21V erzeugung per maxim chip + 160x128 
displayversorgung (hintergrundbeleuchtung läuft über ein anderes 
netzteil)
3) muss oder kann ich irgendwie durch anschliessen von kapazitäten oder 
induktivitäten den messwert stabilisieren?

Vielen Dank für eure Hilfe

von Magnus Müller (Gast)


Lesenswert?

Fabian Knapp wrote:
> Bin momentan am rumrätseln, an was es liegen könnte:
>
> 1) der Versuchsaufbau auf dem Breadboard?

Versuchsaufbauten auf Breadboards sind in meinen Augen IMMER eine 
schwammige / störanfällige Angelegenheit.

> 2) vielleicht ist der überlastete spannungregler (7805) dran schuld, der
> hat nur noch eine Spannung von 4,94 Volt, da er doch ziemlich gefordert
> wird (mc zeug + -21V erzeugung per maxim chip + 160x128
> displayversorgung (hintergrundbeleuchtung läuft über ein anderes
> netzteil)

Ich kann mir nicht vorstellen, dass der 7805 mit dieser Last in 
schwitzen kommt.

> 3) muss oder kann ich irgendwie durch anschliessen von kapazitäten oder
> induktivitäten den messwert stabilisieren?

1.) AVCC wie im Datenblatt über LC-Glied mit VCC verbinden

2.) Wenn du nur ein sehr niederfrequentes Signal auswerten willst
    (und das ist im Falle eines von Hand betätigtem Poti definitiv
    der Fall) ist es sehr hilfreich, ein C zwischen ADC-Eingang und
    GND zu setzen.

3.) Ich wäre jetzt nicht überrascht, wenn du schreiben würdest, dass
    dein Poti ziemlich hochohmig und die Leitung zwischen Poti und
    µC verhältnismässig lang ist. Vermutlich fängst du dir dann damit
    nen Netzbrumm ein.

4.) Es macht auch Sinn, das Poti nicht zwischen VCC und GND sondern
    zwischen AVCC und GND zu hängen.

Gruß,
Magnetus

von Johannes A. (Gast)


Lesenswert?

Gegen Netzbrumm und andere Störungen (z.B. vom Handy oder 
Computermonitor) hilft auch eine Mittelung per Software.

Etwa in dieser Form:

mittelungsvariable = mittelungsvariable + ADC-wert
gemittelter-wert = mittelungsvariable / mittelungsfaktor
mittelungsvariable = mittelungsvariable - gemittelter-wert

"gemittelter-wert" ist dabei der Wert mit dem Du weiterrechnest.

Es ist übrigens praktisch, als mittelungsfaktor eine Wert 2^x zu nehmen
(also 8,16 oder 32), weil dann die Division einfach und schnell mit
Rechtsschieben erledigt werden kann.

Gruß Johannes

von Hansi L. (fabian87)


Lesenswert?

johannes könntest du mir das nochmal erklären? klingt interessant aber 
verstehen tue ich es nicht. welchen wert nimmt die mittelungsvariable an 
usw.

ich hatte bis jetzt nur die idee, denn wert einfach 2 oder 3 mal 
einzulesen und nur bei gleichheit das display zu aktualisieren

von Aufreger deluxe (Gast)


Lesenswert?

Ich würde das mit dem Mitteln erst mal vergessen. Steckbrett und genaues 
Messen ist eh schon so ne Sache. Atmel empfiehlt in den Datenblättern 
nicht umsonst die Beschaltung mit Cs und Spulen und getrennte 
Massefläche usw. Ließ dir das einfach mal durch. Der von Magnetus 
erwähnte Kondensator gegen Masse wirkt allerdings oft Wunder.

Ja und je hochohmiger deine ganze Anordnung ist, desto mehr Rauschen 
hast du.

von Hansi L. (fabian87)


Lesenswert?

also ich hab mal 100n zwischen adc0 und gnd geklemmt und es ändert sich 
nix.

von Johannes A. (Gast)


Lesenswert?

Ein klares Jein an Aufreger ;-)
Ok, ein Aufbau auf dem "Frühstücksbrettchen" ist immer so ne Sache,
aber gerade deswegen hab ich ja die Mittelung per Software ins
Gespräch gebracht. Denn sie läuft innerhalb des Controllers und
kann daher einen Breadboard-Aufbau wesentlich einfacher verifizieren
als es mit puren Hardware-Mitteln möglich ist. Ich weiß nicht, ob Du
schon mal eine Analogmessung mit einem STK zwecks Proof-Of-Concept 
pre-realisiert hast, ich weiß nur, dass ich da ohne den "Software-
Kondensator" hinter dem ADC-Eingang schon mehr als einmal baden
gegangen wäre.
Denn nichts anderes ist die Mittelung in der beschriebenen Form:
ein Integrator, wie ein C oder vielmehr ein RC-Glied am ADC-Eingang.

Zu Fabians Frage: Die mittelungsvariable nimmt maximal den höchsten
ADC-Wert mal mittelungsfaktor an, d.h. bei 10bit ADC-Wert und 16bit
für die mittelungsvariable kannst Du bis zu einem mittelungsfaktor
von 64 gehen. So hoch bin ich bisher aber nie gegangen, denn die Zeit
für die hinreichend genau Annäherung an die Auflösung der Auswertung
wird dann einfach zu groß - wenn Du einen programmierbaren
Taschenrechner hast, gib mal die genannte Formel ein und zähl die
Schritte, um auf Deine 1% Zielgenauigkeit zu kommen...

Gruß Johannes

von Hansi L. (fabian87)


Lesenswert?

habe das grade mal alles auf dem papier mit mf = 2 ausprobiert und das 
scheint echt keine schlechte idee zu sein... bei 32 werten sollte man 
doch schon nah dran kommen!

Danke wiedermal, solangsam hast du dir echt eine danksagung in meinem 
Projektbericht verdient :D

von Uwe (Gast)


Lesenswert?

Hi!
<(z.b. 64 und 65 %)
Nunja, wenn du keine Hysterese zwischen den Werten einbaust hast du 
immer eine harte Umschaltschwelle weil der ADC sich nicht entscheiden 
kann ob die letzte Stelle nun 1 oder 0 sein muss. Mittelwert ist schon 
eine recht hilfreiche Sache, aber selbst damit wirst du es vermutlich 
nicht wegbekommen. Leider kennen wir deine Software nicht und es sind 
alles Vermutungen. Schaue doch einfach mal nach wie bei dir 64/65% 
ermittelt werden. Ich tippe jedenfalls auf fehlende Hysterese.

Viel Erfolg, Uwe

von Johannes A. (Gast)


Lesenswert?

Ich denke, Du wirst bei 8 oder 16 Schritten völlig zufrieden sein :-)

Gruß Johannes

von Hansi L. (fabian87)


Lesenswert?

@Uwe da ich nicht weiss was eine Hyterese ist habe ich sie sicherlich 
nicht in meinem Programm drine :)
könnte mir das jmd erklären? Würde mich interessieren!

von Johannes A. (Gast)


Lesenswert?

Hysterese ist, wenn Du zum Umschalten von einem (Ausgabe)Wert auf einen 
anderen erst eine bestimmte Abweichung vom vorherigen Wert verlangst.

Also z.B. dass bei 87 in der Anzeige der angzeigte Wert nicht schon bei 
86,9 umspringt, sondern erst wenn er kleiner 86,5 wird, und entsprechend 
nach oben.

Das kann mitunter eine Hilfe sein, aber nur sofern die Sprünge zwischen 
zwei Messwerten klein genug sind - wozu wiederum regelmäßig eine 
Integration bzw. Mittelung nach meinem Vorschlag nötig ist :-)

Gruß Johannes





von Karl H. (kbuchegg)


Lesenswert?

> da ich nicht weiss was eine Hyterese

Stell dir folgendes vor:
Du hast eine Heizung mit einem Thermostat. Du möchtest jetzt
25 Grad Raumtemperatur erreichen. Dazu programmierst du deine
Steuerung so, dass sie unterhalb von 25 Grad die Heizung einschaltet
und bei 25 Grad wieder aus. Damit könnte dir folgendes
passieren: Die Temp steigt auf 25.00001 Grad womit der Brenner
ausschaltet. Die Temp sinkt auf 25 Grad. Der Brenner schaltet wieder
ein. Temp: 25.00001 -> Brenner aus. Im Endeffekt ist der Brenner
nur am Ein/Ausschalten.

Daher macht man eine Hysterese hinein: Ausgeschaltet wird erst bei
26 Grad, eingeschaltet erst wenn die Temp im sinken wieder 24 Grad
erreicht hat. Im Mittel ergibt sich dann auch wieder 25 Grad.
Allerdings ist der Brenner jetzt viel ruhiger :-)

von Hansi L. (fabian87)


Lesenswert?

Dann hab ich sowas im groben vorhin schon zufällig programmiert:

Ich habe mir überlegt, wie ich die Sprünge von zwei Prozentwerten 
unterbinden kann und habe dann programmiert, dass das Display erst was 
neues anzeigt, sobald sich mindestens 2% verändert haben. Nun habe ich 
keine ungewollten Prozentsprünge mehr drin :)
Bin jetzt am überlegen, ob ich das ganze nun auf den gemessenen AD Wert 
schon anwenden soll und nicht auf den prozentwert, der ja dann mit 2% 
unterschied einen recht großen Schritt drinne hat. Vielleicht probiere 
ich es mal mit dem  gemessenen 10 bit wert, indem ich angebe, dass er 
nur weiter mit rechnen soll , wenn er sich um mindestens 10 digits (ca 
1%) ändert! Mal sehen obs funktioniert!

von Johannes A. (Gast)


Lesenswert?

Damit bist Du erstmal so auf dem richtigen Dampfer!

Kann jetzt bloss noch sein, dass der Wert vom ADC noch zu sehr 
"flattert".

Gruß Johannes

von Pieter (Gast)


Lesenswert?

moin moin,

bei soetwas arbeite ich immer mit einem gleitenden Mittelwert.
Z.B.:

MittelWert = (MittelWert *3 + ADU-Wert) / 4

Ein neuer ADU-Wert geht also nur mit 25% in den Mittelwert ein.

mfg
Pieter

von Hansi L. (fabian87)


Lesenswert?

@Pieter auch keine schlechte idee :) werden ich eventuell mal 
ausprobieren :)

von Hansi L. (fabian87)


Lesenswert?

Hi
habe noch ein Fehler im Code den ich nicht finden kann :(
kann da vll. mal schnell jmd. drüber sehen?

ADC_DIFFERENCE ist die von mir definierte Abweichung, die überschritten 
werden muss, um das Display zu aktualisieren (im Beispiel habe ich 10 
verwendet). es sieht so aus als würde sich der MC die ganze Zeit 
reseten?!
bin echt überfragt :(
Anfangen tut die funktion mit PERCENT:
sie öffnet sich, sobald in der hauptschleife ein neuer ADC wert 
abgefragt wurde und die wandlung abgeschlossen ist.

PERCENT_2:
  sub  r23,r16        ; r23 = r23 - r16
  sbc  r24,r17        ; r24 = r24 - r17 - c
  cpi  r24,1        ; compare r24 - 1
  brsh  PERCENT_4      ; jump if r24 >= 1
  cpi  r23,ADC_DIFFERENCE  ; compare r23 -ADC_DIFFERENCE
  brlo  ADC_END      ; jump if r23 < ADC_DIFFERENCE
  rjmp  PERCENT_4
PERCENT_3:
  sub  r16,r23        ; r16 = r16 - r23
  sbc  r17,r24        ; r17 = r17 - r24 - c
  cpi  r17,1                    ; compare r17 - 1
  brsh  PERCENT_4      ; jump if r17 >= 1
  cpi  r16,ADC_DIFFERENCE  ; compare r16 - ADC_DIFFERENCE
  brlo  ADC_END      ; jump if r23 < ADC_DIFFERENCE
  rjmp   PERCENT_4

PERCENT:
  clr r3
  clr r1
  in   r16,ADCL      ; ADC lowbyte
     in   r17,ADCH      ; ADC highbyte
  push  r16
  push  r17
  cp  r16,r23      ; compare r16 - r23
  cpc  r17,r24      ; compare r17 - r24 - C
  breq  ADC_END      ; jump if new ADC = old ADC
  brlt  PERCENT_2    ; jump if new ADC < old ADC
  brge  PERCENT_3          ; jump if new ADC > old ADC
PERCENT_4:
  pop  r17
  pop  r16
  mov  r23,r16
  mov  r24,r17
  subi   r16,-1
  sbci   r17,-1

;Dann mit 100 multiplizieren, wobei ein Wert >16bit
;herauskommen kann (R2-R4):

    ldi    r18,100
    mul    r16, r18      ; adcl * 100
    movw   r2, r0
    clr    r4
    mul    r17, r18      ; adch * 100
    add    r3, r0
    adc    r4, r1

;Nun teile ich durch Verschieben durch 256...

    mov    r16,r3        ; r4:r3:r2 / 256
    mov    r17,r4

;...addiere den entsprechenden Wert für die Rundung...

    subi   r16,0xFE      ; + (512/256) entspr. -2
    sbci   r17,0xFF

;...und teile per Rechtschieben noch einmal durch 4:

    lsr    r17           ; / (1024/256)
    ror    r16           ; entspr. r17:r16>>2
    lsr    r17
    ror    r16
    mov  r22,r16

ADC_END:
  pop  r17
  pop  r16
  ret

ADC_END_4:
ret

von Johann K. (hansi)


Lesenswert?

Wenn du über Percent_4 die Funktion abschließt hast du einmal PUSH aber
zweimal POP.
Stelle ADC_END_4 einfach vor ADC_END und es geht.

von Hansi L. (fabian87)


Lesenswert?

oh tatsächlich vielen dank!

Hatte sogar zuerst ADC_END_4 vor ADC_END habe mir dann nachts irgendwann 
gedacht, dass es andersrum doch eleganter wäre... soviel zum denken ;)

von Johannes A. (Gast)


Lesenswert?

Auf eines muss ich unbedingt noch hinweisen, weil ich in meiner 
AVR-Anfangszeit selber mal darauf hereingefallen bin. (Der AVR
war mein erster 8Bitter mit dieser "bösen Falle".)

Du hast zum Verzweigen nach PERCENT_2 und _3 die Befehle brlt und
brge benutzt, statt wie an anderer Stelle, brlo und brsh.

Das macht hier zwar nichts, denn die hier verglichen ADC-Werte sind
immer klein genug, dass der Unterschied nicht auffällt.
Nichtsdestotrotz sind brlt/brge für vorzeichenbehaftete Vergleiche,
und können mit vorzeichenlosen Zahlen unverhofft "sehr seltsames"
Verhalten zeigen, wenn bei einem der beiden verglichenen Werte
das höchswertige Bit gesetzt ist, was im vorzeichenbehafteten
Zahlenmodell negative Werte bedeutet.

Beipielvergleiche (mit 8bit Zahlen):

hex-werte    ohne Vorz.   mit Vorz.   brsh/lo  brge/lt
0x50<->0x7F  80<->127     +80<->+127     lo       lt
0x7F<->0x50  127<->80     +127<->+80     sh       ge
0x50<->0xA0  80<->160     +80<->-96      lo       ge  !!
0xA0<->0x50  160<->80     -96<->+80      sh       lt  !!
0xA0<->0xFF  160<->255    -96<->-1       lo       lt
0xFF<->0xA0  255<->160    -1<->-96       sh       ge


Nochmal zu Deinem Code denke ich, dass die beiden clr-Befehle am
Anfang von PERCENT wohl entfallen können.

Gruß Johannes

von Hansi L. (fabian87)


Lesenswert?

Juche...

habe die extremen ungenauigkeiten mit keiner programmiertechnischen 
methode wirklich rausbekommen. Habe jetzt einfach mal an den poti 3 
kurze dickere und besser abgeschirmte kabel gelötet und habe gnd und 5v 
jeweils direkt nachm 7805 abgegriffen und den poti nen paar cm von den 
anderem zeug weg gemacht. Habe jetzt zusätzlich noch was programmiert, 
dass 16 mal den adc wert misst und davon den durchschnitt errechnet. 
Dieser Durchschnittswert wird nur als neuer ADC Wert übernommen, wenn er 
mindestens mit einer ADC_DIFFERENCE von 10  digit (unter einem Prozent) 
(andere Werte probiere ich noch) vom aktuell dargestellten ADC Wert sich 
unterscheidet. Und siehe da:
Ich habe ÜBERHAUPT KEINE Sprünge mehr drin =)
bin jetzt voll happy, jetzt weiss ich endlich mit einer ziemlichen 
sicherheit das es funktionieren wird wenn ich die platine geätzt hab :)

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.