-
        

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

Thema: Propleme bei mehreren ADC Eingänge

  1. #1
    Benutzer Stammmitglied Avatar von Jackeder
    Registriert seit
    08.02.2015
    Ort
    Chemnitz, Germany
    Beiträge
    51

    Propleme bei mehreren ADC Eingänge

    Anzeige

    Hallo zusammen,

    ich versuche mich seit paar Tagen mit ADC Wandler.
    Ich schreibe in C und nutze Atmelstudio 6. Zum testen habe ich mir ein kleines Kästchen mit einem ATmega8 und einem 20x4 Display gebastelt.

    Vor ein paar Tagen habe ich einen alten analogen Joystick (boeder P-7 Joystick) auf dem Speicher gefunden und wollte diesen nun mit dem Atmega8 über ADC auslesen und vorerst auf dem LCD die Werte anzeigen lassen.
    Allerdings musste ich ersteinmal paar Kabel umlöten, da die beiden 50Kohm Potis keine Masse hatten. 2. hab ich noch beide Tasten mit einem Pull-UP Wiederstand versehen.

    Joystick ATmega8
    X_Achse -- -- -- -- > PC1
    Y_Achse -- -- -- -- > PC2
    Taste A -- -- -- -- > PD2 (INT0)
    Taste B -- -- -- -- > PD3 (INT1)

    Tasten abfragen funktioniert super, nur die ADC_werte spinnen irgendiwe rum, wenn ich beide auslesen will. Einzeln auslesen ist ohne Proplem so wie ich das wünsche.
    hier mal meine AT8adc.h Datie, denke mal das ich irgendwo einen Fehler habe oder es doch auf diese Weise nicht funktioniert.
    Code:
    /*
     * AT8adc.h
     *
     * Created: 18.04.2015 17:29:41
     *  Author: Hendrik
     */ 
    
    
    #define F_CPU 8000000UL
    #include <avr/io.h>
    #include <util/delay.h>
    #include <stdlib.h>	// für dtostrf
    
    // Variablen
    
    unsigned long ADC_result;
    double XAchse;	// double wegen return "XAchse" ins Hauptprogramm
    double YAchse;
    volatile int x;
    char xstr[4];
    char ystr[4];
    
    void initADC (void)
    {
    	// ADC Konfigurieren
    	
    	ADCSRA |= (1<<ADEN); // ADC-Wandler aktivieren
    	ADCSRA |= (1<<ADPS1);// Teiler 64 (zw. 50khz und 200khz)
    	ADCSRA |= (1<<ADPS2);// Teiler 64 (8000000hz / 64 = 125000hz
    	
    }
    // X-Achse messen am ADC1
    double getADC1 (void)
    {
    	ADMUX = 0x01;	// ADC1 selekt
    	ADMUX |= (1<<REFS0); // Referenzspannung = VCC = 5Volt
    	ADC_result = 0;
    	
    	//for (unsigned int i=0; i<8; i++)
    	//{	
    		ADCSRA |= (1<<ADSC);        // single conversion
    		while (ADCSRA & (1<<ADSC)) // warten bis ADC fertig
    		ADC_result = ADCW;
    		//ADC_result += ADCW;		   // adieren der conversion
    	//}
    	XAchse = ADC_result;
    	//XAchse = ADC_result/8;		 // 8mal messen, addieren und durch 8 teilen für Mittelwert
    	dtostrf(XAchse, 4, 0, xstr);
    	lcd_setcursor(5,2);
    	lcd_string(xstr);
    	x = XAchse-512;					// umwandeln  in -512 > 0 < +512
    	lcd_setcursor(15,2);
    	dtostrf(x,4,0,xstr);
    	lcd_string(xstr);
    	return XAchse;
    }
    // Y-Achse messen am ADC2
    double getADC2 (void)
    {
    	ADMUX = 0x02;			// ADC2 selekt
    	ADMUX |= (1<<REFS0);    // Referenzspannung = VCC = 5Volt
    	ADC_result = 0;			// ADC_result zurücksetzen
    	
    	//for (unsigned int i=0; i<8; i++)
    	//{
    		ADCSRA |= (1<<ADSC);        // single conversion
    		while (ADCSRA & (1<<ADSC))  // warten bis ADC fertig
    		ADC_result = ADCW;		    // adieren der conversion
    	//}
    	YAchse = ADC_result;		 // 8mal messen, addieren und durch 8 teilen für Mittelwert
    	dtostrf(YAchse, 4, 0, ystr);
    	lcd_setcursor(5,3);
    	lcd_string(ystr);
    	return YAchse;
    }
    Im Main Programm frage ich dann wie folgt ab

    Code:
    while(1)
        {
    		getADC1();
    		_delay_ms(300);
    		getADC2();
    		_delay_ms(300);
        }
    Die 300 ms hab ich nur rein genommen um zu sehen was das Proplem sein könnte. Lässt sich jetzt schlecht erklären, aber die beiden werte springen wild hin und her und lassen sich nicht zur jeweiligen Achse zuordnen.

    Würde mich freuen wenn jemand mir auf die Sprünge helfen könnte und ne Idee hat.

    Vielen Dank Hendrik

  2. #2
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    21.06.2011
    Ort
    Dresden
    Beiträge
    170
    Hi,
    evtl. ein kleines delay zwischen MUX-Einstellung und ADC-Start.
    mfg
    Achim

  3. #3
    Benutzer Stammmitglied Avatar von Jackeder
    Registriert seit
    08.02.2015
    Ort
    Chemnitz, Germany
    Beiträge
    51
    gerade versucht, _delay_MS(50); eingefügt vor Single Messung ... leider Ergebnis das gleiche

    ""fast wie im wahren Leben, jeder macht was er will und keiner was er soll""

  4. #4
    Unregistriert
    Gast
    AVCC angeschlossen?

  5. #5
    Benutzer Stammmitglied Avatar von Jackeder
    Registriert seit
    08.02.2015
    Ort
    Chemnitz, Germany
    Beiträge
    51
    ja hab ich , sag ja , einzeln messen von ADC1 oder ADC2 geht und wird auch richtig angezeigt, beide zusammen messen wirds Chaos.
    Wenn ich Joystick Hebel nach oben bewege liegen am PC2(ADC2) 5Volt an, auf dem LCD zeigt ADC2: 1023 an, was ja richtig ist, allerdings wechselt ADC1: auch ständig von 492 auf 1023 wieder auf 492....

  6. #6
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    03.09.2009
    Ort
    Berlin (Mariendorf)
    Beiträge
    938
    ADC-Eingänge der Microcontroller sind oft relativ nierderohmig, im Bereich weniger Kiloohm. Ein 50k-Poti als Quelle ist da eigentlich ungünstig.
    Abhilfe ist einerseits möglich durch das bereits beschriebene Delay zwischen MUX-Umschaltung und Start der Messung, um ausreichend Samplingzeit zu gewähren.
    Zum anderen kann ein Pufferkondensator pro Kanal, der sich beständig auf den aktuellen Spannungswert des Kanals auflädt, die effenktive Impedanz der Quelle merklich reduzieren, weil er binnen kurzer Zeit den internen Samplingkondensator des ADC auf (fast) gleichen Pegel bringen kann.

  7. #7
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    07.04.2015
    Beiträge
    196
    Ich frag mal ganz dumm:
    while (ADCSRA & (1<<ADSC)) // warten bis ADC fertig

    muss da nicht ein Semikolon hinter? Soll doch warten, bis ADSC zurückgesetzt ist und dann erst die folgende Codezeile zum Lesen des AD-Wertes ausführen. Ohne Semikolon wird doch die folgende Zeile oder der durch {} eingefasste folgende Block mit dem while ausgeführt, oder bin ich jetzt ganz im falschen Film?
    Geändert von Holomino (22.04.2015 um 08:45 Uhr)

  8. #8
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    06.08.2008
    Ort
    Graz
    Beiträge
    500
    Du musst mal die Variablentypen gleich ziehen:
    es wird ein "double" mit "int" und "unsigned long" vermischt (Fließkommazahlen mit vorzeichenbehafteten Integer mit nicht vorzeichenbehafteten Integer), da sollte der Compiler doch schon einige Warnings anzeigen.
    Meines wissens ist ein "int" nicht exakt definiert, es kann je nach Compiler ein short oder sonstwas sein.

    Von der Rechengenauigkeit her kommst mit "short" Variablen oder "int16_t" aus, die haben einen Zahlenbereich von −32.768 bis +32.767.

    dtostrf: schaut etwas knapp aus, probier mal mehr Speicher bereitzustellen (zB char ystr[6] )

    Add: AT8adc.h
    *.h bedeutet einen Header Datei, da steht schon sicher mal kein Code drinnen, sondern nur zB Definitionen von Funktionen: "extern void lcd_home(void);"
    erst in einer *.c Datei steht dann die genaue Funktion:
    void lcd_home(void)
    {
    lcd_command(1<<LCD_HOME);
    }

    So gesehen sollte das Programm nie funktionieren, oder ist es doch unter *.c gespeichert?

    LG!
    alles über meinen Rasenmäherroboter (wer Tippfehler findet darf sie gedanklich ausbessern, nur für besonders kreative Fehler behalte ich mir ein Copyright vor.)

  9. #9
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    07.03.2011
    Beiträge
    1.398
    Zitat Zitat von Holomino Beitrag anzeigen
    Ich frag mal ganz dumm:
    while (ADCSRA & (1<<ADSC)) // warten bis ADC fertig

    muss da nicht ein Semikolon hinter? Soll doch warten, bis ADSC zurückgesetzt ist und dann erst die folgende Codezeile zum Lesen des AD-Wertes ausführen. Ohne Semikolon wird doch die folgende Zeile oder der durch {} eingefasste folgende Block mit dem while ausgeführt, oder bin ich jetzt ganz im falschen Film?
    Da rächt sich die "dumme" Angewohnheit, leere while-Schleifen in einer Zeile und ohne geschweifte Klammern zu schreiben.
    Code:
    ADCSRA |= (1 << ADSC);        // single conversion
    while (ADCSRA & (1 << ADSC)) // warten bis ADC fertig
    ADC_result = ADCW;
    //ADC_result += ADCW;
    da ist schlecht zu erkennen, was da abgeht, da nun auch noch der Kommentar dicht dahinter steht. Auch beim Lesen ist schlecht zu erkennen, daß es um einen Loop geht, insbesondere wenn man in ein paar Wochen an den Code noch mal ran muß. Und ohne Klammern wird da ganz schnell mal eine Semikolon reingeschrieben, obwohl die nächste Zeile eigentlich in die Schleife gehört. wenn man das grundsätzlich so schreibt:
    Code:
    ADCSRA |= (1 << ADSC);        // single conversion
    while (ADCSRA & (1 << ADSC)) { // warten bis ADC fertig
          ;
    }
    ADC_result = ADCW;
    //ADC_result += ADCW;
    passieren nicht so leicht Fehler und man kann ganz schnell noch einen Print zum Debuggen oder einen Nop für einen Breakpoint einfügen und auch wieder herauskommentieren, ohne daß die Programmstruktur kaput geht.

    In diesem Fall wird hier während der Konvertierung dauernd das Resultat ausgelesen, ob das dem ADC gefällt, weiß ich nicht.

    Zitat Zitat von damfino Beitrag anzeigen
    ]Meines wissens ist ein "int" nicht exakt definiert, es kann je nach Compiler ein short oder sonstwas sein.
    Es ist schon definiert, mindestens 16 Bit. Wenn aber die CPU schneller mit 64 Bit umgehen kann, kanns auch mal 64 Bit sein. Short ist da schon eher nicht definiert. Für einen Joystick reicht aber auch ein int8_t, selbst die Auflösung kann man mit den Fingern gar nicht erreichen.

    MfG Klebwax
    Strom fließt auch durch krumme Drähte !

  10. #10
    Benutzer Stammmitglied Avatar von Jackeder
    Registriert seit
    08.02.2015
    Ort
    Chemnitz, Germany
    Beiträge
    51
    Zitat Zitat von Holomino Beitrag anzeigen
    Ich frag mal ganz dumm:
    while (ADCSRA & (1<<ADSC)) // warten bis ADC fertig

    muss da nicht ein Semikolon hinter? Soll doch warten, bis ADSC zurückgesetzt ist und dann erst die folgende Codezeile zum Lesen des AD-Wertes ausführen. Ohne Semikolon wird doch die folgende Zeile oder der durch {} eingefasste folgende Block mit dem while ausgeführt, oder bin ich jetzt ganz im falschen Film?

    stimmt das Semikolon hab ich vergessen, sorry und danke ... wundert mich das ATmelstudio da nicht gemeckert hat ^^

Seite 1 von 2 12 LetzteLetzte

Ähnliche Themen

  1. Mehrere (unabhängige) ADC-Eingänge am 16F876 benutzen?
    Von PICBeginner im Forum PIC Controller
    Antworten: 3
    Letzter Beitrag: 07.03.2009, 13:31
  2. ADC bei TC1796b
    Von comingone im Forum Microcontroller allgemeine Fragen/Andere Microcontroller
    Antworten: 0
    Letzter Beitrag: 11.08.2008, 20:22
  3. Propleme beim I2C-Bus Aufbau
    Von Bluesky im Forum Elektronik
    Antworten: 2
    Letzter Beitrag: 14.02.2007, 15:11
  4. ADC Eingänge schützen --- Hier ein Vorschlag
    Von Kaiser-F im Forum AVR Hardwarethemen
    Antworten: 1
    Letzter Beitrag: 22.12.2005, 15:13
  5. [ERLEDIGT] Kommastellen bei ADC
    Von Pfiff-1 im Forum PIC Controller
    Antworten: 5
    Letzter Beitrag: 06.08.2005, 22:20

Stichworte

Berechtigungen

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