-
        

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

Thema: 8 ADC-Kanäle schnell auslesen

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    27.11.2004
    Ort
    Heilbronn
    Alter
    33
    Beiträge
    85

    8 ADC-Kanäle schnell auslesen

    Anzeige

    Hallo,

    ich möchte mit einem at90can 8 ADC Kanäle so schnell auslesen:

    Der ADC-Takt ist 125 kHz. (16.000.000 Hz / 128 Prescaler)

    In dem AVRGCC-Tutorial wird geraten eine Dummy-Messung durchzuführen. Gilt das nur nachdem ich den ADEN gesetzt hab oder auch beim wechseln der Kanäle?


    Der Code ist teilweise aus dem AVRGCC-Tutorial
    Code:
    	char i=0;
    	
    	ADMUX = 0x40; // ADC0
    	ADCSRA |= (1<<ADSC);
    	/* Test AD-Wandlung durchführen */
    
    	while (ADCSRA & (1<<ADSC))
    	{
    		;     // Auf Abschluss der Konvertierung warten
    	}
      	adc_werte[0] += ADCL;
    	adc_werte[0] += (ADCH<<8);
    
    	adc_werte[0] =0;
    	/* Test-Wert löschen */
     
    	for(i=0; i<5; i++)					// 5 Wandlungen durchführen
    	{
    		ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion	"
        	while (ADCSRA & (1<<ADSC))
    		{
    			;   // Auf Abschluss der Konvertierung warten
        	}
    
        	adc_werte[0] += ADCL;
    		adc_werte[0] += (ADCH<<8);
    	}
    	adc_werte[0] /= 5;					// Summe durch fünf teilen = arithm. Mittelwert
    	i=0;
    
    	ADMUX = 0x41; // ADC1
    	ADCSRA |= (1<<ADSC);
    	/* Test AD-Wandlung durchführen */
    
    	while (ADCSRA & (1<<ADSC))
    	{
    		;     // Auf Abschluss der Konvertierung warten
    	}
      	adc_werte[1] += ADCL;
    	adc_werte[1] += (ADCH<<8);
    
    	adc_werte[1] =0;
    	/* Test-Wert löschen */
     
    	for(i=0; i<5; i++)					// 5 Wandlungen durchführen
    	{
    		ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion	"
        	while (ADCSRA & (1<<ADSC))
    		{
    			;   // Auf Abschluss der Konvertierung warten
        	}
    
        	adc_werte[1] += ADCL;
    		adc_werte[1] += (ADCH<<8);
    	}
    	adc_werte[1] /= 5;					// Summe durch fünf teilen = arithm. Mittelwert
    	i=0;
    // usw.

  2. #2
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    7.551
    Lies Dir doch mal den Absatz: Changing Channel or Reference Selection im Doc zu Deinem Controller durch. Dort wird einiges geschrieben zu Vorgehens- und Vorsichtsmaßnahmen beim Multiplexen der Eingänge.
    Ciao sagt der JoeamBerg

  3. #3
    Benutzer Stammmitglied
    Registriert seit
    27.11.2004
    Ort
    Heilbronn
    Alter
    33
    Beiträge
    85
    Hallo,

    danke für den Hinweis.

    Laut Datenblatt sind Dummy Messungen um den ADC "warmlaufen" zu lassen überhaupt nicht nötig - zumindest steht da nichts davon!

    Die erste Wandlung dauert zwar doppelt so lang wie die alle folgenden ( so lange der ADC nicht abgeschatet wird) aber ansonsten passiert da laut Datenblatt nichts mehr ungewöhnliches.

  4. #4
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    7.551
    Hi, almic,

    ... Die erste Wandlung dauert zwar doppelt so lang ...
    Betrifft das nicht die erste Wandlung nach dem Umschalten des ADC-Eingangs von einem Pin auf den anderen? Das wäre dann ja beim Multiplexen doch wieder häufiger. Aber ich bin mir da nicht gaaanz sicher.

    In solchen Fällen probier ich das auch schon mal auf (m)einer Flash- und Experimentierplatine aus.
    Ciao sagt der JoeamBerg

  5. #5
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Die Längere Wandlungszeit gilt nicht nach dem Kanalwechsel. Nach dem Kanalwechsel macht eine dummymessung sinn, wenn die Quelle einen hohen Widerstand hat (mehr als etwa 20 KOhm). Der AD Wandler hat sonst noch etwas Gedächnis an den vorherigen Kanal.
    Man sollte etwas Wartezeit einplanen nach dem einschalten der internen Referenz oder dem umschalten der Referenz, besonders in Richtung kleinerer Spannung. Da reicht dann aber oft auch eine Dummymessung nicht aus.

    Zum Programm:
    Für eine Schnelle Messung sollte man den AD duchgängig laufen lassen, also nicht jedesmal als single conversion starten. Das geht auch wenn man die Kanäle umschaltet. Wenn es sein muß könnte man wohl auch auf 250 kHz AD Takt gehen, so groß viel größer werden dadurch die Fehler noch nicht. Zur Mittelwertbildung sind 4 oder 8 Werte oft günstiger, denn da geht das Teilen schneller. Dabei macht es aber duchaus Sinn die Summe von 4 Werten nur durch 2 zu Teilen und das Ergebnis dann als Wert mit 11 Bit Auflösung zu sehen. Entsprechend Macht es Sinn von 16 Werten 12 Bit Auflösung übrig zu lassen.
    Auf den ADC wert kann man auch gleich als 16 bit wert zugreifen:
    adc_werte[0] = ADC;
    reicht zum auslesen aus, den Rest erledigt der Compiler.
    Das aufsummieren sollte man wohl auch besser in einer localen Variable machen, und nicht unbedingt im array.

  6. #6
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    25.11.2003
    Beiträge
    1.111
    Du musst den Channel >1 ADC Takt vor der Conversion wählen!!!
    Bei Dir sind das immerhin 128 Prozessortakte, das geht also nicht gut.
    Nebenbei brauchst Du in C nicht High und Low Byte getrennt zu kopieren, "temp = ADC;" geht auch...
    Gruß

  7. #7
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    7.551
    Zitat Zitat von Besserwessi
    ... Zum Programm: ...
    Ach herrje, schauderhaft was ich alles in Nu (merische) Ma (thematik) vergessen habe. Schlimm schlimm.
    Ciao sagt der JoeamBerg

  8. #8
    Benutzer Stammmitglied
    Registriert seit
    27.11.2004
    Ort
    Heilbronn
    Alter
    33
    Beiträge
    85
    Hallo,

    ich bleibe mal bei der idee mit der Einzelmessung, im zweifelsfall kann ich später noch im freilaufenden Modus wechseln.

    Hab jetzt noch eine Warteschleife eingefügt und die Wertzuweisung geändert.

    Code:
    	char i=0;
    	unsigned char volatile j=0;	
    	unsigned short adc_temp=0;
    
    	ADMUX = 0x40; // ADC0
    
    	for(j=0; j<15; j++) { }	// 10us warten (etwas mehr als ein ADC-Takt)
    	
    	ADCSRA |= (1<<ADSC);
    	/* Test AD-Wandlung durchführen */
    
    	while (ADCSRA & (1<<ADSC))
    	{
    		;     // Auf Abschluss der Konvertierung warten
    	}
      	adc_temp += ADC;
    	adc_temp =0;
    	/* Test-Wert löschen */
     
    	for(i=0; i<4; i++)					// 4 Wandlungen durchführen
    	{
    		ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion	"
        	while (ADCSRA & (1<<ADSC))
    		{
    			;   // Auf Abschluss der Konvertierung warten
        	}
    
      		adc_temp += ADC;
    	}
    	adc_temp /= 2;					// Summe durch fünf teilen = arithm. Mittelwert
    	adc_werte[0] = adc_temp;
    	i=0;
    Die Frage ist jetzt:

    Ist das Programm schneller wenn ich das in eine Funktion packe und die Funktion 8 mal starte oder ist es schneller wenn es einfach (copy&paste sein dank) 8mal hintereinander steht?

  9. #9
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    7.551
    Hi, almic,

    ... Programm schneller ... die Funktion 8 mal starte ...
    Leider bin ich nicht der große C-Freak. Allerdings weiß ich, dass beim Aufruf einer Funktion eine ganze Menge "Verwaltungsarbeit" vom Compiler gemacht wird: Register retten und wieder zurückschreiben. Daher hatte ich mal in einem Programm die "copy&paste"-Variante gemacht und meine Zeitmessung ergab einen klaren Vorteil. Sieht halt unprofessionell aus, aber wenns was bringt . . . .

    Du kannst Dir dazu selbst ein Bild dazu machen: schau Dir mal den Code nach dem Übersetzen an. Der steht in einer Datei *.lls im Unterordner "default" Deines Projektordners. Beim Lesen der *.lls macht sich übrigens eine sorgfältige Kommentierung sehr bezahlt.

    Viel Erfolg.
    Ciao sagt der JoeamBerg

  10. #10
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    25.11.2003
    Beiträge
    1.111
    Sorry! Hab mich vertan: Die Sache mit dem einen ADC Takt gilt nur, wenn man den Channel wechselt, nachdem SingleConversion ausgelöst wurde, bei Dir geschieht es ja vorher! Du brauchst also nicht zu warten. Ich hoffe, ich hab keine Verwirrung gestiftet...
    Allerdings hilft es die Optimierung im Compiler einzuschalten. Und der würde Deine leere Warteschleife ohnehin rausschmeißen.
    Aber wie schon gesagt, Funktiosaufruf kostet viel Zeit, also lieber eine Funktion schreiben.
    Du kannst noch ein bisschen Zeit sparen, indem Du die nächste Konvertierung startest, bevor Du das ADC Register ließt, denn das letzte Ergebnis steht solange dort an, bis es vom nächsten überschrieben wurde.
    Gruß

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

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