A/D Wandler Problem

Gast #126796
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 ?
Gast #126800
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);
}
Gast #126804
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
Gast #126805
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...
Gast #126806
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
Gast #126808
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren