-
        

Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 14

Thema: Zwei Kanaele des ADC spinnen...

  1. #1
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    03.01.2004
    Ort
    Pottenstein
    Alter
    38
    Beiträge
    265

    Zwei Kanaele des ADC spinnen...

    Anzeige

    SMARTPHONES & TABLETS-bis zu 77% RABATT-Kostenlose Lieferung-Aktuell | Cool | Unentbehrlich
    Moin moin!

    Ich versuche zwei Werte ueber den ADC eines ATmega16 einzulesen, aber irgendwie klappt's nicht so wie ich will. Beide Kanaele einzeln gehen (Wenn ich den jeweils anderen Block unten auskommentiere). Wenn ich an beiden Kanaelen was anschliesse, gibt's auf x und w (auf beiden gleich) einen Mix der beiden Werte. Mach ich irgendwas falsch? Ich will keine Interrupts verwenden, nur pollen. Muss ich vielleicht trotzdem ADIF auslesen?? Eigentlich muesste doch das Warten auf ADSC==0 reichen?????
    Kann jemand helfen?

    Code:
    int main(void) {
    	init();
    	
    	while(1) {
    		ADMUX=(1<<MUX0);			// Kanal 1 auswaehlen
    		ADCSR|=(1<<ADSC);		       // Messung starten
    		while((ADCSR&ADSC)==1) ;	     // Warten bis ADSC==0
    		w=ADCL+ADCH*256;		       // Ergebnis auslesen
    		
    		ADMUX=(1<<MUX1)|(1<<MUX0);	 // Kanal 3 auswaehlen
    		ADCSR|=(1<<ADSC);			// Messung starten
    		while((ADCSR&ADSC)==1) ;	      // Warten bis ADSC==0
    		x=ADCL+ADCH*256;			// Ergebnis auslesen
    		
    		print(w,0,x,200);
    	}
    }
    Nils

  2. #2
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    09.06.2004
    Ort
    Aachen
    Beiträge
    2.674
    Also normalerweise wird es schon über ADIF gemacht:

    Code:
    while(!(ADCSRA & (1<<ADIF)));
    Aber im Datenblatt steht:

    ADSC will read as one as long as a conversion is in progress. When the conversion is
    complete, it returns to zero. Writing zero to this bit has no effect.
    Das es nicht läuft könnte aber auch daran liegen, dass es kein Register "ADCSR" beim Mega16 gibt
    Versuchs mal mit ADCSRA!

  3. #3
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    03.01.2004
    Ort
    Pottenstein
    Alter
    38
    Beiträge
    265
    Nabend,

    Hab das Register auf ADCSRA geaendert, keine Ahnung warum mein Compiler das andere nicht angemeckert hat.
    Ich hab jetzt mal nen anderen Kanal ausprobiert (1 und 5 statt 1 und 3), damit geht's. Sehr suspekt... Vielleicht eine kleine Ungenauigkeit im AVR-MUX
    Nils

  4. #4
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.836
    Ich muß mir das auch wenigstens noch dreimal im Datasheet durchlesen.
    Bascom macht das so: Wenn er einen kanal mit Getadc(n) liest,
    setzt er admux
    macht eine Blindmessung
    Und noch eine, und diesen wert gibt er dann her.

    Offensichtlich läßt er sich gar nicht erst auf das Timing mit mux und adc-status ein

    Betrachte ich als workaround, aber wenn's schön macht ?
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

  5. #5
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    03.01.2004
    Ort
    Pottenstein
    Alter
    38
    Beiträge
    265
    Die Blindmessung mach der AVR bei der ersten Messung, jede weitere wird dann nur einmal ausgefuehrt. Und wenn sie fertig ist, geht erstens ADSC wieder auf Null und ADIF auf Eins. Ich hab beides als Wartekriterium ausprobiert, ging beides nicht, Effekt wie oben beschrieben. Mit dem anderen Kanal geht's aber, weiss der Geier wieso.
    Nils

  6. #6
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    09.06.2004
    Ort
    Aachen
    Beiträge
    2.674
    Also unter C gehts auf jeden Fall anders, du schaltest ja nur den kanal um, warum dann ne Blindmessung?
    Ungenauigkeit glaub ich nciht, bei mir läuft der ADC des Mega16 bisher ohne irgendwelche Probleme, auch wenn ich ständig die Kanäle wechsle.
    Wie ist der ADC denn sonst noch konfiguriert?

  7. #7
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    03.01.2004
    Ort
    Pottenstein
    Alter
    38
    Beiträge
    265
    In meiner init():

    Code:
    ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(0<<ADPS0);
    Und diese Funktion wird in main() zyklisch aufgerufen:

    Code:
    void read_inputs(void) {
    	ADMUX=(1<<MUX0);				// Kanal 1 auswaehlen
    	ADCSRA|=(1<<ADSC);				// Messung starten
    	while(!(ADCSRA & (1<<ADIF)));	// Warten bis ADSC==0
    	ADCSRA|=(1<<ADIF);				// ADIF auf Null setzen !?!
    	w=ADCL+ADCH*256;				// Ergebnis auslesen
    	
    	ADMUX=(1<<MUX2)|(1<<MUX0);		// Kanal 5 auswaehlen
    	ADCSRA|=(1<<ADSC);				// Messung starten
    	while(!(ADCSRA & (1<<ADIF)));	// Warten bis ADSC==0
    	ADCSRA|=(1<<ADIF);				// ADIF auf Null setzen !?!
    	x=ADCL+ADCH*256;				// Ergebnis auslesen
    }
    Der ATmega16 laeuft mit 8MHz. Das mit dem ADIF auf Null setzen, indem man ne Eins reinschreibt, steht so im Datenblatt...

    Nils

  8. #8
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    03.01.2004
    Ort
    Pottenstein
    Alter
    38
    Beiträge
    265
    Moin moin!

    Ich kaempfe immer noch mit dem ADC. Irgendwie beeinflussen sich die Kanaele untereinander. Wenn ich an drei ADCs gleichzeitig verschiedene Werte anlege, bekomme ich auf zweien den gleichen Wert, je einen der beiden erwarteten. Also zum Beispiel ist
    ADC0=522,
    ADC1=470,
    ADC2=1023.
    Das kommt raus, wenn ich nur den jeweiligen Block im Code benutze und den Rest auskommentiere. So wie es unten steht, kommt aber dann raus:

    ADC0=522,
    ADC1=1023,
    ADC2=1023.

    Ich krieg einfach nicht raus, wieso. Der Code unten muesste doch stimmen, oder? Kann vielleicht mal jemand seinen funktionierenden Code fuer das Auslesen von mehreren ADCs posten???

    Danke,
    Nils


    Code:
    void read_inputs(void) {
    	ADMUX	=	0x02;					// Kanal 0 auswaehlen
    	ADCSRA	|=	(1<<ADSC);				// Messung starten
    	while(!(ADCSRA & (1<<ADIF)));		// Warten bis ADSC==0
    	ADCSRA	|=	(1<<ADIF);				// ADIF auf Null setzen !?!
    	rohsollwert	=	ADCL+ADCH*256;		// Ergebnis auslesen
    	sollwert	=	rohsollwert/1023.0*100;		// In Prozent umrechnen
    	
    	ADMUX	=	0x01;					// Kanal 1 auswaehlen
    	ADCSRA	|=	(1<<ADSC);				// Messung starten
    	while(!(ADCSRA & (1<<ADIF)));		// Warten bis ADSC==0
    	ADCSRA	|=	(1<<ADIF);				// ADIF auf Null setzen !?!
    	rohistwertx	=	ADCL+ADCH*256;		// Ergebnis auslesen
    	istwertx	=	rohistwertx/1023.0*100;		// In Prozent umrechnen
    	
    	ADMUX	=	0x00;					// Kanal 2 auswaehlen
    	ADCSRA	|=	(1<<ADSC);				// Messung starten
    	while(!(ADCSRA & (1<<ADIF)));		// Warten bis ADSC==0
    	ADCSRA	|=	(1<<ADIF);				// ADIF auf Null setzen !?!
    	rohistwerty	=	ADCL+ADCH*256;		// Ergebnis auslesen
    	istwerty	=	rohistwerty/1023.0*100;		// In Prozent umrechnen
    }

  9. #9
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.836
    rohsollwert = ADCL+ADCH*256; // Ergebnis auslesen
    Ich bin nicht sicher, ob der C die beiden Werte H u.L dann in der richtigen Reihenfolge liest, und da ist der AVR heikel, weil er die Register sperrt.
    Schau mal in das Assembler listing, zu Kontrolle
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

  10. #10
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    03.01.2004
    Ort
    Pottenstein
    Alter
    38
    Beiträge
    265
    An der Stelle haette ich das Problem weniger vermutet, weil ja die Werte stimmen, wenn ich die Kanaele einzeln auslese. Also denke ich, dass dabei ADCL zuerst gelesen wird, wie im Datenblatt vorgeschrieben.

    Habs gerade getestet, wenn ich die Zeile umdrehe, werden alle drei Werte als 520 angezeigt, auch wenn ich die Eingangsspannungen aendere...
    Nils

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •