Forum: Mikrocontroller und Digitale Elektronik A/D Wandler Problem


von bruzzler (Gast)


Lesenswert?

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 ?

von Dirk (Gast)


Lesenswert?

Hi,

mit wieviel Mhz laeuft der Mega? Welchen Prescalerwert hast du fuer den
ADC?

Mfg

Dirk

von bruzzler (Gast)


Lesenswert?

@Dirk

Precaler ist 16 (ADPS2 Bit gesetzt)

bei 1Mhz

von ---- (Gast)


Lesenswert?

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).

von bruzzler (Gast)


Lesenswert?

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);
}

von ...HanneS... (Gast)


Lesenswert?

Lässt du dem ADC zwischen Auswahl der Quelle (ADMUX) und Auslesen des
Resultats genug Zeitn zum Messen?

von ...HanneS... (Gast)


Lesenswert?

Du änderst ADMUX direkt vor dem Auslesen, das kann nicht gehen...

von bruzzler (Gast)


Lesenswert?

@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)

von bruzzler (Gast)


Lesenswert?

@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

von ...HanneS... (Gast)


Lesenswert?

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...

von bruzzler (Gast)


Lesenswert?

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

von bruzzler (Gast)


Lesenswert?

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 ?

von bruzzler (Gast)


Lesenswert?

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.

von ...HanneS... (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.