Forum: Mikrocontroller und Digitale Elektronik Multireading von ADC channel lesen funktioniert nicht Warum?


von Jan H. (jan_h865)


Lesenswert?

Hallo,
Ich ich bin zurzeit bei denn Grundlagen der Mirkocontroller. Ich habe 
arbeitete zurzeit das Avr-gcc tutorial durch dort bin ich jetzt bei 
Analoge Ein und Ausgabe(ADC). Ich habe dort wie in denn Beispiel ein 
Trimmpotentiometer ausglesen. Dieser wahr an ADC0 angeschlossen mit dem 
Arduino Serial Monitor habe ich die Werte über UART gesendet. Dieser hat 
auch funktioniert. Nur dann habe ich versucht mehrere Wert auszulesen, 
das klappt nur indirekt. Ich habe dann ein weiter Trimmpotentiometer an 
ADC1 angeschlossen und es wieder ausgeben. Nun wenn beide auf "0" sind 
wird auch "0" und "0" ausgeben. Aber bei vollen Anschlag wird, beim 
ersten "1023" und beim zweiten "540" ausgeben obwohl der zweite bei "0" 
ist.
Im Internet habe ich was gefunden wie denn vorherigen Channel 
zurücksetzen. Das habe ich mit ADCL = 0; und ADCH = 0; Aber irgendwie 
klappt dieses nicht.
Mein Code bis jetzt:
1
//Main ...
2
//Dann in while
3
adc1 = ADC_Read(0); // Lesen von Kanal 0
4
UDR0 = adc1; // Senden
5
6
adc2 = ADC_Read(1); //Lesen von Kanal 1
7
UDR0 = adc2; //Senden
8
9
uint16_t ADC_Read(uint8_t channel) {
10
  ADMUX = (ADMUX & 0xE0) | (channel & 0x1F);  //Setzten des Channels
11
        ADCL = 0; //zurücksetzten
12
        ADCH = 0; //zurücksetzten
13
  ADCSRA |= (1<<ADSC); //Conversion starten
14
  while(ADCSRA & (1<<ADSC)) { //Auf erste Conversion warten
15
  }
16
  return ADCW; //Zugeben
17
}

Mfg Jan Hampel.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Wie soll Dein Code funktionieren? Deine ADC_Read-Funktion liefert einen 
16-Bit-Wert, den weist Du in Deinem Codeschnipselchen UDR0 zu ... das 
ist ein 8-Bit-Register, da die UART nur 8-Bit-Werte übertragen kann, 
auch nicht weiter überraschend.

von Jan H. (jan_h865)


Lesenswert?

Rufus Τ. F. schrieb:
> Wie soll Dein Code funktionieren? Deine ADC_Read-Funktion liefert einen
> 16-Bit-Wert, den weist Du in Deinem Codeschnipselchen UDR0 zu ... das
> ist ein 8-Bit-Register, da die UART nur 8-Bit-Werte übertragen kann,
> auch nicht weiter überraschend.

Ja hinter ADC_Read(0) kommt noch geteilt durch 4 damit maximal 255 
rauskommt.

Das Senden funktioniert ja. Nur das Multi lesen nicht.

von Karl M. (Gast)


Lesenswert?

Hallo,

auch sehr eigenartig sind diese Zeilen
1
ADCL = 0; //zurücksetzten
2
ADCH = 0; //zurücksetzten

Wo ist den das so definiert ?

Die Spannungsquellen an einen ADC Eingang müssen niederohmig sein.
Wenn dem nicht so ist, kann der Sample-and-Hold Kondensator nicht 
richtig umgeladen werden.

von Stefan F. (Gast)


Lesenswert?

Warte nach dem Umschalten des Multiplexers ein bisschen, bevor Du die 
Messung durchführst.

Der Sample&Hold Kondensator des ADC braucht eine Weile, um sich 
umzuladen.

von Jan H. (jan_h865)


Lesenswert?

Karl M. schrieb:
> Wo ist den das so definiert ?
>
> Die Spannungsquellen an einen ADC Eingang müssen niederohmig sein.
> Wenn dem nicht so ist, kann der Sample-and-Hold Kondensator nicht
> richtig umgeladen werden.

Im Internet habe ich gelesen das in dasADCL(Low register) ADCH(High 
register) die Werte von der letzten Conversation reingeschreiben werden. 
= 0; damit die wieder zurückgesetzt werden.

Avcc = 5 V genau so wie Acc , 100nF Kondensator am AREF Pin

von Jan H. (jan_h865)


Lesenswert?

Stefan U. schrieb:
> Warte nach dem Umschalten des Multiplexers ein bisschen, bevor Du die
> Messung durchführst.
>
> Der Sample&Hold Kondensator des ADC braucht eine Weile, um sich
> umzuladen.

_delay_ms(1000) reicht das?

von Karl M. (Gast)


Lesenswert?

Hallo Jan,

Jan H. schrieb:
> Im Internet habe ich gelesen das in dasADCL(Low register) ADCH(High
> register) die Werte von der letzten Conversation reingeschreiben werden.
> = 0; damit die wieder zurückgesetzt werden.

Nun was steht im Datenblatt dazu ?
Genau, das was du machen möchtest ist unsinnig !

Im Datenblatt eine atmega328p liest man heraus, dass man die Register 
nur lesen (Read) kann.

> Avcc = 5 V genau so wie Acc , 100nF Kondensator am AREF Pin
Gut, und ist AVcc über eine L (10µH)- C (100nF) an Vcc angeschlossen ?

von Karl M. (Gast)


Lesenswert?

Jan,
Jan H. schrieb:
> Stefan U. schrieb:
>> Warte nach dem Umschalten des Multiplexers ein bisschen, bevor Du die
>> Messung durchführst.
>>
>> Der Sample&Hold Kondensator des ADC braucht eine Weile, um sich
>> umzuladen.
>
> _delay_ms(1000) reicht das?

Das ist nur eine Krücke, deine Spannungsquelle ist zu hochohmig, Punkt.
Ändere die Potis (Trimmer) auf 5k Ohm ab und lege je ein 10nF-100nF an 
den ADCn Eingang, der puffert dann ein wenig.

von Mein grosses V. (vorbild)


Lesenswert?

Jan H. schrieb:
> Im Internet habe ich gelesen das in dasADCL(Low register) ADCH(High
> register) die Werte von der letzten Conversation reingeschreiben werden.
> = 0; damit die wieder zurückgesetzt werden.

Im Internet steht jede Menge Scheisse. Ein Blick ins Datenblatt dagegen 
hätte dir gezeigt, daß die ADC-Register Read-Only sind.

Jan H. schrieb:
> Ja hinter ADC_Read(0) kommt noch geteilt durch 4 damit maximal 255
> rauskommt.

Und warum steht das nicht in deinem Programmfetzen? Weil es sowieso 
Quatsch ist?
Wenn man nur 8 Bit braucht, setzt man das ADLAR-Bit und liest nur ADCH 
aus. Dann macht der Controller alles von alleine.

von Jan H. (jan_h865)


Angehängte Dateien:

Lesenswert?

So habe ich denn ADC angeschlossen

von Mein grosses V. (vorbild)


Lesenswert?

Jan H. schrieb:
> So habe ich denn ADC angeschlossen

Da gehören 2 Kondensatoren rein. Einer von Aref und einer von AVcc nach 
(A)GND. Aber keiner zwischen AVcc und Aref.

von Jan H. (jan_h865)


Lesenswert?

Mein grosses V. schrieb:
> Da gehören 2 Kondensatoren rein. Einer von Aref und einer von AVcc nach
> (A)GND. Aber keiner zwischen AVcc und Aref.

Also 100NF zwischen Avcc und AGND und 100 NF zwischen Aref und GND?

von Mein grosses V. (vorbild)


Lesenswert?

Jan H. schrieb:
> Also 100NF zwischen Avcc und AGND und 100 NF zwischen Aref und GND?

Ja.

von Jan H. (jan_h865)


Lesenswert?

Mein grosses V. schrieb:
> Jan H. schrieb:
>> Also 100NF zwischen Avcc und AGND und 100 NF zwischen Aref und GND?
>
> Ja.

Okay. Und dann behebt sich auch das Problem mit dem Multilesen?
//EDIT
100 nf zwischen avcc und agnd und dann auf +5 volt?

: Bearbeitet durch User
von Mein grosses V. (vorbild)


Lesenswert?

Jan H. schrieb:
> Okay. Und dann behebt sich auch das Problem mit dem Multilesen?
Wahrscheinlich nicht. Das fällt eher in den Bereich "Feintuning".
Zeig mal dein ganzes Programm.

> 100 nf zwischen avcc und agnd und dann auf +5 volt?

??? Avcc kommt natürlich an 5V. An Aref machst du, ausser dem 
Kondensator, gar nichts.

: Bearbeitet durch User
von Jan H. (jan_h865)


Angehängte Dateien:

Lesenswert?

Mein grosses V. schrieb:
> Jan H. schrieb:
>> Okay. Und dann behebt sich auch das Problem mit dem Multilesen?
> Wahrscheinlich nicht. Das fällt eher in den Bereich Feintuning.
> Zeig mal dein ganzes Programm.
>
>> 100 nf zwischen avcc und agnd und dann auf +5 volt?
>
> ??? Avcc kommt natürlich an 5V. An Aref machst du, ausser dem
> Kondensator, gar nichts.

Also nochmal für mich:
Avcc auf +5
AGNd auf 0 Volt
AREF 100NF auf 0 Volt? oder 5 Volt?


Ich habe die Klasse mal angehangen. Ich habe die Serial Datenübertragung 
ganz geändert. Ein Kumpel von mir der auch uC Programmiert sagt das das 
so schneller sei. Keine Ahnung ob das stimmt. Aber die Übertragung 
funktioniert auch.

von Mein grosses V. (vorbild)


Lesenswert?

Jan H. schrieb:
> AREF 100NF auf 0 Volt? oder 5 Volt?

Derartige Kondensatoren werden, wenn es nicht ausdrücklich anders 
spezifiziert ist, grundsätzlich mit einer Seite gegen GND geschaltet.

Jan H. schrieb:
> Aber die Übertragung
> funktioniert auch.

Also macht es jetzt, was es soll?

von Jan H. (jan_h865)


Lesenswert?

Mein grosses V. schrieb:
> Jan H. schrieb:
>> AREF 100NF auf 0 Volt? oder 5 Volt?
>
> Derartige Kondensatoren werden, wenn es nicht ausdrücklich anders
> spezifiziert ist, grundsätzlich mit einer Seite gegen GND geschaltet.
>
> Jan H. schrieb:
>> Aber die Übertragung
>> funktioniert auch.
>
> Also macht es jetzt, was es soll?

Also Aref mit 100 nf auf gnd okay verstanden
Avcc an +5 Volt auch verstanden
Agnd auf gnd logisch

macht es jetzt, was es soll?
Nein, Ein Kumpel hat mir diesen Link geben 
http://www.appelsiini.net/2011/simple-usart-with-avr-libc
Soll angeblich schneller sein. Finde ich jetzt nicht direkt aber die 
Übertragung zum Serial Monitor funktioniert genauso wie früher.
Mein problem ist halt. Das wenn ich denn Wert 1 auslese und der ist 
255(Wegen geteilt durch 4) Also beim ersten Poti vollen Anschlag. Der 
zweite Poti steht noch auf "0" aber der ADC gibt mir denn Wert "50" aus 
und nicht "0"

von Mein grosses V. (vorbild)


Lesenswert?

Jan H. schrieb:
> Der
> zweite Poti steht noch auf "0" aber der ADC gibt mir denn Wert "50" aus
> und nicht "0"

1
  ADMUX = (ADMUX & 0xE0) | (channel & 0x1F);  
2
  ADCSRA |= (1<<ADSC);

Setz da mal ein Delay rein.

Also
1
  ADMUX = (ADMUX & 0xE0) | (channel & 0x1F);  
2
  _delay_ms(1);
3
  ADCSRA |= (1<<ADSC);

von Jan H. (jan_h865)


Lesenswert?

Mein grosses V. schrieb:
> Jan H. schrieb:
>> Der
>> zweite Poti steht noch auf "0" aber der ADC gibt mir denn Wert "50" aus
>> und nicht "0"
>
>   ADMUX = (ADMUX & 0xE0) | (channel & 0x1F);
>   ADCSRA |= (1<<ADSC);
>
> Setz da mal ein Delay rein.
>
> Also
>
>   ADMUX = (ADMUX & 0xE0) | (channel & 0x1F);
>   _delay_ms(1);
>   ADCSRA |= (1<<ADSC);

Großes Dankeschön funktioniert nun! :) :)

von Falk B. (falk)


Lesenswert?

@Jan Hampel (jan_h865)

>>   ADMUX = (ADMUX & 0xE0) | (channel & 0x1F);
>>   _delay_ms(1);
>>   ADCSRA |= (1<<ADSC);

>Großes Dankeschön funktioniert nun! :) :)

Mit der Holzhammermethode 8-0

Das hier war schon der richtige Hinweis!

> Karl M. (Gast)
>Das ist nur eine Krücke, deine Spannungsquelle ist zu hochohmig, Punkt.
>Ändere die Potis (Trimmer) auf 5k Ohm ab und lege je ein 10nF-100nF an
>den ADCn Eingang, der puffert dann ein wenig.

10nF von den ADC-Eingängen gegen GND, dann braucht man auch ein Delay 
zwischen MUX-Einstellung und AD-Start! Schon gar nicht 1ms!

von Karl M. (Gast)


Lesenswert?

Danke Falk,

die Anforderungen ergeben sich ja direkt aus einem der Atmel AVR 
Datenblätter.

Desweiteren gibt es mind. zwei Atmel Application Notes zu den ADC, die 
man gelesen habe müsste, bevor man sich über den ADC-Wandler wundert.

Welchen Atmel AVR verwendet der TE ?

War irgendwo zu lesen, wie die Widerstandswerte der Potis (Trimner) sind 
?

von Jan H. (jan_h865)


Lesenswert?

Karl M. schrieb:
> Welchen Atmel AVR verwendet der TE ?

ATMega328P

von Mein grosses V. (vorbild)


Lesenswert?

Falk B. schrieb:
> Mit der Holzhammermethode 8-0

Na und? Natürlich ist die Zeit noch zu lang und es sind auch noch ein 
paar Hausaufgaben zu machen. Aber es läuft jetzt. Und damit ist der 
Fehler eingegrenzt. Euer abgehobenes Geschwafel hat dem TO dagegegen gar 
nichts gebracht.

von Karl M. (Gast)


Lesenswert?

Ich lese
Wissen == "abgehobenes Geschwafel".

Na dann, mal weiter so mit dem Halbwissen.

von Mein grosses V. (vorbild)


Lesenswert?

Karl M. schrieb:
> Na dann, mal weiter so mit dem Halbwissen.

Du mich auch.

von Stefan F. (Gast)


Lesenswert?

Du kannst gerne 1000ms warten, jedoch reichen sicher auch 1ms. Und wenn 
die Beschaltung des ADC Eingangs ausreichend nierderohmig ist, dann 
brauchst du noch weniger zu warten. Im günstigsten fall ist gar keine 
Wartezeit nötig.

Bedenke, dass der Sample&Hold Kondensator nur wenige pF hat.

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.