Forum: Mikrocontroller und Digitale Elektronik AREF schwingt sägezahnförmig


von Georg (Gast)


Angehängte Dateien:

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

von Εrnst B. (ernst)


Lesenswert?

Georg schrieb:

>   ADMUX = mux;                      // Kanal waehlen
>   ADMUX |= (1<<REFS1) | (1<<REFS0); // interne Referenzspannung nutzen

Schaltet die Referenzspannung für jede Messung an und wieder aus...
Besser:
ADMUX = mux | (1<<REFS1) | (1<<REFS0);

von Philipp (Gast)


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

von Georg (Gast)


Lesenswert?

ok ... und ich messe jede Sekunde ein mal -> daher wohl die 1Hz.

von holger (Gast)


Lesenswert?

Mach mal ne Brücke über den 47 Ohm R.

von Georg (Gast)


Lesenswert?

@holger

Die Spannung am AVCC sieht am Oszi gut aus. Trotzdem brücken?

von Εrnst B. (ernst)


Lesenswert?

Georg schrieb:

> Die Spannung am AVCC sieht am Oszi gut aus. Trotzdem brücken?

eigentlich gehört da eine kleine Spule oder ferritperle hin, 47Ohm sind 
"gefühlt" etwas viel.
Aber egal: Erst die geänderte Software testen, dann notfalls zum 
Lötkolben greifen.

von Georg (Gast)


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
}

von Spezi (Gast)


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

von Georg (Gast)


Lesenswert?

OK, hab ich so gemacht. An AREF messe ich jetzt dauerhaft 2,6V. Das 
sollte ja passen.

von Georg (Gast)


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?

von Flo (Gast)


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.

von Flo (Gast)


Lesenswert?

Nachtrag: Diode natürlich andersrum :-)

von Georg (Gast)


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)?

von Spezi (Gast)


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?

von Georg (Gast)


Lesenswert?

Nach der Änderung zeigen beide Eingänge 1023.

von Flo (Gast)


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.

von Spezi (Gast)


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) ...

von Georg (Gast)


Lesenswert?

Ohh nein, ich hab differential inputs (AD0, AD1) statt  ADC0 und ADC 1 
verwendet!

von Georg (Gast)


Lesenswert?

moment ...

von Georg (Gast)


Lesenswert?

AD0(External memory interface address and data bit 0)

mensch ... wie konnte das nur passieren.

von Georg (Gast)


Lesenswert?

Kann man noch dümmer sein?


Sorry, dass ich eure Zeit verschwendet habe!

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.