Moin, habe mir eine kleine Schaltung entworfen (siehe Schaltplan). Ich will eine Spannung, die von einem Absolut-Winkel-Sensor ausgegeben wird und zwischen 0 und 5 V liegt, digitalisieren. Den AREF Pin habe ich mit einem 100nF Kondensator gegen Ground beschaltet. An AVCC liegt eine (einigermaßen) geglättete 5V Spannung an (auch gemessen!). Wenn ich durch die Reference Selection Bits die interne Spannung von 2,5V einstelle, liegt diese auch an AREF an und die Wandlung klappt gut (natürlich nur bis 2,5V). Wähle ich nun AVCC als VREF aus, liegt an AREF seltsamerweise keine Spannung an und der ausgegebene Wert ist somit immer 1023. Was ich schon gecheckt habe: - uc getauscht, da ich vermutet habe, das die Spannung intern nicht umgeschaltete wird -> gleiches Ergebnis - Stromfluß durch die Schaltung liegt bei beiden Modi bei ca. 124 mA Könnte es an dem Kondensator an AREF liegen? Kann den auf der Schaltung nicht messen und auslöten ist sehr fummelig. Ach ja hier sind noch die verwendeten c-Funktionen für den ADC: /* initialize ADC with a frequency of f_ck/128 in single conversion mode */ void adc_init(void) { ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); // AVCC is reference voltage, external capacitor on AREF ADMUX = (0<<REFS1) | (1<REFS0) |(1<<MUX2) | (1<<MUX1) | (1<<MUX0); /* Dummy-Readout of the first value */ ADCSRA |= (1<<ADSC); while (ADCSRA & (1<<ADSC)) //wait for convertion to complete { ; } } float read_channel(unsigned int no_samples) { double result = 0; unsigned int i; for (i=0; i < no_samples; i++) { ADCSRA |= (1<<ADSC); //one conversion while (ADCSRA & (1<<ADSC)) //wait for conversion to complete { ; } result += ADC; } result /= no_samples; return (float) result; }
hallo, vermute du denkst das die 5V Spannung intern erzeugt wird, dem ist aber nicht so !!!! deswegen misst du auch keine 5v, sondern 0V. du musst 5v schon an AREF anlegen, genau wie an AVCC, wenn du mit 5V arbeiten willst. gruss fubu
>du musst 5v schon an AREF anlegen, genau wie an AVCC, wenn du mit 5V >arbeiten willst. Nein, muß man nicht.
@fubu1000: Nein! Genau das muss (und soll) man nicht machen! Bei allen aktuellen AVRs mit A/D-Wandler ist AVCC als Referenz intern einstellbar! Niemals AREF extern mit AVCC verbinden!!
Tja, ich hätte ja getippt, dass Du versehentlich an dem Analog-Eingang nen Pull-Up aktiviert haben könntest. Aber da es ja anscheinend mit der 2,5V-Referenz klappt, scheidet das ja aus... Was anderes fällt mir so auf die Schnelle auch nicht ein...
Wo wird das ADC-DatenReg High and Low gelesen ??? 10 Bits breit Messen ??? bezogen auf V.Ref X-MessBits Milivolt ADC Messbits.
hallo, nochmal datenblatt angeschaut habt recht "muss" man net anschliessen AREF an 5V !!!! @ johnny warum sol man das nit machen 5V an AREF bei mir klappts so super bei nem ATMEGA8. gruss fubu
>warum sol man das nit machen 5V an AREF bei mir klappts so >super bei nem ATMEGA8. Das ist dann eine externe Einspeisung. Da könntest du auch 4,096V anlegen...
> warum sol man das nit machen 5V an AREF
Weil man sich dadurch jeglicher Möglichkeiten beraubt, eine andere
Referenz als AVCC zu benutzen und weil es, wenn man intern ein Bit
falsch setzt und eine andere Referenz auswählt, einen Kurzschluss gibt.
AVCC an AREF macht nur Sinn bei den alten AT90Sxxxx-AVRs, die noch
keine internen Einstellmöglichkeiten hatten.
@Daniel: Den 'Dummy read' kannst du dir schenken. Laut Datenblatt ist zu beachten dass, wenn vor einer Messung der MUX umgeschaltet wurde, eine gewisse Zeit zu warten ist. Empirisch ermittelt habe ich min. 40µs herausgefunden. Wenn die Betriebsart umgeschaltet wird musst du min. 120µs Pause bis zur Messung machen, sonst kommt nur Schrott 'raus! So wie's in deinem Codeschnipsel ist vergehen da mit Sicherheit keine 40µs!
Hallo, ich dachte, es reicht den ADC anzuhalten, z.B. den MUX umzustellen und dann eine neue Messung zu starten und zu warten, bis der ADC fertig ist. Soweit mir bekannt ist, sagt Atmel nur, dass beim Wechsel eines differentiellen Eingangs oder einmal nach dem Wechsel der Referenz 125µsec Wartezeit eingehalten werden sollen. Da ich beim Umschalten der ADC-Eingänge (single-ended nicht differentieller Modus) auch schon Probleme hatte und dieses auch nur durch Warten lösen konnte. Und zwar langes warten: wenn ich als Teiler 128 bei 16MHz Systemtakt wähle, sollte ich als Umsetzzeit ca. 104µsec bekommen, aber gesehen habe ich, dass ich einige Messungen wegwerfen musste, bis man gesehen hat, dass der Kanal auch wirklich gewechselt wurde. Mein Vorgehen: ADCSR=0x07; // ADC anhaltzen ADMUX=0x42; // MUX neu setzen ADCSR=0xc7; // ADC starten while (ADSC==1); // warten bis ADC fertig adc_in=ADCL; // Ergebnis lesen adc_in+=ADCH << 8; ADCSR = 0xc7; //ADC neustarten while (ADSC==1); adc_in=ADCL; adc_in+=ADCH << 8; Damit müsste ich ja nach dem Kanal Wechsel zwei Umsetzungen angestossen haben und ein evtl. falsches (erstes) Resultat verworfen haben. Leider habe ich gesehen, dass ich bis zu 10 Messungen wegwerfen musste, bis ich ein plausibles Ergebnis hatte. Irgendwie verstehe ch es nicht - wo mach ich da den Fehler? Tschüss Ray
Atmel schweigt sich darüber aus. Jedenfalls steht nix im Datenblatt darüber. Irgendwo (weiß leider nicht mehr wo) habe ich mal gelesen dass der MUX 60µs Einschwingzeit hätte. Durch Versuche stellte ich fest, dass er kleiner 40µs tatsächlich Mist gemessen hat. Also nach der Umschaltung min. 40µs warten, dann klappt's!
Ich nochmal, hier meine ADC-Funktion: double ADC_conversion(unsigned char mux, unsigned char MW) // Spannung messen (single ended) { ADMUX = mux; // Multiplexer-Modus einstellen _delay_us(40); // Pause bis Multiplexer eingestellt ist double Messwert = 0; unsigned int ADC_temp; unsigned char i = 1; do { ADCSRA |= (1<<ADSC); // 'single conversion' einleiten while(!(ADCSRA & 0x10)); // auf ende der Wandlung warten, ADIF Flag '1' ADC_temp = ADCL; // ADCL Register lesen ADC_temp += (ADCH << 8); // ADCH Register lesen Messwert += ADC_temp; // Ergebnisse der Messungen addieren i++; // Schleifenzähler erhöhen } while (i <= MW); // MW Messungen für bessere Genauigkeit Messwert = Messwert/MW; // Mittelwert der globalen Variable zuweisen return (Messwert); }
Hallo, vielen Dank - aber ich habe glaube ich meinen Fehler jetzt gesehen - anscheinend muss man Sachen immer erst anderen Leuten zeigen, dass man in seinem eigen Code die Fehler sieht. Der Vergleich auf while (ADSC==1); ist natürlich absoluter Quatsch, weil ADSC ja eine Konstante (ich denke 6) ist, damit warte ich natürlich nicht bis der ADC fertig ist, sondern laufe sofort weiter, daher muss ich auch immer soviele Ergebnisse wegschmeissen - weil der ADC noch gar nichts neues geliefert hat (schäm). Danke Ray
Hab den Fehler gefunden: ADMUX = (0<<REFS1) | (1<REFS0) |(1<<MUX2) | (1<<MUX1) | (1<<MUX0); Damit wird REFS0 natürlich nicht gesetzt. Saublöd, aber irgendwie auch schwer zu entdecken, da es ja keinen Compilerfehler gibt.
>Damit wird REFS0 natürlich nicht gesetzt. Saublöd, aber irgendwie auch >schwer zu entdecken, da es ja keinen Compilerfehler gibt. REFS0 wird gesetzt, REFS1 aber nicht...
nee. quatsch. REFS1 wird aufgrund des einfachen Pfeils nicht gesetzt.
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.