Forum: Mikrocontroller und Digitale Elektronik AD Wandler spuckt seltsame Werte aus


von Jakob B. (teddynator)


Angehängte Dateien:

Lesenswert?

Hi Comunity,

Ich hab ein kleines Problem mit dem AD Wandler des Atmega8.

Zum Aufbau: vier 100k Potis zwischen VCC und GND, Mittelabgriff direkt 
auf ADC0 bis ADC3, an jeden Mittelabgriff zusätzlich noch einen 1uF C 
gegen GND. An TX einen Transistor + Futter + SUBD 9 Buchse.

Die Schaltung soll lediglich die Werte der Potis auslesen und an den PC 
senden. Allen voran ein "Startbyte": 0x00

Allerdings bekomme ich nun  im hterm bei der Einstellung aller Potis auf 
0V folgende (HEX) werte: 00, 96, 94, 96, 95, 00, 96,... etc.

drehe ich nun ein Poti nach oben, wird dessen richtiger Wert bei 
überschreiten von ca. 95 richtig übertragen.

Interessant an der sache ist, dass wenn ein oder mehrere Potis komplett 
auf 5V gestellt sind, werden auch die restlichen Werte richtig 
übertragen. also beispielsweise Poti 1 und 3 auf 5V und 2 und 4 auf 0V 
gibt folgende Werte: 00, 255, 03, 255, 03. Das kommt mir wesentlich 
plausibler vor.

Hat jemand eine Idee woran es liegen könnte, dass die Werte nur dann 
richtig übertragen werden? Hardware? Software?

Der relevante Codeteil ist angehängt.

Danke schonmal

von Weingut P. (weinbauer)


Lesenswert?

die 100k sind eventuell zu groß.
das gibt dann n paar µA an Stromfluss, kann sein das der
entweder zu klein ist um richtig gesampled zu werden
oder Störeinstreuungen mit in den Messwert ein gehen.
Probiers mal mit 10k oder kleiner.

von Jakob B. (teddynator)


Lesenswert?

Fhutdhb Ufzjjuz schrieb:
> Probiers mal mit 10k oder kleiner.

Ok, danke. Hab leider gerade keine zur Hand. Aber werds die nächsten 
Tage mal versuchen.
Allerdings glaube ich nicht, dass wenn ich alle Potis direkt auf Masse 
einstelle, der Stromfluss so gering ist. werd sie mal schnell direkt mit 
Masse verbinden und sehen was passiert.

Für sonstige Tipps bin ich natürlich weiterhin dankbar.

von Jakob B. (teddynator)


Lesenswert?

Thomas B. schrieb:
> werd sie mal schnell direkt mit
> Masse verbinden und sehen was passiert.

gesagt, getan. Ich erhalte die Werte 00, 89, 91, 92, 90, 00, 89,....
daher tippe ich eher auf einen Fehler in der Software

Thomas B. schrieb:
> folgende (HEX) werte

sorry ich meinte natürlich DEC Werte.

von Karl H. (kbuchegg)


Lesenswert?

Thomas B. schrieb:
> Hi Comunity,
>
> Ich hab ein kleines Problem mit dem AD Wandler des Atmega8.
>
> Zum Aufbau: vier 100k Potis zwischen VCC und GND, Mittelabgriff direkt
> auf ADC0 bis ADC3, an jeden Mittelabgriff zusätzlich noch einen 1uF C
> gegen GND. An TX einen Transistor + Futter + SUBD 9 Buchse.

Was hast du mit dem AREF Pin gemacht?

von Edi R. (edi_r)


Lesenswert?

Mit welcher Taktfrequenz arbeitest Du?

Wie ist "sample" definiert?

Wie ist "value" definiert?

von Jakob B. (teddynator)


Lesenswert?

Karl heinz Buchegger schrieb:
> Was hast du mit dem AREF Pin gemacht?

Der liegt auf VCC

Edi R. schrieb:
> Mit welcher Taktfrequenz arbeitest Du?
>
> Wie ist "sample" definiert?
>
> Wie ist "value" definiert?

16Mhz mit ext. Quarz
1
int sample = 0;
2
char value = 0;

von Karl H. (kbuchegg)


Lesenswert?

Nebenbaustelle:

Gewöhn dir schleunigst an, dass du selber die Kontrolle über das 
Vorzeichen übernimmst und das nicht dem Compiler überlässt.

char    benutzt du nur dann, wenn du Textverarbeitung machst.

In allen anderen Fällen benutzt du entweder signed char oder unsigned 
char, oder noch besser uint8_t bzw. int8_t

von Karl H. (kbuchegg)


Lesenswert?

Ich seh aber auch nix, was das Problem so wie geschildert, erklären 
könnte. Meine einzige Hoffnung war, dass ARef in der Luft hängt.

Versuch mal auf das Mittelwertbilden zu verzichten und den Wert aus ADCH 
direkt auszugeben.
1 Messung -> 1 Übertragung mit der UART

(und mach alles unsigned)

Und bau deine globalen Variablen ab. Mit dem 100-maligem Umkopieren wird 
es nicht leichter zu durchschauen, welcher Wert jetzt wohin kopiert 
wird.
1
#define NR_SAMPLES 1
2
#define ADC_MUX_BASE  ((1<<ADLAR))
3
4
uint8_t ad_wandeln (void)        //AD wandeln#
5
{
6
  uint16_t sample;
7
8
  ADCSRA |= (1<<ADSC);            // eine ADC-Wandlung 
9
  while (ADCSRA & (1<<ADSC) )     // auf Abschluss der Konvertierung warten
10
    ;
11
  sample = ADCH;                  //einmal AD wandeln, ergebnis verwerfen
12
  
13
  sample=0;
14
  for(i = 0; i < NR_SAMPLES; i++) //32 mal wiederholen
15
  {
16
    ADCSRA |= (1<<ADSC);          //single conversion mode ein
17
    while ( ADCSRA & (1<<ADSC) )  //warten bis Konvertierung abgeschlosen
18
      ;
19
    sample += ADCH;               //aufsummierung der samplewerte
20
  }
21
22
  return (uint8_t)( sample/NR_SAMPLES);
23
}
24
25
int main(void)
26
{
27
  uint8_t a, b, c, d;
28
29
  DDRD = 0b00100010;
30
  DDRC = 0b00000000;
31
  PORTC= 0b11101111;
32
33
  init_uart(UBRR_VAL);
34
  sei();
35
36
  ADMUX=0b00100000;         //ADC Referenz auf Ext
37
  ADCSRA=0x80;            //ADC einschalten
38
    
39
  while (1)
40
  {
41
    send_char(0x00);
42
      
43
    ADMUX = ADC_MUX_BASE + 0;   //ADC MUX auf Kanal 0 einstellen
44
    a = ad_wandeln();
45
    send_char( a );
46
      
47
    ADMUX = ADC_MUX_BASE + 1;   //ADC MUX auf Kanal 1 einstellen
48
    b = ad_wandeln();
49
    send_char( b );
50
      
51
    ADMUX = ADC_MUX_BASE + 2;   //ADC MUX auf Kanal 2 einstellen
52
    c = ad_wandeln();
53
    send_char( c );
54
      
55
    ADMUX = ADC_MUX_BASE + 3;   //ADC MUX auf Kanal 3 einstellen
56
    d = ad_wandeln();
57
    send_char( d );
58
  }
59
60
  return 1;
61
}

von Karl H. (kbuchegg)


Lesenswert?

Liegt nicht beim Mega8 der ADC am Port C?

  DDRC = 0b00000000;
  PORTC= 0b11101111;

Warum schaltest du dann die Pullup Widerstände ein?
Da darfst du dich nicht wirklich wundern, wenn dein ADC alles mögliche 
misst, wenn du ständig parallel zum Eingang einen Widerstand unbekannter 
Höhe nach Vcc geschaltet hast.

von Sascha W. (sascha_w)


Lesenswert?

und da in ADCSRA die ADPS-Bits alle 0 sind soll er auch noch mit 8MHz 
wandeln!

Sascha

von Spess53 (Gast)


Lesenswert?

Hi

16MHz und Prescaler 2. Sehr portlich.

Die ADC-Frequenz sollte zwischen 50 und 200kHz liegen. Du hast 8 MHz.

MfG Spess

von Jakob B. (teddynator)


Lesenswert?

Karl heinz Buchegger schrieb:
> Warum schaltest du dann die Pullup Widerstände ein?

hatte die mal ein und mal aus. Geändert hat sich dadurch nicht 
sonderlich viel. Dachte zuerst auch das könnte das problem sein. Werd 
Sie wieder abschalten.
Und selbst wenn ich die Eingänge hart auf Masse lege werden seltsame 
Werte gemessen. Da dürfte ein Pullup nicht sonderlich viel ausmachen.

Karl heinz Buchegger schrieb:
> Ich seh aber auch nix, was das Problem so wie geschildert, erklären
> könnte. Meine einzige Hoffnung war, dass ARef in der Luft hängt.
>
> Versuch mal auf das Mittelwertbilden zu verzichten und den Wert aus ADCH
> direkt auszugeben.
> 1 Messung -> 1 Übertragung mit der UART
>
> (und mach alles unsigned)
>
> Und bau deine globalen Variablen ab. Mit dem 100-maligem Umkopieren wird
> es nicht leichter zu durchschauen, welcher Wert jetzt wohin kopiert

Deinen Code habe ich probiert, Problem ist erhalten geblieben.

Sascha Weber schrieb:
> und da in ADCSRA die ADPS-Bits alle 0 sind soll er auch noch mit 8MHz
> wandeln!

Spess53 schrieb:
> Die ADC-Frequenz sollte zwischen 50 und 200kHz liegen. Du hast 8 MHz.

Danke Ihr beiden, an so etwas hatte ich noch garnicht gedacht. Werd den 
Prescaler mal höher stellen. Melde mich wieder wenn ichs versucht hab.

von Jakob B. (teddynator)


Lesenswert?

Nochmal danke an alle. Nach dem Einstellen des Prescalers hat es 
funktioniert.

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.