Widerstandsverlauf eines Potis ändert sich nach Anschluss an Analogeingang

Bobbybau91

Neues Mitglied
15. Nov. 2013
31
0
0
33
Ayl, Germany
Sprachen
  1. ANSI C
Hallo zusammen,

ich habe folgendes Problem:


Ich muss mit einem Atmega8 einen Analogwert eines Potentiometers einlesen. Wenn ich das Potentiometer nur an +5V und GND anschließe, ist der Widerstandsverlauf fast perfekt linear (Gemessen mit einem Voltmeter). Wenn ich nun aber den Schleifkontakt an den Analogeingang anschließe, sinkt die gemessene Spannung an dem Poteniometer um ca. 0.15 V und der Verlauf ist nicht mehr linear.

Ich habe den gleichen Aufbau an einem Arduino Board mit einem ATmega16U2 verbunden und dort ändert sich die Spannung nach Anschluss des Schleifers an den Analogeingang nicht und der Widerstandsverlauf bleibt linear.


Jemand eine Idee, woran das liegen könnte und wie ich das beheben kann? Ich muss leider auf jeden Fall den Atmega8 verwenden.
Ich brauche ja nicht zu erwähnen, dass ich noch ein ziemlicher Anfänger in Sachen Mikrocontroller bin.


Gruß Bob
 
Kann man eigentlich den Pullup eines verwendeten Kanals aktivieren? Sollte doch eigentlich gehen, oder? Dann würde(!) der Pullup auch das Poti verzerren...
(Das korrespondierende PIN-Bit sollte sich ja auch auslesen lassen, solange der digitale Inputpuffer nicht deaktiviert wurde (DIDR)).
Welchen Wert hat denn das Poti?
 
Hallo,

erstmal eine ganz simple Frage, Ist der Eingang vom Programm her auch als Eingang konfiguriert?
Dann mal wieder der Hinweis DATENBLATT !!!

The ADC is optimized for analog signals with an output impedance of approximately 10 kΩ or
less

Bedeutet im Klartext: Wenn dein Poti einen Widerstand > 10K hat, brauchst du dich nicht zu wundern.

- gp177 -
 
Wenn der Pin wirklich ein Ausgang sein sollte, mißt man erstmal entsprechend Vcc oder Gnd. Je nach Schleiferstellung zerlegt es dann ggf den Ausgangstreiber des Pins. Danach ist natürlich jedes Messergebnis denkbar.
 
Hallo,
...

The ADC is optimized for analog signals with an output impedance of approximately 10 kΩ or
less

Bedeutet im Klartext: Wenn dein Poti einen Widerstand > 10K hat, brauchst du dich nicht zu wundern.

- gp177 -

ich denke, dies ist wichtig für die sample time, bzw. ob die sample+hold Kapazität ausreichend schnell umgeladen werden kann. Im Eingangspfad sind hier 1..100kOhm vor der 14pF s+h Kapazität (ATmega2560 zB). Der statische Eingangswiderstand liegt im hohen MOhm Bereich, das sollte also bei einem Potentiometer mit mehr als 10kOhm nicht so viel ausmachen, da sich das Signal ja auch nicht so schnell ändert und somit das s+h C nicht umgeladen werden muss?!

Dirk :ciao:
 
Kann man eigentlich den Pullup eines verwendeten Kanals aktivieren? Sollte doch eigentlich gehen, oder? Dann würde(!) der Pullup auch das Poti verzerren...
(Das korrespondierende PIN-Bit sollte sich ja auch auslesen lassen, solange der digitale Inputpuffer nicht deaktiviert wurde (DIDR)).
Welchen Wert hat denn das Poti?

Der interne PullUp ist gesetzt, der Widerstand ist bei Vollausschlag 47 kOhm groß (genau wie der Widerstand auf dem MyAVR MK2 Board)
 
Code

Hier der Code aus meinem Programm, der mit dem Analogwert zu tun hat:

Code:
	DDRD |= 0b00000000; 					// Datenrichtung Port D  0=Eingang 1=Ausgang
	DDRB |= 0b11111111;   				// Datenrichtung Port B  0=Eingang 1=Ausgang
	DDRC |= 0b00000000; 					// Datenrichtung Port C  0=Eingang 1=Ausgang

	PORTD |= 0b11111100;					// Pull-Up von Port D
	PORTB |= 0b00000000;					// Pull-Up von Port B 
	PORTC |= 0b11111111; 				// Pull-Up von Port C 

	UBRRL = 23;          					// 9600 Baud siehe Baudratentabelle 
	UCSRB = 0b10011000;  				// Interrupt RX ein, Senden & Empfangen ein
	UCSRC = 0b10000110;

Code:
// ------------------------------------------------------------------------------------
// AD-Wandlung von Kanal X
// ------------------------------------------------------------------------------------

int AD_Wandlung(int x)						// Analog-Digital-Wandlung
{
	cli();   	                            // globale Interrupts deaktivieren

	ADMUX = x ;								// Kanal einstellen
	ADMUX |= (1<<REFS0);
	ADMUX |= (0<<REFS1);				   	// AVCC als Referenzspannung, Wandlungsergebnis linksb�ndig
											// um die 2 niederwertigsten Bits rauszufiltern (wegen Flatterwerten)
    ADCSRA = 0b11000101;                    // Frequenzvorteiler auf 32 setzen
											// und ADC0 als Analogeingangsbit aktivieren 
    while(bit_is_set(ADCSRA,ADSC));         // Warten bis Wandlung abgeschlossen

    Analogwert = ADCW;                   	// ADCW-Wert in Analogwert �bergeben
	
	sei();                               	// globale Interrupts aktivieren
  
  	return Analogwert;               		// Analogwert an Hautprogramm zur�ckgegeben
}

Code:
// AD_Wert ermitteln

		AD_Wert = AD_Wandlung(0);			// Analog-Digital-Wandlung aufrufen
		itoa(AD_Wert, AD_WertBuffer, 10);		// Integer to ASCII; 10 = dezimal

// AD_Wert in Eingangs-String einarbeiten

		if(AD_Wert <10)						// Wenn Eingangswert<10 -> Tausender, Hunderter, Zehner = '0'
		{
			Eingaenge[16] = '0';				// Tausenderstelle
			Eingaenge[17] = '0';				// Hunderterstelle
			Eingaenge[18] = '0';				// Zehnerstelle
			Eingaenge[19] = AD_WertBuffer[0];	// Einerstelle
		}
		else if(AD_Wert <100)					// Wenn Eingangswert<100 -> Tausender, Hunderter = '0'
		{
			Eingaenge[16] = '0';				// Tausenderstelle
			Eingaenge[17] = '0';				// Hunderterstelle
			Eingaenge[18] = AD_WertBuffer[0];	// Zehnerstelle
			Eingaenge[19] = AD_WertBuffer[1];	// Einerstelle
		}
		else if(AD_Wert <1000)				// Wenn Eingangswert<1000 -> Tausender = '0'
		{
			Eingaenge[16] = '0';                 // Tausenderstelle
			Eingaenge[17] = AD_WertBuffer[0];    // Hunderterstelle
			Eingaenge[18] = AD_WertBuffer[1];    // Zehnerstelle
			Eingaenge[19] = AD_WertBuffer[2];    // Einerstelle
		}
		else							// sonst Eingangswert vierstellig (>=1000)
		{
			Eingaenge[16] = AD_WertBuffer[0];    // Tausenderstelle
			Eingaenge[17] = AD_WertBuffer[1];    // Hunderterstelle
			Eingaenge[18] = AD_WertBuffer[2];    // Zehnerstelle
			Eingaenge[19] = AD_WertBuffer[3];    // Einerstelle
		}

		Eingaenge[20] = '\0';				// Ausgabestring beenden mit \0
 
Ich bin mir wie gesagt nicht wirklich sicher, ob die Wahl eines Pins als ADC-Eingang (im ADMUX-Register) bei aktiviertem ADC (ADEN-Bit im ADC-Control-Register-Fragezeichen) den Pin nicht komplett von der I/O-Logik abkoppelt (und somit die PORT- und DDR-Bits wirkungslos werden). Dagegen spricht allerdings, daß man die Input-Puffer manuell von den Pins trennen kann - oder eben auch nicht (DIDR-Register).

Wenn der interne Pullup aktiv ist (also das gesetzte Port-Bit wirklich wirksam wird), dann liegt er parallel zum Vcc-seitigen Anteil des Potis. Damit ist also der Strom durch den Gnd-seitigen Teil des Potis nicht mehr konstant - das Messergebnis nicht mehr linear zu zur Schleiferposition...
 
Hallo zusammen,
Ich bin mir wie gesagt nicht wirklich sicher, ob die Wahl eines Pins als ADC-Eingang (im ADMUX-Register) bei aktiviertem ADC (ADEN-Bit im ADC-Control-Register-Fragezeichen) den Pin nicht komplett von der I/O-Logik abkoppelt (und somit die PORT- und DDR-Bits wirkungslos werden). Dagegen spricht allerdings, daß man die Input-Puffer manuell von den Pins trennen kann - oder eben auch nicht (DIDR-Register).

DIDR gibts denke beim alten ATmega8 nicht ?!
Wenn der interne Pullup aktiv ist (also das gesetzte Port-Bit wirklich wirksam wird), dann liegt er parallel zum Vcc-seitigen Anteil des Potis. Damit ist also der Strom durch den Gnd-seitigen Teil des Potis nicht mehr konstant - das Messergebnis nicht mehr linear zu zur Schleiferposition...

Ja, der Pullup ist aktiviert, den einfach mal deaktivieren ...

Code:
// Pullup von PC0 (ADC0) nicht aktivieren:
PORTC |= 0b11111110;                 // Pull-Up von Port C

Noch ein Hinweis, der Code mit den roten Markierungen hat keine Funktion
Code:
[COLOR=#b22222]DDRD |= 0b00000000;[/COLOR]                     // Datenrichtung Port D  0=Eingang 1=Ausgang
DDRB |= 0b11111111;                   // Datenrichtung Port B  0=Eingang 1=Ausgang
[COLOR=#b22222]DDRC |= 0b00000000; [/COLOR]                    // Datenrichtung Port C  0=Eingang 1=Ausgang  
PORTD |= 0b11111100;                    // Pull-Up von Port D [COLOR=#b22222]
PORTB |= 0b00000000;[/COLOR]                    // Pull-Up von Port B  
PORTC |= 0b11111111;                 // Pull-Up von Port C 

// ...

[COLOR=#b22222]ADMUX |= (0<<REFS1);[/COLOR]

Dirk :ciao:
 
DIDR hatte ich nur herangezogen, um die Vermutung zu begründen, daß der Pullup eben auch trotz Verwendung des PINs als ADC-Eingang wirksam aktiviert werden kann, was dann folglich den Spannungsteiler (Poti) verzerrt.

Weil Du da oben den wirkungslosen Code gekennzeichnet hast (Bytes mit 0 verORren) - macht bei den anderen (Bytes mit 0xFF verORren) nicht 'ne direkte Zuweisung Sinn (statt der RMF)?
(Jaja, is OT, und man spart auch nur gaaanz wenige words Flash...)
 
Weil Du da oben den wirkungslosen Code gekennzeichnet hast (Bytes mit 0 verORren) - macht bei den anderen (Bytes mit 0xFF verORren) nicht 'ne direkte Zuweisung Sinn (statt der RMF)?
(Jaja, is OT, und man spart auch nur gaaanz wenige words Flash...)

Kurz OT:

Ja, eine direkte Zuweisung macht dann Sinn, wenn wenn man an der Stelle weiß, was alles einzustellen ist und eben dann, wenn das Programm nicht so komplex ist.

Ist das Pogramm größer und in einzelne Module aufgebaut, finde ich es besser, wenn die einzelnen Module (Initialisierungsroutinen) selber nur diese Sachen konfigurieren, die zum Modul gehören. Die Programmmodule lassen sich somit leichter in andere Projekte mit anderen Controllern übernehmen. Ich gehe eher so vor, bevor ich mir ein paar Bytes Platz oder Maschinenzyklen spare. Ich mache es manchmal sogar so, dass ich Bits explizit auf den Zustand setze der eigentlich schon nach einem Reset vorhanden ist (bei DDRn zum Beispiel Input, wenn ich den benötige), dann überschreibt mir meine Initialisierung ggf. einen falschen Wert, den ein anderer Programmteil verursacht ... muss man aber natürlich nicht machen ;)

Dirk :ciao:
 
Soweit kann ich das nachvollziehen - aber dann sollten erstens an einer Stelle auch nur die dort benötigten Bits durch so eine logische Verknüpfung gesetzt/gelöscht werden (und nicht das ganze Register), und zweitens (und damit im Zusammenhang) konsequenterweise die Bitnamen statt der Byte-Zahl verwendet werden.
 
Soweit kann ich das nachvollziehen - aber dann sollten erstens an einer Stelle auch nur die dort benötigten Bits durch so eine logische Verknüpfung gesetzt/gelöscht werden (und nicht das ganze Register),
Ja genau, es würde auch anders gar nicht funktionieren. Die einzelnen Module würden ansonsten Konfigurationen anderer Module überschreiben.
und zweitens (und damit im Zusammenhang) konsequenterweise die Bitnamen statt der Byte-Zahl verwendet werden.
Genau. Dann ist der Code besser wartbar ... und auch hier im Forum für andere verständlicher, wenn mal ein Code mit Frage dazu gepostet wird ;)
 
Hallo,


ich denke, dies ist wichtig für die sample time, bzw. ob die sample+hold Kapazität ausreichend schnell umgeladen werden kann. Im Eingangspfad sind hier 1..100kOhm vor der 14pF s+h Kapazität (ATmega2560 zB). Der statische Eingangswiderstand liegt im hohen MOhm Bereich, das sollte also bei einem Potentiometer mit mehr als 10kOhm nicht so viel ausmachen, da sich das Signal ja auch nicht so schnell ändert und somit das s+h C nicht umgeladen werden muss?!

Dirk :ciao:

Habe es auch mal mit einem 10 KOhm Widerstand versucht, da habe ich den gleichen Effekt
 
Ich habe mal versucht den Pullup zu deaktivieren, aber dann funktioniert die Messung überhaupt nicht mehr

Also stimmt da ja etwas nicht, wenn die Messung nicht mehr funktioniert, wenn der Pullupwiderstand deaktiviert ist.

Vielleicht stelle doch noch einmal den aktuellen Sourcecode in das Forum.



Dirk :ciao:
 
Hi,

Ich habe mal versucht den Pullup zu deaktivieren, aber dann funktioniert die Messung überhaupt nicht mehr
Also stimmt da ja etwas nicht, wenn die Messung nicht mehr funktioniert, wenn der Pullupwiderstand deaktiviert ist.

also in meinem Kopf entsteht ein Bild ...

Ist das Poti evtl nur mit 2 Leitungen zwischen dem ADC-Pin und GND angeschlossen? Dann wäre der PullUp der obere Teil des Spannungsteilers :p

Das Poti muß mit den Enden am Vcc und GND. Der Schleifer muß an den ADC-Eingang.

Gruß
Dino
 
Hi,

also in meinem Kopf entsteht ein Bild ...

Ist das Poti evtl nur mit 2 Leitungen zwischen dem ADC-Pin und GND angeschlossen? Dann wäre der PullUp der obere Teil des Spannungsteilers :p

Das Poti muß mit den Enden am Vcc und GND. Der Schleifer muß an den ADC-Eingang.

Gruß
Dino

Ganz genau so habe ich den Poti angeschlossen ;) Also an VCC und GND, und der Schleifer ist am ADC
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)