Forum: Compiler & IDEs Probleme mit AD Wandler am AT90CAN128


von Stephan (Gast)


Lesenswert?

Morgen Forumsgemeinde,

ich habe ein Problem mit dem AD-Wandler an meinem AT90CAN128. Ich habe 
den Quellcode aus dem AVR-GCC Tutorial genommen und anversich nicht 
verändert, bis auf eine Abfrage welche Reversenzspannung genommen werden 
soll.

Hier kurz den Quellcode:
1
uint16_t ReadChannel(uint8_t mux, uint8_t referenz)
2
{
3
  uint8_t i;
4
  uint16_t result;
5
6
  ADMUX = mux;                      // Kanal waehlen
7
8
  if(referenz == 0)
9
    ADMUX |= (0<<REFS1) | (1<<REFS0) | (0 << ADLAR); //externe Referenzspannung(5V) nutzen
10
  if(referenz == 1)
11
    ADMUX |= (1<<REFS1) | (1<<REFS0) | (0<<ADLAR);  //interene Referenzspannung (2,56V) nutzen
12
13
  ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);    // Frequenzvorteiler
14
                               // setzen auf 128 (1) und ADC aktivieren (1)
15
16
  /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
17
     also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
18
  ADCSRA |= (1<<ADSC);              // eine ADC-Wandlung
19
  while ( ADCSRA & (1<<ADSC) ) {
20
     ;     // auf Abschluss der Konvertierung warten
21
  }
22
  result = ADCW;  // ADCW muss einmal gelesen werden,
23
                  // sonst wird Ergebnis der nächsten Wandlung
24
                  // nicht übernommen.
25
26
  /* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
27
  result = 0;
28
  for( i=0; i<4; i++ )
29
  {
30
    ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
31
    while ( ADCSRA & (1<<ADSC) ) {
32
      ;   // auf Abschluss der Konvertierung warten
33
    }
34
    result += ADCW;        // Wandlungsergebnisse aufaddieren
35
  }
36
  ADCSRA &= ~(1<<ADEN);             // ADC deaktivieren (2)
37
38
  result /= 4;                     // Summe durch vier teilen = arithm. Mittelwert
39
40
  return result;
41
}

Wie ihr seht frage ich vor dem beschreiben des ADMUX-Registers die 
Variable "referenz" ab um die gewünschte Referenzspannung in das 
Register zu programmieren.
In meiner while-Schleife in meiner Main-Funktion rufe ich direkt 3 mal 
hintereinander die "ReadChannel"-Funktion auf, um die Channel 0 bis 2 
wandeln zu lassen.
1
while(1)
2
{
3
     .
4
     .
5
     .
6
7
     ergebnis1 = ReadChannel(0, ad_wandler1[1]);
8
     ergebnis2 = ReadChannel(1, ad_wandler2[1]);
9
     ergebnis3 = ReadChannel(2, ad_wandler3[1]);
10
     
11
     .
12
     .
13
     .
14
}
Das funktioniert auch soweit nur wenn ich z.B. dem Channel 0 die 2,56 
Volt  interneReferenzspannung zuweise und den Channeln 1 und 2 die 5 
Volt externe Referenzspannung zuweise bekomme ich kein vernünfiges 
Ergebnis für die einzelnen Wandlungen.
Variable "result" vom Channel 0 hat bei einer Spannung von 1 Volt bei 
der intern Referenzspannung einen Wert von 265 sollte aber rechnerisch 
bei 400 liegen.
Variable "result" der Channel 1 und 2 hat einen Wert von 222 bei einer 
realen Referenzspannung von 4,6 Volt.

Wenn ich allen 3 Channeln die gleicher Referenzspannung zuweise, egal 
welche, passen alle 3 Ergebnise.

Hat jemand von euch eine Idee wo ich den Fehler habe? Kann vieleich der 
AD-Wandler nicht schnell genug seine Referenzspannung umschalten?

Ich dank euch allen wie immer für eure Hilfe.

Gruß
Stephan

von ADC (Gast)


Lesenswert?

Das Datenblatt sagt:

21.5 Changing Channel or Reference Selection
...
Note that the conversion starts on the following rising ADC clock edge 
after
ADSC is written. The user is thus advised not to write new channel or 
reference selection values
to ADMUX until one ADC clock cycle after ADSC is written.

Vielleicht solltest du nach dem Umschalten ein bisschen warten oder den 
ersten ausgelesenen Wert verwerfen...

von ADC (Gast)


Lesenswert?

Ich sehe gerade, dass du das ja machst.
Probier es doch mal, wenn du ihm etwas mehr Zeit gibst. (zB zwei oder 
drei Dummyreads)

von Stephan (Gast)


Lesenswert?

Danke für die schnelle Antwort. Werde ich mal versuchen.

von Stephan (Gast)


Lesenswert?

Also wenn ich 10 Dummyreads mach dann funktioniert es, aber des ist doch 
eigendlich auch nicht Sinn der Sache, oder?

von Andreas R. (rebirama)


Lesenswert?

Ich vermute das ist ein elektrisches, kein Softwarepoblem.

Du schaltest zwischen interne Ref und AVCC als Ref um.
Beide Referenzspannungen werden mit dem Kondensator an AREF gepuffert.
-> Du musst warten, bis der Kondensator umgeladen wurde.
(21.5.2 im Datenblatt)

-> Kondensator kleiner machen oder Wartezeit nach dem Referenzwechsel 
erhöhen.

von Stephan (Gast)


Lesenswert?

Das mit der Ladezeit des Kondensators klingt logisch. Ich lass einfach 
den AD-Wandler die Dummyreads machen.

Dank euch mal wieder.

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.