www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik 2 Potis an ADC gegenseitige Beeinflussung


Autor: Alex (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Zusammen,

ich betreibe wie im angehängten Schaltplan dargestellt 2 Potis am ADC 
eines ATMega32.
Da ich keine absolute Spannung messen will, habe ich die 1M Potis direkt 
auf Vref gelegt.
Leider habe ich das Problem, dass die Spannung an ADC0 von der 
Potistellung an ADC1 leicht beeinflusst wird und umgekehrt, wohl durch 
die Stromänderung.

Hat jemand eine einfach Idee wie ich das verhindern kann?
Ich denke das Problem ist recht trivial, aber analoge Schaltungstechnik 
ist definitiv nicht meine Stärke ;)

Vielen Dank schonmal,
Alex

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist zu 99,99% ein SW-Fehler.


Peter

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter, hier mein Code:
/* ADC initialisieren */
  // externe referenz (AVCC) nutzen und die MSBs in ADCL ablegen
  ADMUX |= (1<<REFS0);
  // prescaler einstellen (bei 16Mhz zwischen 80 und 240 -> 128 einstellen)
  ADCSRA |= (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
  // ADC anschalten
  ADCSRA |= (1<<ADEN);

  while(1)  
  {
    /* Servo 1 Update an ADC0*/
    // Kanal von ADC w�hlen
    ADMUX &= ~(1<<MUX0);
    // ADC Messung anstossen und warten
    ADCSRA |= (1<<ADSC);
    while ( !(ADCSRA & (1<<ADIF)));
    // Wert an ADC berechnen
    tmp = (float)ADC/1023; //ADC: Wert von 0 ... 1023  // 0->1000us, 1023->2000us, 512->1500us
    ServoPos1 = (uint16_t)(tmp*250) + 250; // 250 ... 500 mitte 375


    /* Servo 2 Update an ADC1 */
    // Kanal von ADC w�hlen
    ADMUX |= (1<<MUX0);
    // ADC Messung anstossen und warten
    ADCSRA |= (1<<ADSC);
    while ( !(ADCSRA & (1<<ADIF)));
    // Wert an ADC berechnen
    tmp = (float)ADC/1023; //ADC: Wert von 0 ... 1023  // 0->1000us, 1023->2000us, 512->1500us
    ServoPos2 = (uint16_t)(tmp*250) + 250; // 250 ... 500 mitte 375
}

Habe gerade entdeckt dass ich im Schaltplan Aref geschrieben habe, das 
muss AVcc heißen.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
    while ( !(ADCSRA & (1<<ADIF)));

Du verwendest kein Interrupt gesteuertes auslesen. Also lass das ADIF 
Flag in Ruhe.

Du setzt das ADSC Flag um den ADC das Signal zum loslegen zu geben. Der 
ADC löscht das Flag wieder, wenn er fertig ist
    while ( ADCSRA & (1<<ADSC))
      ;

Das ADIF Flag müsstest du selbst löschen. Es wird nur duch den Aufruf 
einer Interrupt Funktion oder indem du es aus dem Code heraus löscht 
(durch Schreiben eines 1 Bits) zurückgesetzt.
Das ist in den Datenblättern etwas unglücklich ausgedrückt. Einfacher 
ist es, sich an das ADSC Bit zu klemmen um festzustellen, ob eine 
Konvertierung beendet ist.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alex schrieb:
> Da ich keine absolute Spannung messen will, habe ich die 1M Potis direkt
> auf Vref gelegt.

Das ist zu hochohmig, nimm mal 10k Potis.
Alternativ kannst Du auch einige Dummy-Messungen nach MUX-Wechsel 
machen, damit sich der ADC umladen kann.


Peter

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stimmt, da hat sich ein Fehler eingeschlichen...
Habe ihn soeben behoben, aber das Problem tritt weiterhin auf.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Du verwendest kein Interrupt gesteuertes auslesen. Also lass das ADIF
> Flag in Ruhe.

Kann er ruhig nehmen, er löscht es ja wieder:
ADCSRA |= (1<<ADSC);


Peter

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter Dannegger schrieb:
> Das ist zu hochohmig, nimm mal 10k Potis.
> Alternativ kannst Du auch einige Dummy-Messungen nach MUX-Wechsel
> machen, damit sich der ADC umladen kann.

Kannst du mir kurz erklären warum die 1M Potis hier Probleme machen?
Ich würde es gerne verstehen

Autor: Helmut Lenzen (helmi1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alex schrieb:
> Da ich keine absolute Spannung messen will, habe ich die 1M Potis direkt
> auf Vref gelegt.

1MOhm ist viel zu hochohmig.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter Dannegger schrieb:
> Karl heinz Buchegger schrieb:
>> Du verwendest kein Interrupt gesteuertes auslesen. Also lass das ADIF
>> Flag in Ruhe.
>
> Kann er ruhig nehmen, er löscht es ja wieder:
>
> ADCSRA |= (1<<ADSC);
> 

Ooops. Du hast recht.
Ich würde trotzdem nicht tun. Das wär mir ehrlich gesagt zu implizit und 
zu versteckt. Zumindest hätte es sich einen Kommentar verdient, dass 
hier als Nebeneffekt das ADIF gelöscht wird.

Mein Fehler.

Autor: Helmut Lenzen (helmi1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alex schrieb:
> Kannst du mir kurz erklären warum die 1M Potis hier Probleme machen?
> Ich würde es gerne verstehen

Dein ADC hat eine Sample und Hold und ein Kapazitives Netzwerk im 
Eingang.
Diese Kapazitaeten muessen erstmal umgeladen werden und das braucht 
Zeit.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alex schrieb:
> Peter Dannegger schrieb:
>> Das ist zu hochohmig, nimm mal 10k Potis.
>> Alternativ kannst Du auch einige Dummy-Messungen nach MUX-Wechsel
>> machen, damit sich der ADC umladen kann.
>
> Kannst du mir kurz erklären warum die 1M Potis hier Probleme machen?
> Ich würde es gerne verstehen

Kurz und vereinfacht gesagt:
Im ADC sitzt ein kleiner Kondensator, der die Spannung konstant halten 
soll, solange der ADC arbeitet.
Dieser Kondensator muss auf die anliegende Spannung aufgeladen werden. 
Dazu braucht er aber Strom. Nicht viel, aber doch.
Strom, der über 1MOhm (bzw. den jeweiligen Anteil) nicht mehr fliessen 
kann, damit er sich in der kurzen Zeit die du ihm gibst, auf den 
Spannungswert aufladen kann.

Autor: Jojo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich glaube auch, daß deine Potis viel zu hochohmig sind. Da misst du ja 
eher das kosmische Rauschen mit :) ...

Nimm 10k-Potis, mach Dummy-Messungen und schau vielleicht nochmal in den 
Code aus dem Tutorial (wg. Abfrage des ADCs und so).

Außerdem finden die kleinen AVRs das Rechnen mit floats total doof :( . 
So einfach Kram wie bei dir kann man eigentlich problemlos mit 
Festkommaarithmetik erschlagen...
http://www.mikrocontroller.net/articles/Festkommaarithmetik

Gruß

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, vielen Dank euch.
Leider habe ich nur noch ein 10k Poti hier rumfliegen, werde mir 
Nachmittags noch eins besorgen und dann kurz berichten obs geklappt hat.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alex schrieb:
> Leider habe ich das Problem, dass die Spannung an ADC0 von der
> Potistellung an ADC1 leicht beeinflusst wird und umgekehrt
Was heißt "leicht"?
Der 1MOhm Widerstand ist relativ hoch. Schalt da mal noch einen 
100nF-Kondensator zwischen den Schleiferanschluss und GND.

Autor: U.R. Schmitt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alex schrieb:
> Kannst du mir kurz erklären warum die 1M Potis hier Probleme machen?
> Ich würde es gerne verstehen

Der AD Wandler hat eine Sample and Hold Stufe. Das heisst ein kleiner 
Kondensator wird auf die zu messende Spannung aufgeladen und dann der 
Eingang während der eigentlichen Messung vom Messsystem getrennt. So 
vermeidet man Fehlmessungen, die auftreten können wenn sich die 
Messspannung während der Messung ändert.
Zum Aufladen des S/H Kondensators muss aber ein bestimmter Strom 
fliessen, und zwar umso mehr, je weniger Zeit Du dem Kondensator 
zwischen 2 Messungen lässt.
Das müsste auch im Datenblatt des µCs stehen (maximale Eingangsimpedanz 
evt. in Abhängigkeit von der Zeit zwischen dem Umschalten auf einen ADC 
Kanal und der Messung.
Die Potis sind viel zu hochohmig, daß sich der S&H C schnell genug 
umladen kann.

Autor: U.R. Schmitt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mal wieder zu langsam :-)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und wie JoJo schon sagte, ändere auch das
    tmp = (float)ADC/1023; //ADC: Wert von 0 ... 1023  // 0->1000us, 1023-2000us, 512->1500us
    ServoPos2 = (uint16_t)(tmp*250) + 250; // 250 ... 500 mitte 375

Wenn du nicht durch 1023 sondern durch 1024 dividierst (was sowieso 
richtiger ist), dann gibt es eine völlig naheliegende 'Optimierung', die 
deinem µC das Leben wesentlich erleichtert.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hatte da wohl zu lange gewartet... ;-)

U.R. Schmitt schrieb:
> Die Potis sind viel zu hochohmig, daß sich der S&H C schnell genug
> umladen kann.
Wie gesagt: probier da mit den Kondensatoren mal. Damit wird der 
dynamische Widerstand des Potis reduziert.

Und das solltest du dir noch mal anschauen:
    tmp = (float)ADC/1023; //ADC: Wert von 0 ... 1023  // 0->1000us, 1023->2000us, 512->1500us
    ServoPos2 = (uint16_t)(tmp*250) + 250; // 250 ... 500 mitte 375
Das geht garantiert ohne Fließkommazahlen.

EDIT:
> Wenn du nicht durch 1023 sondern durch 1024 dividierst
Und zudem ist es erst dann auch mathematisch richtig.... :-o
Denn der ADC macht ja 1024 Schritte: 0...1023

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Festkommaaritmetik hab ich jetzt drin, scheint zu funktionieren.
Der 100n C vom Schleifer zur Masse war wohl der richtige Tipp !

Jetzt kann ich keine Beeinflussung mehr messen.
Vielen Vielen Dank euch allen!

Autor: U.R. Schmitt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alex schrieb:
> Der 100n C vom Schleifer zur Masse war wohl der richtige Tipp !

Du musst Dir nur im klaren sein, daß die Spannung am Poiausgang ggf. 
etwas verzögert ändert. Wenn man eine Worstcase Rechnung aufmacht (5*tau 
und fast max. Widerstand kommt man auf knapp 0,5Sekunden bei Mittelwert 
(500KOhm und 5Tau) auf 0,25 Sekunden.
Das heisst als Joystickeingang kann man das nicht benutzen. Für einen 
Poti der moderat langsam verstellt wird ist das OK.
Gruß

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
U.R. Schmitt schrieb:
> 5*tau
Nach 5Tau hat die Spannung erst 99,3% des Endwerts erreicht.
Das reicht für einen 10-Bit-Wandler eigentlich noch nicht ganz... ;-)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.