Forum: Mikrocontroller und Digitale Elektronik Träger AD- Wandler?


von Stephan R. (Gast)


Lesenswert?

Moin!

Leider kann ich keinen Code posten, versuche aber, mein Anliegen 
ausreichend zu erklären:

Ich möchte nacheinander und immer wieder 2 AD- Eingänge des Atmega8 
abfragen (und erstmal per HTerm anzeigen).

Dazu führe ich eingangs eine Init durch und ändere anschließend für 
jeden Einlesevorgang das "Mux-Register" entsprechend dem gewünschten AD- 
Eingang.

Quasi:

MUX = 1;
wert1 = ADC;
MUX = 2;
wert2 = ADC;
anzeigen();

Es kommt aber stets der gleiche Wert für beide Variablen dabei heraus!!
Woran könnte das liegen?

von spess53 (Gast)


Lesenswert?

Hi

Programmiersprache?

An welcher Stelle startest du den ADC und wartest auf das Ergebnis?

MfG Spess

von Stephan R. (Gast)


Lesenswert?

a: c

b: ADSC (start convert) setze ich im Init, das Ergebnis hole ich mir 
später in der Schleife.

Ich habe im Tutorial gelesen, dass ADSC vor dem ersten Muxen gesetzt 
werden soll, dennoch funktioniert es ja quasi auch so (ein bisschen).

Ich kann mir vorstellen, dass ich vor jedem MUX- Wechsel bzw nach jedem 
Auslesen auch an den Status-Bits rumoperieren muss?!

von Stephan R. (Gast)


Lesenswert?

Korrektur:

Ich habe im Tutorial gelesen, dass ADSC > NACH < dem ersten Muxen 
gesetzt
werden soll, dennoch funktioniert es ja quasi auch so (ein bisschen).

von spess53 (Gast)


Lesenswert?

Hi

>Leider kann ich keinen Code posten,...

Wieso nicht? Sollen jetzt alle ihre Kristallkugeln putzen?

MfG Spess

von Stephan R. (Gast)


Lesenswert?

Das kann ja nie schaden!

Der Programmierrechner hängt nicht am Internet. Aber ich werds daheim 
versuchen..

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Nach dem Ummuxen direkt eine Messung zu starten, geht meist daneben, da 
der MUX eine gewisse Zeit zum Umschalten braucht, im Bereich einiger 
hundert ns. Es kann nicht schaden, entweder nach dem Umschalten zu 
warten, oder aber den MUX direkt VOR dem Einlesen der vorherigen Messung 
umzuschalten. Das Einlesen geschieht entweder durch Interrupt oder per 
Polling des ADSC oder ADIF. Also nach Bestätigung des gültigen 
Ergebnisses wird erst umgemuxt, dann ADCL und ADCH eingelesen und 
weggespeichert und dann eine neue Messung gestartet. Das Einlesen 
verbraucht dann die Zeit, die der MUX zum Schalten benötigt. Alternativ 
kann man die Messungen auch immer mit einem festen Timerinterval 
starten, dann hat der MUX ewig genug Zeit.

von Floh (Gast)


Lesenswert?

Stephan R. schrieb:
> Es kommt aber stets der gleiche Wert für beide Variablen dabei heraus!!
> Woran könnte das liegen?

Was hängt an den AD-Eingängen?

von Ralli (Gast)


Lesenswert?

Wer lesen kann und diese Gabe nutzt, ist manchmal im Vorteil.
Hier wieder ein Beweis.

Datenblatt ATmega8:
-------------------
However, the simplest method is to wait for the first conversion
to complete, and then change the channel selection. Since the next
conversion has already started automatically, the next result will
reflect the previous channel selection. Subsequent conversions will
reflect the new channel selection.

Der ATmega8 macht also genau das, was im Datenblatt steht.
- Das gefällt mir an den Dingern!

von Stephan R. (Gast)


Lesenswert?

Es wird und wird nicht besser.. Ich frage mich, ob das START-CONVERT- 
Bit Einfluss auf die Messung hat. (Ich habe die INIT- Routine hier mit 
eingebaut.)


int get_ad (int ch)
{
 ADCSRA |= (1 <<  ADEN);  // AD-Wandler enabled
 ADCSRA |= (0 <<  ADFR);  // Free Running Mode aus
 ADMUX  |= (1 << REFS0);  // AVcc als Referenzspannung
 ADMUX  |= (0 << REFS1);  //
 ADMUX  |= (0 << ADLAR);  // Die 8 bit kommen in das Low-Register
 ADCSRA |= (1 << ADPS1);  // Vorteiler
 ADCSRA |= (1 << ADPS0);  // auf /8
 ADCSRA |= (1 <<  ADSC);  // convert an

  switch (ch)
  {
    case 0:   ADMUX  |= (0 <<  MUX0) | (0 <<  MUX1) | (0 <<  MUX2); 
break;
    case 1:   ADMUX  |= (1 <<  MUX0) | (0 <<  MUX1) | (0 <<  MUX2); 
break;
    case 2:   ADMUX  |= (0 <<  MUX0) | (1 <<  MUX1) | (0 <<  MUX2); 
break;
   }
return ADC;
}

von Floh (Gast)


Lesenswert?

Wo löscht du die mux-bits ausm ADMUX Register?

von Stephan R. (Gast)


Lesenswert?

Löschen? Ich setzt doch bei jedem Switch eine neue Maske?!





(nicht gut?)

von Edi R. (edi_r)


Lesenswert?

|= ist was anderes als =

Du meintest:
1
    case 0:   ADMUX  = (0 <<  MUX0) | (0 <<  MUX1) | (0 <<  MUX2);
usw.

von Floh (Gast)


Lesenswert?

Edi R. schrieb:
> |= ist was anderes als =
>
> Du meintest:    case 0:   ADMUX  = (0 <<  MUX0) | (0 <<  MUX1) | (0 <<  MUX2);
> usw.

REfs dabei nicht vergessen. :-)

von Magnus M. (magnetus) Benutzerseite


Lesenswert?

Stephan R. schrieb:
> Löschen? Ich setzt doch bei jedem Switch eine neue Maske?!

Nö. Mit "|=" werden Bits nur gesetzt.

Gruß,
Magnetus

von Stephan R. (Gast)


Lesenswert?

Oha! Ein graues Wölkchen zieht auf!

Heisst das,

|= (0 <<  MUX0)

rücksetzt das Bit nicht auf 0??

von AVR-Frickler (Gast)


Lesenswert?

Hi Stephan,

du machst in deinem Code 2 Fehler:

1. Du startest erst den ADC und setzt dann den Mux. Setzte deinen 
Switch-Block vor dem Initialisierungsblock.

2. Du wartest überhauüt nicht bis der ADC fertig ist. Sieh dazu die 
Anmerkungen von Travel Rec. weiter oben, oder schau mal ins 
AVR-GCC-Tutorial auf dieser Seite.

Ein kleiner Tipp es reicht aus wenn du die ersten 7 Zeilen deines 
Initialisierungsblocks nur ein einziges Mal ausführst. Also einfach nur 
einmal vor deiner Hauptschleife in main().

von Stephan R. (Gast)


Lesenswert?

Es läääääuft!! Es läuftesläuftesläuft!!!!!
Init abgetrennt, Mux nach vorn geschoben, dem ganzen nen kleines 
Päuschen eingebaut und alles in Butter!

Habt Dank!

von Magnus M. (magnetus) Benutzerseite


Lesenswert?

Stephan R. schrieb:
> Heisst das,
> |= (0 <<  MUX0)
> rücksetzt das Bit nicht auf 0??

Richtig. Zum gezielten zurücksetzen schreibt man z.B.:

ADMUX &= ~((1<<MUX0)|(1<<MUX1));

Gruß,
Magnetus

von Floh (Gast)


Lesenswert?

oder man schreibt fürs obere Programm einfach:

ADMUX = (1<<REFS0)|(ch);
:-)

von Stephan R. (Gast)


Lesenswert?

Denn ist dieser Code

case 0:   ADMUX  = (0 <<  MUX0) | (0 <<  MUX1) | (0 <<  MUX2);


wirkungslos??

von Magnus M. (magnetus) Benutzerseite


Lesenswert?

Nö. Immerhin beschreibt er das Register mit dem Wert "0".

von Floh (Gast)


Lesenswert?

Stephan R. schrieb:
> case 0:   ADMUX  = (0 <<  MUX0) | (0 <<  MUX1) | (0 <<  MUX2);

Er überschreibt dir halt deine gewünschte REFS einstellung, da diese 
auch im ADMUX register sind, mit 0.

von Stephan R. (Gast)


Lesenswert?

Stephan R. schrieb:
> Heisst das,
>
> |= (0 <<  MUX0)
>
> rücksetzt das Bit nicht auf 0??

Magnus Müller schrieb:
> Richtig. Zum gezielten zurücksetzen schreibt man z.B.:
>
> ADMUX &= ~((1<<MUX0)|(1<<MUX1));

Stephan R. schrieb:
> Denn ist dieser Code
>
> case 0:   ADMUX  = (0 <<  MUX0) | (0 <<  MUX1) | (0 <<  MUX2);
>
>
> wirkungslos??

Magnus Müller schrieb:
> Nö. Immerhin beschreibt er das Register mit dem Wert "0".



Graue Wolke angekommen.

von spess53 (Gast)


Lesenswert?

Hi

>dem ganzen nen kleines Päuschen eingebaut und alles in Butter!

Das Päuschen macht man mit:

 while (ADCSRA & (1<<ADSC)

MfG Spess

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.