Ich möchte folgendes machen: Ich frage über den USART bei einem MEGA8 nacheinander die Analogen Eingänge ab. Das heisst ich dem uC zB. eine '0' und der uC schickt mir zB. '1023' zurück. Das funktioniert auch soweit. Jetzt das Problem: Ich frage den uC über ein Programm permanent ab. Komischerweise scheint die Spannung alle 5s zusammenzubrechen und sich dann wieder zu erholen obwohl ich die Spannung am Analogeingang konstant halte. Zuerst dachte ich das der USART Interrupt den AD Wandler unterbricht und deshal dieser seltsame Effekt auftritt. Aber auch nachdem ich das uC Programm so geändert habe, dass bei Empfang eines Bytes der USART Interrupt abgeschaltet wird und erst nach dem Senden der Antwort wieder angeschaltet wird, ändert sich nichts. Ich bin etwas ratlos. Könnte das ein elektrischer Fehler sein ?
Hi, mit wieviel Mhz laeuft der Mega? Welchen Prescalerwert hast du fuer den ADC? Mfg Dirk
Wenn jetzt einer kommt und dir erzählt, daß der Fehler in Zeile 43 liege, dann will er darauf hinweisen, daß ohne Sourcecode hier wenig zu sagen ist... ----, (QuadDash).
Ja OK ich habs kapiert ! Also USART empfängt Byte.... if (data == '1') { USART_Pause(); ADMUX = _BV(MUX0); ADCSRA = _BV(ADEN) | _BV(ADPS2) | _BV(ADIE); ADCSRA |= _BV(ADSC); } Wenn der ADC fertig ist... SIGNAL (SIG_ADC) { ADCSRA = 0x00; //BV(ADIE) | BV(ADEN); ADMUX = 0x00; x = ADC; itoa(x, buffer, 10); USART_transmit_string (buffer); USART_Weiter(); } hier nochmal die Funktionen Pause und Weiter: void USART_Pause(void) { UCSRB = BV(RXCIE) | BV(TXCIE) | _BV(RXEN) | _BV(TXEN); } void USART_Weiter(void) { UCSRB = _BV(RXCIE) | _BV(TXCIE) | _BV(RXEN) | _BV(TXEN); }
Lässt du dem ADC zwischen Auswahl der Quelle (ADMUX) und Auslesen des Resultats genug Zeitn zum Messen?
@hannes ich denke schon, ich wähle die Quelle und aktiviere dann den ADC-Interrupt. Das Auslesen kommt dann ja erst wenn der Interrupt da ist. (siehe Quellcode oben)
@hannes Wieso nicht ? ADMUX ist doch nur für die Auswahl des ADC Kanals und das Klappt. Nur wenn ich immer wieder alle Kanäle nacheinander auslese kommt es alle 5s zu Problemen. Es klappt also ca. 10-20 mal nacheinander bevor es schiefgeht. Aber falls das trotzdem der Fehler ist, wie mache ich es richtig ? mfg Heinz
Richtig... Und im Interrupt setzt du zuerst ADMUX auf 0 und liest erst danach den ADC aus. ADMUX = 0x00; x = ADC; Das kann gut gehen, muss aber nicht. Ich würde ADMUX erst ändern, wenn ein neuer "Messauftrag" vorliegt. Oder noch besser alle ADC-Quellen reiherum ausmessen und die Werte im SRAM speichern. Wenn UART einen Wert anfordert, dann diesen aus dem SRAM holen... ...HanneS...
Also ich hab das mal abgeändert und ADMUX aus dem Interrupt herausgenommen sieht dann so aus: if (data == '2') { USART_Pause(); ADMUX = 0x00; ADMUX = _BV(MUX1); ADCSRA = _BV(ADEN) | _BV(ADPS2) | _BV(ADIE); //ADC-Interrupt aktivieren (ADIE) ADCSRA |= _BV(ADSC); } SIGNAL (SIG_ADC) { ADCSRA = 0x00; //BV(ADIE) | BV(ADEN); x = ADC; itoa(x, buffer, 10); //wandelt (int) in string um USART_transmit_string (buffer); USART_Weiter(); } ich habs auch gleich getestet, ist aber immer noch dasselbe Problem
Was hat es denn mit diesem Prescaler auf sich ? Laut Datenblatt soll die Eingangsfrequenz zwischen 50kHz und 200 kHz liegen. Meine liegt bei 62,5 kHz. Wäre eine höhere Frequenz besser ?
Danke für die vielen Tips ! Ich konnte das Problem inzwischen lösen. Falls jemand dasselbe Problem hat: Es lag nicht an der Software, sondern an meinem (zu billigen) Netzteil mit dem ich hier arbeite. Offensichtlich kann der ADC mit Wechselspannungsanteilen in der zu messenden Spannung nicht besonders gut umgehen. Ein Kondensator zwischen ADCx und GND und schon funtionierts.
Na der ist bei mir selbstverständlich... (außer, die Messquelle ist recht niederohmig...)
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.