- LiTime Speicher und Akkus         
Ergebnis 1 bis 10 von 10

Thema: ADC - Ich finde den/die Fehler nicht

  1. #1
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    25.03.2006
    Ort
    nahe Tulln (Niederösterreich)
    Alter
    33
    Beiträge
    460

    ADC - Ich finde den/die Fehler nicht

    Anzeige

    Praxistest und DIY Projekte
    Hallo!
    Ich habe mein erstes Programm mit dem Internen ADC Wandler des mega8 geschrieben, aber es funktioniert noch nicht ganz.

    Code:
    #include <avr/io.h>
    #include <stdint.h>
    
    #define F_CPU 3686400UL
    #include <util/delay.h>
    
    
    // LEDs:
    // - Grün: PORT C 0
    // - Gelb: PORT C 3
    // - Rot: PORT C 5
    // POTI an PORT B 0
    
    //===========================================================================================================
    
    int adc (uint8_t mux)
    
    {	uint8_t i;
    	uint16_t ergebnis=0;
    	
    	ADCSRA=(1<<ADEN);					// ADC ein
    	ADCSRA=(1<<ADPS2)|(1<<ADPS0);		// Frequenzteiler 32
    		
    	ADMUX|=(1<<REFS1)|(1<<REFS0);		// Interne Refrerenzspg ein
    	ADMUX=mux;							// ADC an Pin mux
    	
    	ADCSRA|=(1<<ADSC);					// Dummy Load
    	while(ADCSRA&(1<<ADSC)) {}			// Warten bis Messung fertig
    	
    	for(i=0;i<5;i++)					// 5 Mal messen
    	{	ADCSRA|=(1<<ADSC);
    		while(ADCSRA&(1<<ADSC)) {}		// Warten bis messung fertig		
    		ergebnis=ergebnis+ADC;			// Mittelwert bestimmen	
    	}
    	
    	ADCSRA&=~(1<<ADEN);					// ADC ausschalten
    	
    	ergebnis=ergebnis/5;
    	return ergebnis;					// Ergebnis zurückgeben
    }
    
    //=========================================================================================================
    
    int main (void)
    
    {	DDRD=0x00;
    	DDRB=0x00;
    	DDRC=0xff;
    	PORTC=0x00;
    
    	uint16_t wandlung;
    	while(1)
    	{	wandlung=adc(0);
    		
    		if(wandlung<21845)
    		{	PORTC|=(1<<0);
    			PORTC&=~(1<<3);
    			PORTC&=~(1<<5);
    		}
    		
    		if(wandlung>21845 && wandlung<43690)
    		{	PORTC|=(1<<3);
    			PORTC&=~(1<<0);
    			PORTC&=~(1<<5);
    		}
    	
    		if(wandlung>43690 && wandlung<65535)
    		{	PORTC|=(1<<5);
    			PORTC&=~(1<<0);
    			PORTC&=~(1<<3);	
    		}
    		
    		else{}
    
    	}
    }
    
    //==========================================================================================================

    Wenn ich das Programm in den Controller brenne, leuchtet nur die Rote Led, d.h. es wird immer der else-Zweig im Hauptprogramm ausgeführt.

    Ich glaube es liegt daran, dass ich nicht weiß, wie man dem uC sagt, dass das Poti auf PORT B ist, mit ADMUX=0 sagt man ihm ja nur, dass der ADC Pin der Pin 0 ist.

    Außerdem kenn ich mich mit der Referenzspg. nicht so gut aus. Man kann also nur Spannungen von 0-2,54 Volt in den Controller schicken, das halte ich auch ein, aber ich weiß nicht, ob die Einstellungen ADMUX|=(1<<REFS1)|(1<<REFS0); stimmen.

    Grüße,
    Christoph

  2. #2
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    06.02.2005
    Ort
    Hamburg
    Alter
    37
    Beiträge
    4.255
    Nur die mit ADC0..7 bezeichneten Eingänge eines AVRs sind Analogeingänge! Beim Mega8 liegen sie an PortC.

    ADMUX|=(1<<REFS1)|(1<<REFS0); schaltet auf intern 2,56V Referenz.

    Um die Referenz auf die Betriebsspannung zu setzen (praktisch wenn man Potis zwischen VCC und GND schaltet) nimmt man
    ADMUX|=1<<REFS0);
    Wenn VCC=5V kann man dann auch bis 5V messen.

  3. #3
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    25.03.2006
    Ort
    nahe Tulln (Niederösterreich)
    Alter
    33
    Beiträge
    460
    Danke, ich habe das jetzt ausgebessert. Jetzt sieht mein Programm so aus:

    Code:
    #include <avr/io.h>
    #include <stdint.h>
    
    #define F_CPU 3686400UL
    #include <util/delay.h>
    
    
    // LEDs an PORT B 3, 4, 5
    // POTI an PORT C 0
    
    //===========================================================================================================
    
    int adc (uint8_t mux)
    
    {	uint8_t i;
    	uint16_t ergebnis=0;
    	
    	ADCSRA=(1<<ADEN);					// ADC ein
    	ADCSRA=(1<<ADPS2)|(1<<ADPS0);		// Frequenzteiler 32
    		
    	ADMUX=(1<<REFS0);					// Interne Refrerenzspg 5V
    	ADMUX=mux;							// ADC an Pin mux
    	
    	ADCSRA|=(1<<ADSC);					// Dummy Load
    	while(ADCSRA&(1<<ADSC)) {}			// Warten bis Messung fertig
    	
    	for(i=0;i<5;i++)					// 5 Mal messen
    	{	ADCSRA|=(1<<ADSC);
    		while(ADCSRA&(1<<ADSC)) {}		// Warten bis messung fertig		
    		ergebnis=ergebnis+ADCW;			// zusammenzählen
    	}
    	
    	ADCSRA&=~(1<<ADEN);					// ADC ausschalten
    	
    	ergebnis=ergebnis/5;				// Mittelwert bestimmen
    	return ergebnis;					// Ergebnis zurückgeben
    }
    
    //=========================================================================================================
    
    int main (void)
    
    {	uint16_t wandlung;
    
    	DDRC=0x00;
    	DDRB=0xff;
    	PORTB=0xff;
    
    	while(1)
    	{	
    		wandlung=adc(0);
    		_delay_ms(50);
    		if(wandlung<341)
    		{	PORTB|=(1<<3);
    			PORTB&=~(1<<4);
    			PORTB&=~(1<<5);
    		}
    		
    		if(wandlung>341 && wandlung<682)
    		{	PORTB|=(1<<4);
    			PORTB&=~(1<<3);
    			PORTB&=~(1<<5);
    		}
    	
    		if(wandlung>682 && wandlung<1024)
    		{	PORTB|=(1<<5);
    			PORTB&=~(1<<3);
    			PORTB&=~(1<<4);	
    		}
    		
    	}
    }
    
    //==========================================================================================================
    Jetzt leuchtet nur die grüne led, die auf B3 hängt, das heißt, es wird immer die erste if anweisung ausgeführt, egal wie ich das poti drehe, aber ich weiß nicht warum. Im tutorial von microcontroller.net steht, dass ADCW den wert 0-1024 annehmen kann. Diese Menge habe ich gedrittelt, und auf die 3 if anweisungen aufgeteilt.
    Ich verstehe nicht ganz warum 1024, ein 16 bit Datentyp geht ja bis 2^16 = 65536. Oder hat das garnichts mit den 16 bit zu tun?

    MfG
    Christoph

  4. #4
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    17.06.2006
    Alter
    33
    Beiträge
    113
    Es sind 10Bit und nicht 16 bit, deswegen 1024...
    Stell dir vor es ist krieg - und keiner geht hin.
    Gewinner des Roboterwettbewerbs "Zukunft durch Innovation" des Bundeslandes NRW in Aachen.

  5. #5
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Es müsste heissen
    Code:
    ADMUX = (1<<REFS0) | mux;
    ansonsten überschreibst du ADMUX.

    Der Wert des ersten ADC-Ergebnisses nach Aktivierung des ADC sollte man laut Handbuch in die Tonne kloppen. Also nach Aktivierung erst eine Blind-Wandlung machen.
    Disclaimer: none. Sue me.

  6. #6
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    06.02.2005
    Ort
    Hamburg
    Alter
    37
    Beiträge
    4.255
    @SprinterSB:
    die Kanalwahl wird ja erst danach reingeschrieben, daher ist das egal. Es stellt zudem sicher, dass kein Reste einer alten Kanalauswahl mehr übrigbleiben. Die Routine scheint aus dem µc.net-Tutorial zu stammen. Und die 1. wandlung zum Warmlaufen ist auch enthalten...

    EDIT: sorry, hast recht. Ich hab das fehlende | übersehen!

    @Christoph2:setz mal um die einzelnen Abfragen Klammern.

  7. #7
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Gleiches gilt für ADCSRA: Entweder

    Code:
       ADCSRA = (1<<ADEN);
       ADCSRA |= (1<<ADPS2) | (1<<ADPS0);
    oder
    Code:
       ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS0);
    wobei ich hier der 2. Variante den Vorzug gebe
    Disclaimer: none. Sue me.

  8. #8
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    25.03.2006
    Ort
    nahe Tulln (Niederösterreich)
    Alter
    33
    Beiträge
    460
    Danke, ich habe jetzt alles ausgebessert, und jetzt funktioniert das programm!!

    Kann mir noch jemand erklären, wie das mit den Strichen | funktioniert?
    Ich verstehe nicht ganz, wann man |= und wann man nur = schreiben muss.

    MfG
    Christoph

  9. #9
    Erfahrener Benutzer Robotik Visionär Avatar von Hubert.G
    Registriert seit
    14.10.2006
    Ort
    Pasching OÖ
    Beiträge
    6.220
    Sieh mal hier, vieleicht hilft dir das: www.mikrocontroller.net/articles/Bitmanipulation

  10. #10
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    25.03.2006
    Ort
    nahe Tulln (Niederösterreich)
    Alter
    33
    Beiträge
    460
    ich verstehe es!!! danke!!!

Berechtigungen

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

LiTime Speicher und Akkus