PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Widerstandswert ( Poti ) mit nur einem I/O Pin einlesen ?



Kaiser-F
04.02.2005, 11:00
Hallo,

Ich möchte gern meinen AVR dazu benutzen eine Regelung zu machen.

Dazu muss ich mehrere Potis einlesen in nur einen µC.

Ich hab mir das so vorgestellt:



Vcc
|
C1: 100nF
|
+---(R2 220)---->µC
|
|
Poti 10K
|
-
GND


Dazu muss der Pin am µC als Ausgang auf HING gesetzt werden.

Dadurch dass an C1 nun an beiden Seiten +5V anliegen, wird dieser entladen.

Schaltet man nun den Pin des µC als Eingang, so wird C1 über das Poti geladen.

Nach einer bestmmten Zeit unterschreitet die Spannung am Pin des µC die "schwellspannung von ca. 2.2V und der µC hat ein LOW auf seinem Eingang.


Diese Methode habe ich aus einer Anleitung herausgelesen und hoffentlich richtig interpretiert.

Leider weiss ich nochnicht wie ich einen Pin des µC als Eingang und gleichzeitig als Ausgang benutzen kann.

in der anleitung ging es mit dem Befehl "__mmio" (Memory mapped I/O)
Das will der Compiler aber nicht, sagt immer error.

hier mal mein Code (Verwendet wurde pin 0 von Port A):


#include <io.h>

typedef unsigned short WORD;
typedef unsigned char BYTE;


int main (void)

{
volatile WORD x;
register WORD y;

// Portpin auf Ausgang setzen.
__mmio (DDRA) = __mmio (DDRA) | (1 << 0);

// Portpin auf HIGH setzen
__mmio (PORTA) = __mmio (PORTA) | (1 << 0);

// Kondensator entladen, indem der Ausgang auf HIGH (Vcc) gesetzt wird.
for (x=0; x<50;) x++ /* Zaehlen */;

y = 0;

// Portpin auf Eingang schalten.
__mmio (DDRA) = __mmio (DDRA) & ~(1 << 0);


/* Zaehlschleife.
Wir zaehlen y so lange hoch bis der Kondensator unter die
Schwellwertspannung geladen ist. */
while (__mmio (PINA) & (1 << 0) && y < 65535) y++;

// Zählerwert zurückgeben
return y;

}


Kann von euch jemand evtl den Fehler finden?
Oder mir eine einfachere Programmvariante nennen?

Ich hab schon das ganze Forum durchstöbert und konnte leider nichts treffendes finden.

PicNick
04.02.2005, 11:23
Hi, Ich find beim Winavr nur
__MMIO_BYTE () u.
__MMIO_WORD ()
und die in <sfr_defs.h>
Soll nix heißen, aber wenn keiner was besseres weiß, kannst du ja probieren. mfg

Pascal
04.02.2005, 11:30
könnte man das nicht auch mit dem AD-Converter des AVR machen, indem man eine Spannungsteilerschaltung (mit Poti und festem Widerstand) aufbaut, bei der der AVR zwischendrin die Spannung misst und in Poti-Wert umrechnet?

PicNick
04.02.2005, 11:50
Wie auch immer, der Trick is nicht schlecht, den verwendet im Prinzip LEGO Mindstorms für seine Sensoren. Alle (aktiven) Sensoren haben Graetz-Gleichrichter, mit dem sie den kurzen Out-Impuls in passenden Saft verwandeln. Man spart draht und kann anstecken, wie man will (is ja für Kinder). mfg robert

Kaiser-F
04.02.2005, 12:04
Hallo,

@ Pascal

A/D Wandler wollt ich auch schon benutzen, aber die µC haben leider, so viel ich weiß, keine 5 Stück...





Ich finde das Prinzip auch super,

Vor allem weil man fast keine Komponenten braucht und jeden beliebigen Port-Pin verwenden kann.

Im Prinzip bräuchte ich nur einen Befehl mit dem ich einen Pin als ausgang UND Eingang verwenden kann...

Falls das nicht gehd muss ich halt nen zweiten Pin benutzen, und mit diesem immer wieder den Kondensator Entladen ( über Diode dazuschalten ):




Vcc+5V
|
|
C1 100nF
|
|
+--- ( |< Diode )---( 220R )---µC "entlade Pin "
|
+-----------------------µC "lesepin"
|
|
Poti 10K
|
|
_
GND

(Diode ist nötig, da ja sonst wenn der Ausgang auf LOW steht, GND am eingang anliegt und das ergebnis hinfällig macht....

Der Programmablauf müsste im Grunde nur folgendermaßen aussehen:

- Entlade C1: Ausgang auf HIGH ( zB 50ms lang, je nach Kondensatorgröße )
- Umschalten auf Eingang (entladevorgang abschalten) und zählen bis LOW anliegt
- Zählerwert ausgeben und zurücksetzen

das Ganze ständig wiederholen.


Wär halt cool wenn man dafür nur einen Pin bräuchte.

Vielen Dank für eure Bemühungen!

mfg

PicNick
04.02.2005, 12:27
Hi, also das Out-definieren mach ich beim Winavr direkt DDRx = 0x11
Mit dem AD Wandler müßtest du dich noch auseinandersetzen, damit er inzwischen Ruhe gibt
Vielleicht geht das auch überlappt, d.h wenn du einen PIN High setzt zum C-Laden, kann er ja derweil einen anderen Kanal digitalisieren, mfg

04.02.2005, 12:48
Hallo

hier ein Link zum Thema

http://www.atmel.com/dyn/resources/prod_documents/DOC0942.PDF


Dieter

Pascal
04.02.2005, 13:17
A/D Wandler wollt ich auch schon benutzen, aber die µC haben leider, so viel ich weiß, keine 5 Stück...

die haben vielleicht keine 5 ADCs, aber dafür einen 6 oder 8 kanaligen ADC, du kannst also, je nach AVR, bis zu 8 analoge Signale einlesen(zeitlich versetzt)

Kaiser-F
04.02.2005, 13:51
@ Pascal

Muss ich ganz ehrlich zugeben, das mit den Kanälen hab ich nicht gewusst... Muss ich mich noch einlesen.

@ Gast,

Danke für den Link, werd ich mir demnächst mal vornehmen


Ich hab in der zwischenzeit schon experimentiert und das Programm für die " 2-Pin-Variante" geschrieben. ist evtl. noch ein bisschen umständlich,

muss noch optimiert werden:




#include <avr/io.h>


typedef unsigned char BYTE;
typedef unsigned int WORD;

WORD entladedauer; // Variable für Entladungsdauer
WORD entladen_1; // Variable zum zählen der Entladungsdaue
WORD poti_1; // Variable zum zählen des Widerstandswertes





int main(void)
{

outp (0x01,DDRA); // PORT A: PIN 0 als Ausgang, Rest Eingang
outp (0xFF,DDRB); // PORT B: Ausgabe des ermittelten Wertes

entladedauer = 500; // hier wird die entladedauer festgelegt...
entladen_1 = 0;
poti_1 = 0;



for(;;)
{

if( entladen_1 >= entladedauer ) { // Wenn lange genug entladen
cbi (PORTA, 0); // entladung stoppen ( Pin0 auf LOW )

if( !bit_is_clear (PINA, PIND1)) { // solange der zählpin HIGH ist, zählen
poti_1++;
}
if( bit_is_clear (PINA, PIND1)) { //wenn Zählpin LOW wird,
outp (poti_1, PORTB); //Wert des Widerstands ausgeben
poti_1 = 0; //Wert zurücksetzen für neue Messung
entladen_1 = 0; //Wert zurücksetzten für neue Entladung
}
}else{ // ansonsten wenn Kondensator nicht genügend entladen,
sbi (PORTA, 0); // entladen ( PIN0 auf HIGH )
entladen_1++;
}

}
}



Bei einem Poti mit 10K und einem Kondensator mit 100nF
Erhalte ich am Ausgangsport Werte zwischen 0 und 40.

nicht gerade die beste Auflösung, aber ich werd mal mit den Kondensator und Potiwerten Experimentieren.


Ansonsten Funktioniert es einwandfrei.


Was meint ihr dazu?
ist es umständlicher oder einfacher als über A/D wandler?

(hier bin ich nicht pingebunden....)