Beschaltung von mehreren ADC Eingängen

OP #590075
Lesenswert?

Hi

Hab mal wieder ein kleines Problem.

Bin gerade dabei mit meinem Atmega32 4 ADC werte einzulesen das klappt 
auch alles einwandfrei wenn ich immer nur 1 ADC benutze. Sobald ich aber 
mehrere benutze und die Kanäle wechsele bekomme ich sehr merkwürdige 
Werte. Hab im Anhang ein Teil meiner Platine (jedoch sind die Dioden im 
moment nur brückendrähte.

Wie im Toturial beschrieben nutze ich eine einfache variante, denn 
Spannungsteiler. Wenn ich jedoch jetzt die Kanäle ändere ist auf allen 
Kanälen +- 20 jeder wert gleich und eine änderung bring so gut wie keine 
veränderung mehr.

Jetzt die Frage:

Kann es sein das dadurch dass alle ADC Kanäle die gleiche Masse nutzen 
der Wert verfäscht wird und das ich dies durch Dioden verhindern kann?

Wie gesagt wenn ich die Kanäle nicht ändere geht alles einwandfrei nur 
wenn sie geändert werden spinnt auf einmal alles.

Ach ja bevor ich es vergesse: Selbst wenn nur an einem Kanal meine 
Spannung anliegt gibt er mir den richtigen Wert aus wenn ich nur diesen 
Messe, sobald ich jedoch mehrere (Kanal wächsele) Messen will spinnt 
wieder alles.
Angehängte Dateien:
#590106
Lesenswert?

Daniel H. wrote:
> Hi
>
> Hab mal wieder ein kleines Problem.
>
> Bin gerade dabei mit meinem Atmega32 4 ADC werte einzulesen das klappt
> auch alles einwandfrei wenn ich immer nur 1 ADC benutze. Sobald ich aber
> mehrere benutze und die Kanäle wechsele bekomme ich sehr merkwürdige
> Werte.
Es ist meist sinnvoll (auch wenn es nicht explizit im Datenblatt steht) 
nach dem Umschalten auf einen anderen Kanal eine kurze Wartezeit 
einzufügen (ein paar zig µs). Versuch das mal.

> Hab im Anhang ein Teil meiner Platine (jedoch sind die Dioden im
> moment nur brückendrähte.
Es gibt in EAGLE die Möglichkeit, sogenannte Junctions an den 
Verbindungspunkten von Signalen zu platzieren, damit man sehen kann, 
dass an der Stelle tatsächlich eine Verbindung vorliegt und keine 
Kreuzung. Bei Dir ist überhaupt nicht erkennbar, wo da Verbindungen sind 
und wo nicht. Kleiner Tip: Ziehe die Signale im Schaltplan nicht mit 
Wire sondern mit Net. Dann werden die Junctions automatisch gemacht.

> Wie im Toturial beschrieben nutze ich eine einfache variante, denn
> Spannungsteiler. Wenn ich jedoch jetzt die Kanäle ändere ist auf allen
> Kanälen +- 20 jeder wert gleich und eine änderung bring so gut wie keine
> veränderung mehr.
>
> Jetzt die Frage:
>
> Kann es sein das dadurch dass alle ADC Kanäle die gleiche Masse nutzen
> der Wert verfäscht wird und das ich dies durch Dioden verhindern kann?
Nein, wenn die "Masse" die selbe Masse wie das AGND des Controllers ist, 
dann kann das eigentlich nicht sein und die Dioden werden da auch nichts 
bewirken. Aber auch das ist dem Schaltplanschnipsel nicht zu 
entnehmen...
OP #590160
Lesenswert?

Das ist echt ziemlich komisch. Wenn ich zum Beispiel 2 Messungen 
durchführe beide auf ADC 0 kein Prob alles geht oder 2 Messungen auf ADC 
1 ebenfalls kein Prob. Sobald ich aber eine auf ADC 0 mache und die 
andere auf ADC 1 dann simmt nichts mehr.

jemand nee Idee?

Gruß
Daniel
#590163
Lesenswert?

Daniel H. wrote:
> Das ist echt ziemlich komisch. Wenn ich zum Beispiel 2 Messungen
> durchführe beide auf ADC 0 kein Prob alles geht oder 2 Messungen auf ADC
> 1 ebenfalls kein Prob. Sobald ich aber eine auf ADC 0 mache und die
> andere auf ADC 1 dann simmt nichts mehr.
>
> jemand nee Idee?

Wie sieht denn Deine Messung softwaremäßig aus? Könnte ja sein, dass da 
der Hase im Pfeffer liegt...

...
Gast #590168
Lesenswert?

Die oben angesprochene Wartezeit (von ca. 120µs) MUSS zwischen 
Umschalten des MUX oder der Betriebsart (single-ended oder 
differentiell) eingehalten werden. Also erst MUX umschalten, dann die 
Displayausgabe, dann messen. Dann sollte es funktionieren.
OP #590172
Lesenswert?

Ok es gibt schon wieder neuigkeiten.

Also wegen den Pausen hab da ein delay von 250ms drinne darann denke ich 
kann es nicht liegen.

Code kann ich Posten ist aber schon ein Stücken (300 Zeilen).

Ich Schalte jetzt nach jeder Messung den ADC ab und jetzt sieht man 
wenigstens einen deutlichen unterschied. Jedoch beeinflussen sich die 
beiden Messungen doch irgendwie. Wenn ich die Spannung an ADC0 verändere 
dann steigt ADC1 mitjedoch nicht gleich sondern nur im verhältnis.

Alle Messschaltungen (Sensor + Teilerwiederstand) nutzen eine gemeinsame 
Masse und Spannungsversorgung wie in der Zeichnung dargestellt.
#591148
Lesenswert?

Daniel H. wrote:
> @ Hannes
>
> Hab ich doch gemacht. Aber leider bringt das auch nichts. Wenn ich ein
> Sensor komplett weglasse geht es einwandfrei.

Irgendwie verstehe ich nicht, wie Du das meinst. Was verstehst Du unter 
"weglassen"? Wenn ein Eingang abgefragt ist, sollte er auch beschaltet 
sein. Ansonsten wird Müll eingelesen.

>
> Kennt jemand eine schaltung mit mehreren Sensoren aus dem Kopf die hier
> im Netz rumschwebt wo ich einfach mal nachgucken könnte?#

Was für Sensoren??
Wenn Potis zwischen GND und AVCC auch (im weitesten Sinne) als sensoren 
akzeptiert werden, dann kenne ich eine Schaltung samt Software:
http://www.hanneslux.de/avr/mobau/7ksend/7ksend02.html
Bei der sind die eingelesenen ADC-Werte recht stabil, obwohl weder 
Oversampling noch Mittelwertberechnung angewendet wird.

...
OP #591182
Lesenswert?

Also als sensoren meine im moment PT100 oder Poti (ein veränderbaren 
Wiederstand). Mit weglassen ist gemeint: immer 2 Kontakte an x2, x3 ,x4 
gehören zusammen. Versorgungsspannung wird über die Leiste rausgegeben 
durch z.B.PT100 durchgeleitet und dann an den ADC eingang 
weitergeleitet. Gleichzeitig wird mit jeweils einem Wiederstand ein 
Spannungsteiler aufgebaut um einen Spannungsteiler aufzubauen (PT100 + 
Wiederstand). Die Dioden auf meinem Bild werden ja nich benötigt und 
sind somit durch Brückendraht ersetzt worden und verbinden den 
Spannungsteiler somit an meine Masse.
#591266
Lesenswert?

PT100 (mit Widerstand als Spannungsteiler) direkt am AVR-ADC-Eingang?

Auf diese Idee wäre ich nie gekommen. Ich habe den PT100 zwar noch nicht 
benutzt, gehe aber davon aus, dass seine temperaturabhängige 
Widerstandsänderung zwar sehr linear, aber recht klein ist. Ich 
vermutete also, dass der Aufwand der Signalaufbereitung den Nutzen 
übersteigt.

In einem Temperatur-Regler für einen alten E-Boiler nutze ich als Sensor 
einen Heißleiter, ist zwar nicht ganz linear, aber für den Zweck gut 
genug. Ist aber nur eine Mess-Stelle, auch kein Mega32 (ich mag nicht 
immer gleich mit Kanonen auf Spatzen schießen), sondern nur ein Mega48 
mit LCD 2x16 und 4 Tasten.

...
Gast #591404
Lesenswert?

Die übliche PT100-Anwendung wäre: Konstantstrom (1mA) über den Fühler 
und den Spannungsabfall über dem Sensor messen (Vierleitertechnik). Das 
(mV-) Messsignal verstärken und einen Offset abziehen (Bereich auf 0..5V 
anpassen), dann ist es vernünftig mit einem AVR zu messen. Die 
Linearisierung (falls nötig) ist mit µC auch kein Problem, z.B. mit 
Look-up-Tabelle.
OP #591704
Lesenswert?

Code:

void adc_init (void) { // ADC init
  ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS0); // ADC aktiviert, 
Prescaler auf 32, ADC Interrupt enabled

         ADMUX = (1<<MUX1) | (1<<MUX0); // ADC Channel 3
  ADMUX |= (1<<REFS0); // AVCC als Referenzspannung nutzen


  ADCSRA |= (1<<ADSC); // erste Wandlung Starten zum justieren
    while ( ADCSRA & (1<<ADSC)); // Warten bis die Wandelung 
abgeschlossen ist

  int tata = ADCW;

}
int adc (int mux) { // ADC Wert auslesen

  adc_init();

  int result=0;
  ADMUX |= mux; // Channel wählen

  for( int i=0; i<6; i++ ) {
    ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
    while ( ADCSRA & (1<<ADSC) ) {
      ;   // auf Abschluss der Konvertierung warten
  }
    result += ADCW;        // Wandlungsergebnisse aufaddieren
  }

  result = result / 6;                     // Summe durch sechs teilen = 
arithm. Mittelwert

  ADCSRA = 0;

  return result;

}

void testmode (void) { // Test Mode zum testen der Signale

  int save = 0;

  sei(); // Global Interrupt enabled

  while(1) //Endlos schleife
  {

  lcd_clrscr();
  lcd_gotoxy(0,0);
  lcd_puts("Wert 1:");
  lcd_gotoxy(0,1);
  lcd_puts("Wert 2:");

  save = adc(3); // Wert 1 holen

         lcd_gotoxy(11,0);
  lcd_puts("      ");
  lcd_gotoxy(11,0);
  itoa (save, buffer, 10);
  lcd_puts(buffer);

  pause (1000);

  save = adc(2); // Wert 2 holen
  lcd_gotoxy(11,1);
  lcd_puts("      ");
  lcd_gotoxy(11,1);
  itoa (save, buffer, 10);
  lcd_puts(buffer);

  pause (1000);

}
}


void powerup (void) { // Start Sequenz

  lcd_init(LCD_DISP_ON); // Display Initalisierung
  DDRC = 0x00; // PORT C als Eingang deklariert
  PORTC = 0x00; // Pull up Wiederstand aus
  lcd_clrscr(); // LCD Komplett Löschen

  timer_init(); // Timer starten
  adc_init(); // ADC starten

         testmode();
}
int main(void){ // Main
  powerup();
  while(1)
  {
  }

  return 1;
}


So das ist er nun in abgespeckter Fassung. ICP fehlt und ein paar 
kleinigkeiten.
Gast #591726
Lesenswert?

Hallo,

vielleicht eine C-Übung für mich (mache sonst nur ASM)...

int adc (int mux) { // ADC Wert auslesen

  adc_init();

  int result=0;
  ADMUX |= mux; // Channel wählen

1. Aufruf mit mux = 1 (Kanal 1), also 0b00000001

2. Aufruf mit mux = 2 (Kanal 2), also 0b00000010

ADMUX ist also 1, ADMUX |= mux; sollte also 3 ergeben, vermutlich nicht 
das, was Du erwartest.

Von ADMUX also erst alle MUX-Bits ausblenden, ADMUX = (ADMUX & 0xF0) | 
mux

Muß mal bitte ein C-User in die richtige Syntax bringen.

Gruß aus Berlin
Michael
Gast #591732
Lesenswert?

Du musst darauf achten dass du FRÜHESTENS 40µs nach der Umschaltung des 
MUX die Wandlung einleitest (nach ändern der Betriebsart single-ended 
<=> differentiell sogar 120µs). Diese Zeit braucht der Analogschalter 
(MUX) zum Durchschalten. Andernfalls wird es immer Hausnummern geben.
Gast #591741
Lesenswert?

Hallo,

das passt aber nicht sonderlich zum Datenblatt.

MUXX und REFS werden bei Beginn der Wandlung übernommen, nur die 
Änderung von REFS versaut die erste Wandlung, die zweite ist schon ok.

Klappt bei mir auch ganz praktisch so.

Zumindest bei den gängigen ATMega 8/16/32.

Gruß aus Berlin
Michael
Gast #591780
Lesenswert?

Hier mal eine Version von mir, auch wenn durch den _delay-Befehl Zeit 
verplempert wird: ;-)

1
double ADC_conversion(unsigned char mux, unsigned char MW) // Spannung messen (single ended)
2
{  
3
 ADMUX = mux;                 // Multiplexer-Modus einstellen
4
 delay_us(40);                // Pause bis Multiplexer eingestellt ist
5
 double Messwert = 0;
6
 unsigned int ADC_temp;
7
 unsigned char i = 1;
8
    
9
 do
10
   {
11
    ADCSRA |= (1<<ADSC);       // 'single conversion' einleiten
12
    while(!(ADCSRA & 0x10));   // auf ende der Wandlung warten, ADIF flag '1'
13
    ADC_temp = ADCL;           // ADCL Register lesen
14
    ADC_temp += (ADCH << 8);   // ADCH Register lesen      
15
    Messwert += ADC_temp;      // Ergebnisse der Messungen addieren
16
    i++;                       // Schleifenzähler erhöhen
17
   }
18
 while (i <= MW);              // MW Messungen für bessere Genauigkeit 
19
 Messwert = Messwert/MW;       // Mittelwert der Messungen der double-Variable zuweisen
20
  
21
 return (Messwert);
22
}
Gast #591782
Lesenswert?

Hallo,

@Power: Atmel sagt, daß der MUX vor Beginn der Wandlung gesetzt werden 
soll. Frühestens 1 ADC-Takt nach Beginn der Wandlung kann der MUX 
bereits wieder umgeschaltet werden, übernommen wird die Einstellung mit 
dem nächsten Start einer Wandlung. Das ging bisher auch immer bei mir.

Ein Dummy-Zyklus wird nur nach Ändern der Betriesart oder der 
Referenzspannung gefordert, unabhängig von Wartezeiten.
Es heißt nur, daß das erste Wandlungsergebnis nach Änderung von AREF 
ungültig sein kann und man besser verwerfen soll.

Bis jetzt haben meine AVR das Datenblatt offenbar auch gelesen. ;-)))))

Gruß aus Berlin
Michael
OP #593647
Lesenswert?

OK

hab mal wieder etwas Zeit gefunden um weiter zu machen.

Michael U. du hast recht zusammen mit Karl Heinz Buchegger. Hat an der 
einen kleinen Zeile gelegen.

Das einzigste was mir noch fehlt ist das mir einer mal kurz erklärt was 
eigentlich in der Zeile passiert:

ADMUX = (ADMUX & 0xF0) | mux;

Ich dachte immer wenn ich ADMUX |= mux eingebe dan ändert er nur die 
Bits dessen Wert mux hat?

Gruß und nochmals Danke
Daniel
Gast #593713
Lesenswert?

Hallo,

> Ich dachte immer wenn ich ADMUX |= mux eingebe dan ändert er nur die
> Bits dessen Wert mux hat?

Einfach unpräzise ausgedrückt und sicher auch gedacht. ;)

Es ist eine Oder-Verknüpfung, die Veränderung besteht also darin, das 
die Bits in MUX einzeln mit den Bits in ADMUX OR-Verknüpft werden. Das 
heißt aber ja letztlich: es sind hinterher alle Bits in ADMUX gesetzt, 
die vorher bereiits gesetzt waren ODER die in mux gesetzt sind.

   0000 0001   ADMUX
OR 0000 0010   mux
-------------
   0000 0011   ADMUX hinterher...

Gruß aus Berlin
Michael

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