mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik AD-Wandler gibt krumme Werte


Autor: Tim (Gast)
Datum:
Angehängte Dateien:
  • AD.txt (1,59 KB, 294 Downloads)

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich beschäftige mich noch nicht lange mit Mikrocontrollern und bin 
gerade dabei das GCC-Tutorial durchzuarbeiten. Meine Hardware ist ein 
STK500, ein Atmega48 und ein JTAGICEmkII. Als Software benutze ich das 
AVR-Studio.

Nun habe ich mich mit den AD-Wandlern des Atmega beschäftige. Dazu habe 
ich zwei Stück initialisiert und versorge sie mit einer spannung 
zwischen 0 und 5V.

Nun zu meinem Problem. Solange ich beide AD-wandler mit einer Spannung 
versorge, klappt alles prima. Der AD-Wandler erzeugt mir Werte zwischen 
0 und 255 die auch im Verhältnis zur Spannung zu stimmen scheinen. Nur 
sobald ich einen AD-wandler unbeschaltet lasse, gibt dieser mir krumme 
Werte aus. Der beschaltete verhält sich aber ganz normal. Müsste der 
unbeschaltete AD-wandler nicht 0 zurückgeben?

Den Code hab ich auch mal beigefügt. Vielleicht kennt einer das Problem 
und kann mir helfen. Vielen Dank.

Gruß Tim

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Öhhh, die ATMegas haben nur EINEN AD-Wandler, der NACHEINENDER 
mehrere Kanäle abtasten kann... Was hast Du da "beschaltet" bzw. 
programmiert?

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
BTW: Wenn ein Analog-Eingang offen (also unbeschaltet) ist, kann da so 
ziemlich alles rauskommen. Null nur dann, wenn man den Eingang direkt 
auf Masse legt.

Autor: Alex Bürgel (Firma: Ucore Fotografie www.ucore.de) (alex22) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
richtig, niemals einen Eingangs-Pin abfragen, an den gar nichts dran 
angeschlossen ist. Da kommt nur murks bei rum. Verbinde deinen 
"nichtangeschlossenen" AD-Port mal über einen z.B. 1k Widerstand mit 
GND, dann wird er dir auch "0" ausgeben.

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
andererseits: warum sollte man einen Eingang samplen, an dem sowieso 
nichts dran ist bzw. der auf Masse liegt??

Autor: Power (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
- Immer an die Pause nach dem Umschalten des MUX auf einen anderen Kanal 
(40µs) oder eine andere Betriebsart (120µs) denken.
- Teiler für den ADC richtig eingestellt (125kHz)?
- Pullups an den Messeingängen abgeschaltet?
- Referenzspannung richtig programmiert (intern/extern)?
- Bei intern: KerKo an Uref gegen Masse drin?
- Bei extern: Uref > 2V?

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
crazy horse wrote:
> andererseits: warum sollte man einen Eingang samplen, an dem sowieso
> nichts dran ist bzw. der auf Masse liegt??

Vermutlich, weil man ein betriebssystemähnliches Universalprogramm 
schreiben will, dass auf alle Eventualitäten vorbereitet ist. ;-)

Spaß beiseite...

@Tim:
Ich habe mal in den Code reingeschaut, bin aber kein C-Freak, also aus 
Sicht des Assembler nutzenden Bastlers. Dabei fiel mir auf:

- Der ADC wird auf Quelle und Referenzquelle eingestellt, gestartet
  und per Busy-Poll gewartet, dass er fertig wird. Das ist zwar nicht
  falsch, das würde ich aber nicht tun. Denn Busy-Poll ver"wartet"
  wertvolle Rechenzeit, erzeugt Müll (Störimpulse) und bringt rein gar
  nix. Stattdessen würde ich den ADC im Hintergrund laufen lassen und
  entweder per ADC-Int oder (ganz nebenbei) per Timer-Int auslesen. Das
  Aktivieren des Sleep während der Controller auf den nächsten Int
  wartet, senkt auch den Müll (CPU-Takt ist ja im Sleep aus).

- Die erste Messung wird verworfen. Das ist gut so, denn unter 
bestimmten
  Bedingungen ist die erste Messung nach der Quellenumschaltung ja auch
  fehlerhaft. Dann erfolgen 10 Messungen, deren Messwerte addiert 
werden,
  um sie dann durch 10 zu dividieren. Warum um Gottes Willen 10???
  Hast Du mal drüber nachgedacht, wie sich ein AVR strecken muss, eine
  Division durch 10 zu rechnen? Mit 8, 16 oder gar 256 Messungen könnte
  der AVR das per Shift bzw. durch Verwerfen des Low-Bytes realisieren,
  aber 10 ist einfach nicht zu Ende gedacht. Auch als C-Programmierer
  sollte man daran denken, dass der AVR kein C kann, sondern nur ASM 
bzw.
  Maschinencode.

Wenn ich mehrere ADC-Werte brauche, dann lese ich diese reiherum ein. 
Meist lasse ich den ADC frei laufen und frage den Wert im 
Timer-Interrupt ab. Dieser ist sowiso vorhanden und kann das nebenbei 
miterledigen. Dabei wird ADC-Tempo und Timer-Intervall so aufeinander 
abgestimmt, dass pro Timer-Intervall mindestens zwei neue ADC-Wandlungen 
erfolgt sind. Das sorgt dafür, dass die erste Wandlung ignoriert wird.
Im Timer-Interrupt lese ich nun erstmal ADMUX aus, ermittle daraus die 
Quelle, lese dann ADC aus und sichere den Wert in einem Datenfeld 
(Quelle als Index), incrementiere die Quelle und schreibe sie nach ADMUX 
zurück. Nun kann sich der Controller in der Mainloop anderen Dingen 
widmen, der ADC läuft im Hintergrund, er wandelt einmal, zweimal, .. und 
irgendwann schlägt der Timer zu und liest ihn aus.

Wird das letzte Fünkchen Genauigkeit benötigt, dann ist der ADC nur 
während Sleep im Mode ADC-Noise-Reduction zu betreiben, das ist aber 
eine andere Baustelle, das erfordert etwas umsichtigeres Herangehen, da 
der Timer-Takt solange deaktiviert ist und daher die Timer-Intervalle 
daran angepasst werden müssen...

...

Autor: Power (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Die erste Messung wird verworfen. Das ist gut so, denn unter
>bestimmten Bedingungen ist die erste Messung nach der Quellenumschaltung
>ja auch fehlerhaft.

Diese Bedingungen meinte ich weiter oben mit Pause von min. 40µs nach 
der Umschaltung des MUX. Mit Pause vor der Messung gibt's auch keine 
Fehler mehr.

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Power wrote:
>>Die erste Messung wird verworfen. Das ist gut so, denn unter
>>bestimmten Bedingungen ist die erste Messung nach der Quellenumschaltung
>>ja auch fehlerhaft.
>
> Diese Bedingungen meinte ich weiter oben mit Pause von min. 40µs nach
> der Umschaltung des MUX. Mit Pause vor der Messung gibt's auch keine
> Fehler mehr.

Ich habe auch keine Messfehler, nutze die "Pausen" aber für Aufgaben der 
Mainloop, anstatt sie für Warteschleifen und Busywait zu vertrödeln. Und 
wenn die Mainloop "arbeitslos" wird, also alle anstehenden Jobs erledigt 
hat, dann wird Sleep aufgerufen, womit der nächste Interrupt (meist ein 
Timer) stabile Bedingungen vorfindet und immer die gleiche Response-Zeit 
benötigt.

...

Autor: Power (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Na klar, die Pausen sollte man schon nutzen. War nicht im Sinne einer 
Warteschleife gemeint ;)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.