[solved] Arduino UNO (ATmega328P) - ADC: Free Running Mode ist immer aktiv

Hallo zusammen.

Ich bearbeite gerade ein Projekt mit einem Arduino UNO, bei dem ich das Rauschen an einem analogen Eingang auswerten möchte.

In meinem Programm nehme ich aktuell nur das LSB vom ADC und schicke es über USART an den Seriellen Monitor.

Obwohl programmtechnisch eine Single Conversion des ADCs umgesetzt sein sollte (der neue Start einer Conversion in der ISR "USART0_TX_vect" ist auskommentiert), verhält sich das ganze so, als wäre der ADC im Free Running Mode und ich werde mit Nullen/Einsen bombadiert.

Ich habe das Programm auf einem ATmega2560 (STK600) getestet und dort wird wie gewollt nur eine Conversion durchgeführt.

Hier mal mein Code:

#include <avr/io.h>
#include <avr/interrupt.h>

volatile unsigned short ADC_Value;

int main(void)
{
  ADMUX = (0 << REFS1) | (1 << REFS0) | (0 << ADLAR) | (0 << MUX3) | (0 << MUX2) | (0 << MUX1) | (0 << MUX0);

  ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0) | (1 << ADIE) | (1 << ADEN);
  ADCSRA &= ~(1 << ADATE);  

  ADCSRB = (0 << ADTS2) | (0 << ADTS1) | (0 << ADTS0) | (0 << ACME);

  UCSR0C = (1 << UCSZ00) | (1 << UCSZ01);

  UBRR0H = 0;
  UBRR0L = 103;

  sei();

  ADCSRA |= (1 << ADSC);              // Start Conversion

  while(1)
   {
   }
}

ISR(ADC_vect)
{
  ADC_Value = 0;
  ADC_Value = ADCL;
  ADC_Value |= (ADCH << 8);
  UCSR0B = (1  << TXEN0) | (1 << TXCIE0);
  UDR0 = (ADC_Value & 0x1) + '0';
}

ISR(USART0_TX_vect)
{
  UCSR0B = 0;
  //ADCSRA |= (1 << ADSC);
}

Ist mein UNO defekt und das ADATE-Bit ist immer 1? Ich habe es aber auch versucht auszulesen und per Seriellem Monitor zu lesen und dabei kam 0 raus.

Falls von euch einer eine Idee hat, woran das liegen könnte, würde ich mich über eine Antwort freuen.

Mit freundlichen Grüßen
daterio

ISR(USART0_TX_vect)

ISR(USART_TX_vect)
(0 << REFS1)

Macht nicht was du denkst. Damit kann man kein Bit auf 0 setzen. Denn Sinn des Schiebens der 1 hast du nicht verstanden

Am besten einfach weglassen. Braucht man nicht und verwirrt nur

Macht nicht was du denkst.

Ich denke schon, dass ihm klar ist, dass das Bit dann 0 bleibt.
Schließlich funktioniert sein Code ganz prächtig.

Wende auch gerne das Verfahren an.

Denn Sinn des Schiebens der 1 hast du nicht verstanden

Du hast den Sinn des 0 schiebens nicht verstanden.

Am besten einfach weglassen. Braucht man nicht und verwirrt nur

Das weglassen stört bei der Arbeit!
Unterbricht die Ordnung.

Also fein drin lassen.

:roll_eyes:

Ich werde dich in Zukunft einfach ignorieren. Es nervt nur noch

Du weißt ganz genau dass das nur durch das = so geht. Wenn man da |= werden die Bits nicht auf 0 gesetzt. Aber statt dessen kommen nur die üblichen dummen Sprüche.
Vielleicht steht es auch nur dort um es deutlich zu machen und er weiß dass es eigentlich nichts bewirkt. Wenn man es richtig macht kann das ok sein. Aber ich habe schon mehrmals Anfänger gesehen die das falsch gemacht haben und eigentlich was anderes wollten

Ja, du gehst mich seit einiger Zeit öffentlich an.

Hier habe ich ganz klar meine Meinung ausgedrückt.
Nach bestem Wissen und Gewissen.

Wenn du das für dumme Sprüche hältst... da werde ich dich nicht dran hindern können.

Wenn man da |= werden die Bits nicht auf 0 gesetzt.

Wenn den Code untersuchst, dann sollte auffallen, dass dieser Zustand an keiner Stelle dort vorkommt.
Und das ist kein Zufall, sondern kontrollierte Absicht.
Dafür möchte ich wetten!

Nachtrag:

Vielleicht steht es auch nur dort um es deutlich zu machen und er weiß dass es eigentlich nichts bewirkt. Wenn man es richtig macht kann das ok sein. Aber ich habe schon mehrmals Anfänger gesehen die das falsch gemacht haben und eigentlich was anderes wollten

Aha, jetzt ja!
Der Groschen ist gefallen.
Nur weil irgendwer das mal falsch gemacht hat, ist das Prinzip noch lange nicht böse.

combie:

ISR(USART_TX_vect)

Vielen Dank!! Das war's :).
Das ist aber verwirrend, dass es ein UCSR0B gibt, aber dann die Interrupt-Routine dann ohne 0 ist. Aiaiai. Hab extra im Datenblatt beim 328P geschaut, ob ich nicht bspw. UCSRB ohne die 0 verwenden muss. Da dem nicht so war, habe ich über die ISR gar nicht mehr nachgedacht.

Serenifly:
Vielleicht steht es auch nur dort um es deutlich zu machen und er weiß dass es eigentlich nichts bewirkt. Wenn man es richtig macht kann das ok sein. Aber ich habe schon mehrmals Anfänger gesehen die das falsch gemacht haben und eigentlich was anderes wollten

Danke für die Hinweise. Ich weiß schon, dass es keine Auswirkung hat. Ich habe das bloss so gehandhabt, damit man, falls Werte schnell auf 1 geändert werden sollen, man den Code nicht mehr erweitern muss, bzw. dass man im Vergleich mit den Tabellen des Datenblatts direkt sieht, welche Bits welchen Wert haben und man dann direkt auf die Modi etc. schließen kann.

Fein!

Hallo,

wenn man schon dabei ist, dann erwähne ich das ein verodern und dann löschen schon etwas komisch ist.

ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0) | (1 << ADIE) | (1 << ADEN);
ADCSRA &= ~(1 << ADATE);

Man kann gleich konkret zuweisen und damit nur die Bits aktivieren die man benötigt.

Wenn du noch in der Testphase bist kannste alles vereinzeln und damit jedes Bit Zeilenweise auskommentieren.

  ADCSRA = _BV(ADPS2)
           | _BV(ADPS1)
           | _BV(ADPS0)
           | _BV(ADIE)
           | _BV(ADEN)
           ;

Tja und die korrekten Schreibweisen der Interrupt Vectoren findet man leider nur eindeutig im Headerfile.
C:\Program Files (x86)\Arduino\hardware\tools\avr\avr\include\avr
Alle Register- und Bitnamen stehen korrekt im Manual. Bei den Interrupt Vectoren wurde das leider nicht für notwendig gehalten. Warum auch immer. Wenn man das Schema kennt gehts auch, ist dennoch blöd, zugegeben.um auch immer. Wenn man das Schema kennt gehts auch, ist dennoch blöd, zugegeben.

Doc_Arduino:
Hallo,

wenn man schon dabei ist, dann erwähne ich das ein verodern und dann löschen schon etwas komisch ist.

ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0) | (1 << ADIE) | (1 << ADEN);

ADCSRA &= ~(1 << ADATE);

Ganz ehrlich, ich war einfach nur paranoid, weil ich dachte das ADATE Bit ginge nicht auf 0. Deshalb der extra Schritt. Davor hatte ich das nicht drin.

Hallo,

achso. Ne da musste keine bedenken haben. Wenn du klassisch ohne setup und loop programmierst, kannste davon ausgehen das alle Register nach Reset genullt sind.