mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Atmega32: ADC Ergebnis mit AVCC als VREF immer 1023


Autor: Daniel Meyer (dandansen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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;
}

Autor: Daniel Meyer (dandansen)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hier ist der Anhang.

Autor: fubu1000 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>du musst 5v schon an AREF anlegen, genau wie an AVCC, wenn du mit 5V
>arbeiten willst.

Nein, muß man nicht.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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!!

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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...

Autor: Holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wo wird das ADC-DatenReg High and Low gelesen ???
10 Bits breit Messen ???
bezogen auf V.Ref
X-MessBits Milivolt
ADC Messbits.

Autor: fubu1000 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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...

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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.

Autor: Sonic (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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!

Autor: Ray (Gast) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Sonic (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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!

Autor: Sonic (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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);
}

Autor: Ray (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Dan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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...

Autor: Dan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
meinte ich auch.

Autor: Dan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
nee. quatsch. REFS1 wird aufgrund des einfachen Pfeils nicht gesetzt.

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stimmt... sollte ja 1<<REFS1 heissen.

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.