AD Wandler spuckt seltsame Werte aus

OP #1865005
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
Angehängte Dateien:
OP #1865049
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.
#1865099
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
#1865102
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
}
#1865116
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.
OP #1865143
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.

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