Forum: Mikrocontroller und Digitale Elektronik AD Wandler auf dem ATmega48


von charly (Gast)


Lesenswert?

Hi ich habe ein Problem mit meinem ADWandler mit meinem ATmega48. Ich 
möchte 2 Kanäle auslesen und zwar 0 und 1 diese habe ich probehalber 
einmal mit VCC und den anderen mit GND beschaltet. Doch egal was ich 
mache ich bekomme für beide Werte immer die selbe Ausgabe, wenn ich mir 
den Wert über die Serielle Schnittstelle ausgeben lasse.

Ich hoffe ihr habt eine Idee wo mein Problem liegt. Ich bin total 
überfragt.

Hier habt ihr meine Register Konfiguration und die entsprechenden 
Funktionen und ein paar Eckdaten.

VCC = 5V
F_CPU = 1MHz interner Takt
1
void adcInit(){
2
3
  ADMUX = 0;
4
  
5
  DIDR0 |= (1 << ADC0D) | (1 << ADC1D);
6
  
7
  //ADC ist freigeschaltet, automatisch getriggert, interrupt ist enabled und prescaler ist bei 8 also 125kHz -> 104µs pro Wandlung
8
  ADCSRA = (1 << ADEN) | (1 << ADIE) | (1 << ADPS1) | (1 << ADPS0);
9
  ADCSRB = 0;
10
  
11
}
12
13
void adcChannel(uint8_t c){
14
  if(channel >= 0 && channel <= 7){
15
    //wähle den Channel aus aber lasse linksbündige einstellung drin 64 setzt ADLAR und die channel Variable die MUX Bits
16
    ADMUX = channel;
17
  }
18
}
19
20
ISR(ADC_vect){  
21
  uint8_t valueHigh = ADCH;
22
  uint8_t valueLow = ADCL;
23
  uint16_t value = valueLow + (valueHigh << 8);
24
  
25
  
26
  uartPutS("Channel ");
27
  uartPutC(channel + 48);
28
  uartPutS(" = ");
29
  uartPutC(value/1000 + 48);  //1000er Stelle
30
  uartPutC(value%1000/100 + 48);  //100er Stelle
31
  uartPutC(value%100/10 + 48);  //10er Stelle
32
  uartPutC(value%10 + 48);  //1er Stelle
33
  uartPutC('\n');
34
  //*/
35
  
36
  if(channel == 1){
37
    channel = 0;
38
  }else{
39
    channel = 1;        
40
  }
41
  
42
  adcChannel(channel);
43
  
44
  ADCSRA |= (1 << ADSC);
45
}

Die Ausgabe im Terminal:

Channel 1 = 0450<\n>
Channel 0 = 0450<\n>

Ich hoffe ihr könnt mir weiterhelfen :) Danke für eure Aufmerksamkeit.

charly

von Karl H. (kbuchegg)


Lesenswert?

Du hast die REFS Bits im ADMUX auf 0. Bist du sicher, dass du eine 
extern über AREF eingespeiste Spannung als Referenz benutzen willst?

Ausserdem: Welche Werte kriegst du, wenn du nicht dauernd den Kanal 
wechselst, sondern immer nur denselben (entweder 0 oder 1)?

von Thomas (kosmos)


Lesenswert?

Im ADMUX Register steht nicht nur die Kanalauswahl da musst du auch die 
Referenz einstellen.

von charly (Gast)


Lesenswert?

Also wenn ich den Kanal wechsel dann, bleibt es bei einem Wert um die 
400 +- 10

VCC und AVcc sind beide direkt an 5V angeschlossen. Keine Kondensatoren. 
Und ich habe noch einen 1k Widerstand zwischen Klemme und dem mega48 das 
hätte ich noch erwähnen sollen.

Danke schonmal.

von Karl H. (kbuchegg)


Lesenswert?

charly schrieb:
> Also wenn ich den Kanal wechsel dann, bleibt es bei einem Wert um die
> 400 +- 10
>
> VCC und AVcc sind beide direkt an 5V angeschlossen.

das ist erst mal egal. Denn weder Vcc noch AVcc werden benutzt. So wie 
du ADMUX eingestellt hast, wird die SPannung an AREF als 
Referenzspannung benutzt und nichts anderes.

> Keine Kondensatoren.

Kein Kommentar (zumindest jetzt noch nicht)

> Und ich habe noch einen 1k Widerstand zwischen Klemme und dem mega48 das
> hätte ich noch erwähnen sollen.

Zwischen welcher Klemme und welchem Anschluss des Mega48?

von Karl H. (kbuchegg)


Lesenswert?


von charly (Gast)


Lesenswert?

Karl Heinz schrieb:
>> Und ich habe noch einen 1k Widerstand zwischen Klemme und dem mega48 das
>> hätte ich noch erwähnen sollen.
>
> Zwischen welcher Klemme und welchem Anschluss des Mega48?

zwischen dem Anschlusspin des Controllers und der Klemme an der später 
das Poti dran ist, welches zwischen VCC und GND geschaltet ist.

Karl Heinz schrieb:
> das ist erst mal egal. Denn weder Vcc noch AVcc werden benutzt. So wie
> du ADMUX eingestellt hast, wird die SPannung an AREF als
> Referenzspannung benutzt und nichts anderes.

AREF ist ebenfalls auf 5V geschaltet.

von Thomas E. (thomase)


Lesenswert?

charly schrieb:
> uint8_t valueHigh = ADCH;
>   uint8_t valueLow = ADCL;
>   uint16_t value = valueLow + (valueHigh << 8);

ADCL muss vor ADCH ausgelesen werden!

Also überlass das dem Compiler, anstatt dir selbst etwas falsches 
zusammen zu basteln:

1
uint16_t value = ADC;

Die UART-Ausgaben in der ISR zu kommentieren, erspare ich mir jetzt.

mfg.

: Bearbeitet durch User
von charly (Gast)


Lesenswert?

Ich habe jetzt erst das Low byte gelesen und auch deinen Rat mit value = 
ADC befolgt. Beides führt zu keinem Ergebnis. Ich bekomme immernoch nur 
seltsame Werte. Hat jemand noch einen Tipp?

Gruss charly

von Karl H. (kbuchegg)


Lesenswert?

Können wir uns darauf einigen, mal ein ganz simples Testprogramm ohne 
Interrupt und sonstigen Schnickschnack, nur mit den Tutorial Routinen zu 
schreiben?
1
...
2
hier die Routinen aus dem Tutorial, wobei du die Referenzspannung so einstellst, wie du das brauchst.
3
...
4
5
int main()
6
{
7
  uint16_t adcval;
8
9
  ADC_Init();
10
11
... was immer du noch für die UART benötigst
12
...
13
 
14
  while( 1 ) {
15
16
    adcval = ADC_Read(0);  // Kanal 0
17
18
    sprintf( uart_buff, "ADC 0: %u\n", adcval );
19
    uartPutS( uart_buff );
20
  }
21
}

Dann variierst du mal die Spannung am ADC Eingang 0 (mit Voltmeter 
kontrollieren) und siehst nach, was die ausgegebenen Werte machen.

Wenn sich die wie erwartet verhalten, dann kommt das nächste 
Testprogramm
1
...
2
  while( 1 ) {
3
4
    adcval = ADC_Read(0);
5
6
    sprintf( uart_buff, "ADC 0: %u\n", adcval );
7
    uartPutS( uart_buff );
8
9
    adcval = ADC_Read(1);
10
11
    sprintf( uart_buff, "ADC 1: %u\n", adcval );
12
    uartPutS( uart_buff );
13
  }

von Ingo (Gast)


Lesenswert?

Es sollte mich wundern wenn damit nicht jeden PC abschießt. Mach hinter 
dem Senden nochmal 500ms Pause mit nem Delay_ms(500).


Ingo

von flavius (Gast)


Lesenswert?

charly schrieb:
> Karl Heinz schrieb:
>>> Und ich habe noch einen 1k Widerstand zwischen Klemme und dem mega48 das
>>> hätte ich noch erwähnen sollen.
>>
>> Zwischen welcher Klemme und welchem Anschluss des Mega48?
>
> zwischen dem Anschlusspin des Controllers und der Klemme an der später
> das Poti dran ist, welches zwischen VCC und GND geschaltet ist.

Jetzt ist Zeit für einen Schaltplan.

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.