Hallo, ich versuche mich grade daran, den ADC vom Mega 128 in Gang zu bringen. Nach langem lesen vom Forum und dem Tutorial bin ich zu folgenden Quellcode gekommen: #include <avr/io.h> uint8_t i; uint16_t result = 0; void adc_init_ch0(void) // Initialisierung von ADC-Kanal 0 { ADMUX = 0x00; // Spannungsmessung an PA0 ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); // ADC aktiviert, ADC Freilaufmodus, Vorteiler auf 128 ADMUX |= (1<<REFS0)|(1<<REFS1); // Interne Referenzspannung nutzen SFIOR = 0; // Spezialfunktionen Ausschalten } void main(void) { adc_init_ch0(); ADCSRA |= (1<<ADSC); while (ADCSRA & (1<<ADSC)) // Dummy-Messung um den ADC warmlaufen zu lassen { ; } for(i=0;i<2;i++) { ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion" while ( ADCSRA & (1<<ADSC) ) // auf Abschluss der Konvertierung warten { ; } result += ADCW; / Wandlungsergebnisse aufaddieren } ADCSRA &= ~(1<<ADEN); // ADC deaktivieren result /= 2; // Summe durch zwei teilen = arithm. Mittelwert } Testweise versuch ich den gemessenen Wert mit einem Referenzwert zu vergleichen und lasse je nachdem ob er höher oder niedriger als der gemessene Wert ist, eine LED leuchten. Leider bekomme ich hierbei keine nachvollziehbaren Ergebnisse. Könnt Ihr mir sagen, ob der Code bis jetzt so richtig ist, bzw. was ich daran verbessern kann? mfg Florian
> Testweise versuch ich den gemessenen Wert mit einem Referenzwert zu > vergleichen und lasse je nachdem ob er höher oder niedriger als der > gemessene Wert ist, eine LED leuchten. > Leider bekomme ich hierbei keine nachvollziehbaren Ergebnisse. Könnt Ihr > mir sagen, ob der Code bis jetzt so richtig ist, bzw. was ich daran > verbessern kann? Der Code ist nicht vollständig. * wo ist die Auswertung deines gemittelten Wertes? * wo werden die LEDs abhängig vom Ergebnis gesetzt? * warum läuft das (Test-)Programm nicht in einer Schleife? * was meinst du mit "keine nachvollziehbaren Ergebnisse"? Gruß, Magnetus
Aufgerufen wird die Messung durch Übermittlung eines Zahlenwertes per RS232. if (UDR1=='4') { uart_puts (status4); // Messung aktiviert adc_ch0(); // ruft Unterprogramm adc auf } if (UDR1=='5') { uart_puts (status5); // Messung gestoppt adc_ch1(); // ruft Unterprogramm adc auf } das ganze läuft in einer Endlosschleife. Es soll also bei Zeichenübermittlung immer eine Messung durchgeführt werden. mit adc_ch0 bzw. adc_ch1 wird das oben schon geschriebene aufgerufen. void adc_ch0(void) { adc_init_ch0(); ADCSRA |= (1<<ADSC); while (ADCSRA & (1<<ADSC)) // Dummy-Messung um den ADC warmlaufen zu lassen { ; } for(i=0;i<2;i++) { ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion" while ( ADCSRA & (1<<ADSC) ) // auf Abschluss der Konvertierung warten { ; } result += ADCW; // Wandlungsergebnisse aufaddieren } ADCSRA &= ~(1<<ADEN); // ADC deaktivieren result /= 2; // Summe durch zwei teilen = arithm. Mittelwert if (result < (2*1023)/5) batt_blinky(); if (result > (2*1023)/5) uart_blinky(); } hier mal nur für Kanal 0. Mit keine nachvollziehbaren Ergebnisse meinte ich, das mal batt_blinky() und mal uart_blinky() aufgerufen wird, obwohl immer dieselbe Spannung am ADC hängt. Im Moment ist das zu Testzwecken einfach Masse.
Da würde ich dir doch mal vorschlagen, das ganze abzuspecken, extrem zu vereinfachen und den UART (den du offensichtlich schon in Betrieb hast) dazu zu benutzen, die Messergebnisse auszugeben. Wenn du das nicht willst, würde ich mal den Messwert komplett auf einen Port ausgeben. Mit extrem abspecken meine ich: Nur einen Kanal messen Eine simple Schleife in main, die * den ADC anwirft * auf das Ergebnis wartet * das Ergebnis auf Port oder UART ausgibt
> ADCSRA &= ~(1<<ADEN); // ADC > deaktivieren Ich seh zwar, dass du den ADC deaktivierst, ich seh aber nirgends wo du den ADC aktivierst.
Karl heinz Buchegger wrote: >> ADCSRA &= ~(1<<ADEN); // ADC >> deaktivieren > > Ich seh zwar, dass du den ADC deaktivierst, ich seh aber nirgends > wo du den ADC aktivierst. Das macht er gleich zu Beginn... void adc_ch0(void) { adc_init_ch0(); ... ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); // ADC aktiviert ... }
Magnus Müller wrote: > Das macht er gleich zu Beginn... >
1 | > ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); // ADC aktiviert |
2 | >
|
...mit dem höchstmöglichen Prescaler. Wenn der ATmega128 mit seinen standardmäßigen 1 MHz läuft, tickert der ADC dann mit 8 kHz. Da wäre es kein Wunder, dass die Ergebnisse nicht mehr zuverlässig sind. Nicht nur, dass eine Messung endlos lange dauert, ich wage zu bezweifeln, dass die sample&hold-Schaltung im Eingang die Spannung so lange festklemmen kann.
Hallo, so ich hab den Code jetzt mal ganz zusammengekürzt und lasse jetzt eine LED angehen bzw. ausgehen, wenn ich 2,5V bzw. 0V anlege. Das funktioniert soweilt. Also denk ich mal, das mein erster Code wohl zu kompliziert war und ich nie zum Messen gekommen bin
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.