- 12V Akku mit 280 Ah bauen         
Ergebnis 1 bis 10 von 10

Thema: AD-Wandler problem

  1. #1
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    19.03.2005
    Ort
    Villach
    Alter
    33
    Beiträge
    995

    AD-Wandler problem

    Anzeige

    Praxistest und DIY Projekte
    Hallo,

    Mein code funktioniert einfach nicht. er ist aus den avr-gcctutorial von mikrocontroller.net abgewandelt.
    Der wert der herauskommt ist vermutlich nicht null, nicht größer null und nicht kleiner null
    Der Code ist in 3 dateien zerlegt. Programieren tu ich mit Kontrollerlab, hab den aktuellen avr-gcc, mein AVR ist ein Mega 16 mit 14,.... mhz. F_CPU wird von Kontrollerlab definiert und muss nomit nicht im programm stehen.

    pinbelegung.h:
    Code:
    #include <avr/io.h>
    
    void initavr(void) {
    
    	DDRD = 0xF0;
    	DDRB = 0xE3;
    
    }
    adc.c:
    Code:
    #include <avr/io.h>
    #include <util/delay.h>    // definiert _delay_ms()
    
    void adcstart(void);
    void adcstop(void);
    
    void adcstart(void) {
    	ADCSRA |= ((1<<ADPS0) | (1<<ADPS1) | (1<<ADPS2) | (1<<ADEN));//ADPS0-2(Vorteiler 128), ADEN (Enable)
    	uint8_t kanal = 0;
    	ADMUX = kanal;
    	ADMUX |= (1<<REFS1) | (1<<REFS0);
    	
    	ADCSRA |= (1<<ADSC);              	// eine ADC-Wandlung als Dummy zum warmlaufen
    	while ( ADCSRA & (1<<ADSC) ) {
    	;     					// auf Abschluss der Konvertierung warten 
    	}
    }
    
    void adcstop(void) {
    	ADCSRA &= ~(1<<ADEN);
    }
    
    uint16_t adcget(uint8_t kanal) {
    	uint8_t i;
    	uint16_t ergebnis = 0;
    
    	ADMUX = kanal;            		// Kanal waehlen
    	ADMUX |= (1<<REFS1) | (1<<REFS0);	// interne Referenzspannung nutzen 
    
    	ADCSRA |= (1<<ADSC);			// eine Wandlung "single conversion"
    	while ( ADCSRA & (1<<ADSC) ) {
    	;  					 // auf Abschluss der Konvertierung warten
    	}
    
    	    ergebnis=ADC;
    	return ergebnis;
    }
    adc_test.c (Mit main schleife):
    Code:
    #include <avr/io.h>
    #include <util/delay.h>    // definiert _delay_ms()
    #include "pinbelegung.h"
    
    uint16_t adcwert = 0;
    
    int main(void)
    {
    	initavr();
    	
    	adcstart();
    	PORTB |= (1<<PB7) | (1<<PB5) | (1<<PB6);
    	
    	for(;;) {
    		adcwert = adcget(0); // MUX-Bits auf 0b0000 -> Channel 0 
    		//adcwert = adcget(2); // MUX-Bits auf 0b0010 -> Channel 2 
    		
    		if (adcwert==0) {
    			PORTB |= (1<<PB7);
    		}
    		
    		else if (adcwert<0) {
    			PORTB |= (1<<PB5);
    		}
    		else if (adcwert>800) {
    			PORTB |= (1<<PB6);
    		}
    		else {
    			PORTB &= ~((1<<PB5) | (1<<PB6) | (1<<PB7));
    		}
    		_delay_ms(100);
    	}
    	return(0);
    	adcstop();
    }
    Frohe Weihnachten
    Thomas

  2. #2
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    22.05.2005
    Ort
    12°29´ O, 48°38´ N
    Beiträge
    2.731
    Hallo,

    bei Mega16 sind die ADC-Eingänge doch an PortA, ich kann da im Programm nirgends dazu etwas finden, Stichwort DDRA !

    Evtl. schreibst Du auch beim auslesen des Wertes auch gleich so:
    ergebnis = ADC;
    denn das mit der Reihenfolge des auslesens der 16-Bit-Register ist immer so eine Sache.

  3. #3
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    19.03.2005
    Ort
    Villach
    Alter
    33
    Beiträge
    995
    Ich lese jetzt den wert mit ergebnis = ADC; aus. doch noch kein ergebnis.

    DDRA brauch ich ja nicht als eingang zu definieren, oder? Der kanal wird ja von den mux bits festgelegt.

    wenn ich bei den if schleifen abfrage, ob adcwert=0 dann leuchtet keine der leds an pb5-7, jedoch wenn ich frage adcwert >= 9 leuchtet pb7, hedoch an adcwert>0 leuchtet nichts. also müsste der wert zw. 0 und 1 liegen. soll jedoch zw. 1 und 1024 sein.

    Grüße
    Thomas

  4. #4
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    22.05.2005
    Ort
    12°29´ O, 48°38´ N
    Beiträge
    2.731
    Doch, Du musst auf Eingang stellen, sonst kommt nix rein an den ADC, und Du misst nur 0 oder 1, evtl. noch wenn der Pullup aktiviert ist 1023.

  5. #5
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    19.03.2005
    Ort
    Villach
    Alter
    33
    Beiträge
    995
    Alos jetzt hab ich DDRA = 0x00; in die initavr am anfang geschrieben. doch es hat nichts gebracht.

    normalerweise ist das ja shcon auf eingang, oder? alles ist auf 0 wenns nit anders programmiert wird.

  6. #6
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    22.05.2005
    Ort
    12°29´ O, 48°38´ N
    Beiträge
    2.731
    Ja, stimmt auch wieder,
    wie schaut denn deine externe Beschaltung aus ?
    Wenn Du interne REF-Spannung(2,56V) hast, sollte da ein Kondensator aussen dran sein.

    Evtl. liegt es aber auch an deiner If-Abfrage, Du setzt anfangs alle Ausgänge auf 1, kleiner 0 kann der Wert eigentlich nicht werden, dann sollten die Ausgänge auf 0 gehen, wenn der Wert zwischen 0 und 800 liegt
    Mach evtl. mal die Pause am Ende etwas länger, damit man etwas mehr Zeit hat zu sehen was da genau passiert, sonst kanns sein das es nur so ausschaut als wenn die immer an oder aus sind

    Aber zeig erstmal Deine Schaltung, dann schau'ma weiter.

  7. #7
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    19.03.2005
    Ort
    Villach
    Alter
    33
    Beiträge
    995
    Hallo,

    auf http://embedit.de/content/view/47/26/ ist eine pdf mit der beschreibung.
    ein kondensator ist dran.

    Die zeile wo pb5-7eingeschalten werden (PORTB |= (1<<PB7) | (1<<PB5) | (1<<PB6); ) hab ich shcon rauskommentiert. das ist nicht schuld.

    Spielt die reihenflger wie ich die Register setze eine rolle? wie kann ich es wenns eine rolle spielt den code so schnell wie möglich durchführen lassen (also so wenig wie möglich register setzen zu müssen pro durchlauf).

    Ihrkönnt mir auch helfen wenn ihr mir funktionierenden singleconversation c code von euch wo rauskopiert den ich dann vergleichen kann.

    ich habe die avr.c etwas verändert, jedoch soll dies nicht die entgültige lösung sein:
    Code:
    #include <avr/io.h>
    #include <util/delay.h>    // definiert _delay_ms()
    
    void adcstart(void);
    void adcstop(void);
    
    void adcstart(void) {
    // 	ADCSRA |= ((1<<ADEN) | (1<<ADPS0) | (1<<ADPS1) | (1<<ADPS2));//ADPS0-2(Vorteiler 128), ADEN (Enable)
    // 	
    // 	ADMUX = 0;
    // 	ADMUX |= (1<<REFS1) | (1<<REFS0);
    // 	
    // 	ADCSRA |= (1<<ADSC);              	// eine ADC-Wandlung als Dummy zum warmlaufen
    // 	while ( ADCSRA & (1<<ADSC) ) {
    // 	;     					// auf Abschluss der Konvertierung warten 
    // 	}
    }
    
    void adcstop(void) {
    	ADCSRA &= ~(1<<ADEN);
    }
    
    uint16_t adcget(uint8_t kanal) {
    	
    
    ADMUX =  0xC0; //0b1100 0000
    ADCSRA = 0xC7;	//0b1100 0111
    
    
    uint16_t ergebnis = 0;
    
    // 	ADMUX = kanal;            		// Kanal waehlen
    // 	ADMUX |= (1<<REFS1) | (1<<REFS0);	// interne Referenzspannung nutzen 
    // // 	ADCSRA |= (1<<ADEN);
    // 	ADCSRA |= (1<<ADSC);			// eine Wandlung "single conversion"
    	while ( ADCSRA & (1<<ADSC) );	 // auf Abschluss der Konvertierung warten
    	
    	ergebnis=ADC;
    	adcstop();
    	return ergebnis;
    }
    Was da passiert, außer dass es nicht funktioniert kann ich leider nicht mehr sagen da mein akku leer wurde.

    mfg
    Thomas

  8. #8
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    22.05.2005
    Ort
    12°29´ O, 48°38´ N
    Beiträge
    2.731
    Hast Du schon die Wiki Seite angeschaut:
    https://www.roboternetz.de/wissen/in.../ADC_%28Avr%29
    Da ist doch ein schönes C-Beispiel drin, evtl. kann man das mit dem aktivieren des ADC und das beenden weglassen, so wie das bei Deinem Beispiel schon ist.
    Den Prescaler noch richtig einstellen, schaut bei Dir auch schon gut aus mit den 128 bei 14,7456MHz.

    Wie hast Du das zu messende an den AVR angeschlossen, evtl. läuft da der Strom nicht so wie Du meinst ?

  9. #9
    Erfahrener Benutzer Robotik Visionär Avatar von Hubert.G
    Registriert seit
    14.10.2006
    Ort
    Pasching OÖ
    Beiträge
    6.220
    Habe das Programm mal gecheckt. Du musst dir das Prog wieder teilen, ich habe es zusammengefasst, die Pin verändert da bei mit dort LEDs drauf hängen und die if-Schleife geändert. Dann das mit einem Poti probiert, die drei LED laufen je nach Eingangsspannung hin und her. Ich hoffe es ist so wie du es dir vorgestellt hast.

    Hubert
    Angehängte Dateien Angehängte Dateien
    • Dateityp: c adc.c (1,9 KB, 13x aufgerufen)

  10. #10
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    19.03.2005
    Ort
    Villach
    Alter
    33
    Beiträge
    995
    Danke an alle. Besonders Hubert. Deine Datei ging sofort.

    Grüße
    Thomas

Berechtigungen

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

Labornetzteil AliExpress