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
Öhhh, die ATMegas haben nur EINEN AD-Wandler, der NACHEINENDER mehrere Kanäle abtasten kann... Was hast Du da "beschaltet" bzw. programmiert?
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.
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.
andererseits: warum sollte man einen Eingang samplen, an dem sowieso nichts dran ist bzw. der auf Masse liegt??
- 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?
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... ...
>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.
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. ...
Na klar, die Pausen sollte man schon nutzen. War nicht im Sinne einer Warteschleife gemeint ;)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.