AREF schwingt sägezahnförmig

Gast #1730799
Lesenswert?

Hallo,

ich habe bei einem ATmega128L (3.3V) probleme mit dem ADC. Ich bekomme 
keine vernünftigen Werte. Ich messe an ADC0 und ADC1. Ich bekomme 
jeweils einen Wert um die 350 raus (int16t_t-Wert), egal welche Spannung 
am den Eingängen anliegt. Ich verwende den Code aus dem 
AVR-ggc-Tutorial.
1
uint16_t ReadChannel(uint8_t mux)
2
{
3
  uint8_t i;
4
  uint16_t result;
5
 
6
  ADMUX = mux;                      // Kanal waehlen
7
  ADMUX |= (1<<REFS1) | (1<<REFS0); // interne Referenzspannung nutzen
8
 
9
  ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);    // Frequenzvorteiler 
10
                               // setzen auf 8 (1) und ADC aktivieren (1)
11
 
12
  /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
13
     also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
14
  ADCSRA |= (1<<ADSC);              // eine ADC-Wandlung 
15
  while ( ADCSRA & (1<<ADSC) ) {
16
     ;     // auf Abschluss der Konvertierung warten 
17
  }
18
  result = ADCW;  // ADCW muss einmal gelesen werden,
19
                  // sonst wird Ergebnis der nächsten Wandlung
20
                  // nicht übernommen.
21
 
22
  /* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
23
  result = 0; 
24
  for( i=0; i<4; i++ )
25
  {
26
    ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
27
    while ( ADCSRA & (1<<ADSC) ) {
28
      ;   // auf Abschluss der Konvertierung warten
29
    }
30
    result += ADCW;        // Wandlungsergebnisse aufaddieren
31
  }
32
  ADCSRA &= ~(1<<ADEN);             // ADC deaktivieren (2)
33
 
34
  result /= 4;                     // Summe durch vier teilen = arithm. Mittelwert
35
 
36
  return result;
37
}
38

39

40
temp1 = ReadChannel(0);
41
temp2 = ReadChannel(1);


Ich habe mal mit dem Oszi die Pins durchgemessen und festgestellt, das 
AREF sägezahnförmig zwischen 1 V und 2,5 V schwingt. Frequenz ca. 1Hz.
Ist das normal?

Es kommt vor, das an den Eingängen manchmal neg. Spannung von ca. -4V 
anliegen. Ich habe die Eingänge mit 4k7 Widerständen abgesichert. Könnte 
der ADC beschädeigt worden sein.

Jemand eine Idee wo mein Problem liegen könnte?


Gruß
Georg
Angehängte Dateien:
Gast #1730816
Lesenswert?

Negative eingangsspannungen mögen die nunmal garnich gerne..
wenn dann musst du deine 4k7 nehmen und danach mit dioden (am besten 
shotky) gegen GND absichern. das mag er womöglich noch vertragen
Gast #1730845
Lesenswert?

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

Hallo,

wenn der Controller nicht Strom sparen muss, lässt man den ADC nach der 
Initialisierung dauerhaft eingeschaltet und triggert ihn bei Bedarf 
(nach Auswahl des Kanals). Das spart das Dummy-Read des Wertes (ausser 
beim ersten Einschalten des ADC).

Initialisierung des ADC wäre dann:

>> ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);    // Frequenzvorteiler

und wird zu Beginn des Programms aufgerufen.
Der Rest läuft dann in der Routine ab, aber ohne die Zeilen

> ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);
> ADCSRA &= ~(1<<ADEN);             // ADC deaktivieren
Gast #1730889
Lesenswert?

Bekomme immer noch Werte zwischen 350 und 380, egal welche Spannungen 
anliegen.

Gerade liegen vor dem 4k7 -3V an, nach dem 4k7 sind es noch -0.6V.

Wahrscheinlich ist der ADC auf grund der neg. Spannungen defekt?!

Hier im Forum wird aber öfter geschrieben, dass einen Absicherung nur 
mit einem Widerstand reicht (in Verbindung mit den internen Dioden). Ist 
das nicht zutreffend?
Gast #1730895
Lesenswert?

Die -0,6 Volt entstehen durch den Spannungsteiler:

-3Volt  Widerstand   -0,6Volt   Diode |>|  Masse

Daher passt das schon, du musst nur aufpassen, dass der Strom durch die 
Diode nicht größer als 1 mA wird, sonst ist sie kaputt und dein Eingang 
gleich mit.
Gast #1730901
Lesenswert?

jepp ... sollte ja nicht passieren.

(-4V + 0.6V) / 4k7 = 0.7 mA   (-4V ist der max. auftretende Wert).


Sollte also im grünen Bereich sein.


Gibt es eine Möglichkeit festzustellen, ob der ADC definitiv defekt ist 
(z.b. messtechnisch)?
Gast #1730902
Lesenswert?

> Bekomme immer noch Werte zwischen 350 und 380

Sind diese Werte denn konstant, oder schwanken sie?

Versuche es mal zum Testen mit AVcc als Referenz (REFS1 = 0, REFS0 = 1). 
Ändert sich der A/D Wert?
Gast #1730909
Lesenswert?

Georg schrieb:
> Gibt es eine Möglichkeit festzustellen, ob der ADC definitiv defekt ist
> (z.b. messtechnisch)?

Die neueren ADCs können über ADMUX mit einem internen Vergleichswert 
belegt werden, z.B. 1,2 Volt.
Bei diesen Vergleichwerten weist du ja dann, was ungefähr rauskommen 
muss. Stimmts überein, funktioniert der AD-Umsetzer noch, dann liegen 
die Probleme entweder beim Verdrahten oder beim Sensor.
Gast #1730915
Lesenswert?

> Die neueren ADCs können über ADMUX mit einem internen Vergleichswert
> belegt werden, z.B. 1,2 Volt.

Beim Mega128 ist dies:

MUX4..0 = 11110 - ADC misst interne Referenz (1.1V)
MUX4..0 = 11111 - ADC misst GND (sollte A/D-Wert von Null ergeben)

Aber eigentlich kann es nicht sein, dass bei höherer Referenzspannung 
ein grösserer A/D-Wert herauskommt (wie du beschrieben hast) ...

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren