Hallo,
ich möchte zwei Gabellichtschrenken an PB0 und PD5 abfragen. Beide
liefern im offenen Zustand etwa 5V (High-aktiv). Ist ein Gegenstand in
der Lichtschranke, kann am Ausgang des Transistors etwa 2mV gemessen
werden.
Um nun eine Aktion auszuführen, muss man auf LOW-Abfragen. Ist das
richtig?
Hier sind die entsprechenden Codezeilen:
1
...
2
DDRB|=(1<<PB3)|(1<<PB4);
3
4
DDRB&=~(1<<PB0);// PB0 als Eingang
5
//PORTB |= (1<<PB0); // Pull-up an PD5
6
DDRD&=~(1<<PD5);// PD5 als Eingang
7
//PORTD |= (1<<PD5); // Pull-up an PD5
8
9
if(!(PINB&(1<<PINB0)))// Führe aus, wenn PB0 gesetzt ist
10
{
11
PORTB|=(1<<PB4);// LED gelb an
12
PORTB&=~(1<<PB3);// LED rot aus
13
}
14
if(!(PIND&(1<<PIND5)))// Führe aus wenn PD5 gesetzt ist
15
{
16
PORTB|=(1<<PB3);// LED rot an
17
PORTB&=~(1<<PB4);// LED gelb aus
18
}
19
...
nun zum Problem:
Es tut sich nicht.
Was mache ich falsch?
Danke
Hast du Opencollektor Ausgänge an deinen Lichtschranken? Wenn ja musst
du die Auskommentierten Pull-Up Aktivieren reinmachen.
Die Eingänge der Lichtschranken musst du eigentlich nicht extra auf
Eingang setzten. Das ist nacht dem POR immer auf 0 gesetzt.
1
DDRB|=(1<<PB3)|(1<<PB4);
2
3
PORTB|=(1<<PB0);// Pull-up an PB0
4
PORTD|=(1<<PD5);// Pull-up an PD5
5
6
if(!(PINB&(1<<PB0)))// Führe aus, wenn PB0 gesetzt ist
7
{
8
PORTB|=(1<<PB4);// LED gelb an
9
PORTB&=~(1<<PB3);// LED rot aus
10
}
11
if(!(PIND&(1<<PD5)))// Führe aus wenn PD5 gesetzt ist
12
{
13
PORTB|=(1<<PB3);// LED rot an
14
PORTB&=~(1<<PB4);// LED gelb aus
15
}
Sonnst fallen mir aber keine Fehler auf. Gehen die LEDs selber? Also
wenn du nur die LEDs einschaltest zb?
Hallo und danke schon mal für die Hilfe.
@Matrix:
die Lichtschranke haben keine Opencollektor Ausgänge. ich betreibe sie
wie in der Skizze beschrieben. Auch mit den Pull-ups.
Die LED´s sind ok. Habe zB. auf High abgefragt ( if(PINB&(1<<PB0)){...}
). Das Verhalten war wie erwartet. Dadurch dass sich kein Gegenstand in
der Lichtschranke befindet und der Transistor am Emitter etwa 5V hat,
wird die "if(PINB&(1<<PB0)){...}" ausgeführt und die entsprechende LED
leuchtet.
Wie erwehnt, fallst sich ein Gegenstand in der Schranke befindet macht
der Tansistor zu und am Emitter sind nur noch etwa 2mV zu messen.
Ich frage mich nun ob diese 2mV immer noch zu hoch sind damit der uC am
Pin einen Unterschied merkt um es als Schaltschwelle zu erkennen.
@technikus:
der Code befindet sich in einer Funktion. Die while(1) ist somit in der
main().
Ich verwende übrigens einen Atmega48. Allerdings glaube ich nicht dass
die Pinabfrage Controllerspezifisch ist.
Vielen Dank noch mal
Gast wrote:
> Ich frage mich nun ob diese 2mV immer noch zu hoch sind damit der uC am> Pin einen Unterschied merkt um es als Schaltschwelle zu erkennen.
Mit Sicherheit nicht.
> der Code befindet sich in einer Funktion. Die while(1) ist somit in der> main().
Poste es trotzdem.
Kannst ja ruhig mal das Programm abspecken, so dass es den Fehler immer
noch zeigt aber kleiner ist. Aber poste was komplettes und nicht nur
Fragmente!
Ach, komm.
Schön langsam wirds fad. Du willst Hilfe, nicht wir!
Poste doch mal was komplettes, mit dem man auch was anfangen kann. Dein
Code-Fragment ist erst mal so in Ordnung, aber das weißt du selber auch.
Also muss das Problem woanders sitzen. Nur wenn du nichts herzeigst,
kann dir auch keiner helfen das Problem zu identifizieren.
Der Interrupt wird ausgelöst? Vielleicht ist ja auch die Konfiguration
des Int0 Interrupts fehlerhaft.
Edit: Ich mag nicht mehr. Ich bin raus.
Hallo,
Gast wrote:
...
> ). Das Verhalten war wie erwartet. Dadurch dass sich kein Gegenstand in> der Lichtschranke befindet und der Transistor am Emitter etwa 5V hat,> wird die "if(PINB&(1<<PB0)){...}" ausgeführt und die entsprechende LED> leuchtet.> Wie erwehnt, fallst sich ein Gegenstand in der Schranke befindet macht> der Tansistor zu und am Emitter sind nur noch etwa 2mV zu messen.
Am Emitter? Also Kollektor des Kopplers an +5V?
Dann solltest Du auch einen Pulldown-Widerstand einlöten, der den
Eingang auf L zieht, wenn der Transistor im Koppler sperrt.
Üblicher wäre wohl, den internen PullUp einschalten und den Koppler an
AVR- Pin und den Emitter an GND zu schalten.
Gruß aus Berlin
Michael
Gast wrote:
> Ich verwende übrigens einen Atmega48. Allerdings glaube ich nicht dass> die Pinabfrage Controllerspezifisch ist.
wobei ich gerne wissen würde, wie die Interruptpins beschaltet sind...
Justus Skorps wrote:
> Gast wrote:>>> Ich verwende übrigens einen Atmega48. Allerdings glaube ich nicht dass>> die Pinabfrage Controllerspezifisch ist.
Aaah, jetzt habe ich es auch gefunden. Gut versteckt!
BTW:
10 Sekunden Delay in einem Interrupt Handler sind einfach nur
grottenschlechter Programmierstil...
10 Sekunden Delay in einem Interrupt Handler sind einfach nur
2
grottenschlechter Programmierstil...
es geht hierbei nicht um die Zeitdauer oder um den Programmierstil...
@ Justus Skorps:
eine handskizzierte Pinbeschaltung ist im Dateianhang zu finden.
Wobei:
Die Lichtschranken liefern, wenn nicht unterbrochen 5V, also logisch 1.
Ich behaupte mal, dass hinter dem Dioden-Or immer eine 1 vorhanden ist,
weil eine der beiden Lichtschranken nicht unterbrochen ist.
Erst wenn beide Lichtschranken gleichzeitig unterbrochen werden, müsste
der INT0 auslösen. Ich denke aber, dass genau das nicht passiert, denn
die eine ist mit Links und die andere mit Rechts beschriftet :-)
Karl Heinz,
das mit logisch 1 ist schon richtig, das ist ein eindeutig definierter
Zustand. Aber wenn da kein Pulldown dran ist, wie soll denn der Int0
Eingang auf 0 gehen ? Der ist dann einfach ohne Signal, also hochohmig
floatend.
MWS wrote:
> Karl Heinz,>> das mit logisch 1 ist schon richtig, das ist ein eindeutig definierter> Zustand. Aber wenn da kein Pulldown dran ist, wie soll denn der Int0> Eingang auf 0 gehen ? Der ist dann einfach ohne Signal, also hochohmig> floatend.
Yep. Daran hab ich noch gar nicht gedacht (jetzt versteh ich auch deine
Anmerkung von vorher mit dem Pulldown). Über die Dioden kann ja der
Eingang gar nicht auf 0 gezogen werden.
Karl Heinz,
ich glaube es handelt sich um eine bunte Mischung verschiedener Fehler,
denn was Du geschrieben hast stimmt ja auch. Meines Erachtens würde es
funktionieren, wenn die Dioden umgedreht werden und gegen einen
eingeschalteten Pullup des PD2/Int0 arbeiten, das ist dann ein
UND-Ersatz.
Damit würde ein Int0 ausgelöst, sobald eine der Lichtschranken
unterbrochen würde und auf Low geht.
Wobei
> Beide liefern im offenen Zustand etwa 5V (High-aktiv).
und
>die Lichtschranke haben keine Opencollektor Ausgänge. ich betreibe sie> wie in der Skizze beschrieben. Auch mit den Pull-ups.
ich keine Skizze sehe und die Aussagen nicht eindeutig sind. Was aber
entscheidend wäre.
Liefern sie aktive Low, oder ziehen Pulldown Widerstände bei
unterbrochenem Lichtstrahl den Ausgang auf Low ?
Ist letzteres der Fall, müssen die Pulldowns deutlich kleiner als der im
µC integrierte Pullup bei beschriebener UND-Ersatzschaltung sein, sonst
gibt das einen ungünstigen Spannungsteiler.
@Gast, poste doch mal die Verschaltung der Gabellichtschranken.
...
die Pulldowns sind bei den Lichtschranken mitverschaltet.
siehe Anhang
durch die Codeänderung der DDRD und DDRB zu Eingängen, hat es mit beiden
INT0 und INT1 funktioniert. Allerdings verstehe ich nicht warung Matrix
(2. Beitrag von oben) meinte:
1
Die Eingänge der Lichtschranken musst du eigentlich nicht extra auf
2
Eingang setzten. Das ist nacht dem POR immer auf 0 gesetzt.
Gast wrote:
> ...> die Pulldowns sind bei den Lichtschranken mitverschaltet.> siehe Anhang
Da nützen die aber nichts. Es muss zwischen den Dioden und den Portpins
für ein definiertes Potenzial gesorgt werden!
>> durch die Codeänderung der DDRD und DDRB zu Eingängen, hat es mit beiden> INT0 und INT1 funktioniert. Allerdings verstehe ich nicht warung Matrix> (2. Beitrag von oben) meinte:>
1
> Die Eingänge der Lichtschranken musst du eigentlich nicht extra auf
2
> Eingang setzten. Das ist nacht dem POR immer auf 0 gesetzt.
Er meint damit, dass nach dem (Power On-) Reset praktisch alle
I/O-Register (inkl. der DDR-Register) sowieso Null sind. Man sollte
allerdings (auch wenn Matrix was anderes behauptet) die Register
trotzdem explizit setzen.
Es ist allerdings schwierig, ohne die Anordnung der Lichtschranken zu
kennen, etwas über mögliche Denkfehler im Programm zu sagen.
Die Anordnung, wie Du sie bei den Lichtschranken gewählt hast, ist auch
ziemlich unüblich. Die Widerstände dort könntest Du Dir sparen, wenn Du
einfach die Controller-Pins an die (offenen) Kollektoren anschließt und
im Controller die Pull-Ups aktivierst. Die Dioden dann einfach umdrehen
und schon sollte es gehen.
Johannes M. wrote:
> Gast wrote:>> ...>> die Pulldowns sind bei den Lichtschranken mitverschaltet.>> siehe Anhang> Da nützen die aber nichts. Es muss zwischen den Dioden und den Portpins> für ein definiertes Potenzial gesorgt werden!
Yep.
Siehs mal so:
Über die Dioden kann Strom von der Lichtschrankenschaltung zum Pin
laufen.
Aber so eine Diode ist wie ein Einwegventil. Wenn von der Lichtschranke
nichts mehr kommt, heist das nicht, das der Spannungssstand (Analaogie
zu einem Wasserstand. Man möge es mir verzeihen) automtisch sinkt. Da
ist nichts was einen definierten 0-Pegel rechts von den Dioden erzeugen
würde.
Widerstand nach Masse würde genau das bewerkstelligen: Bildlich
gesprochen macht der den Abfluss auf, sodass rechts von den Dioden das
Wasser (eh: der Strom) abfliessen kann.
Aber auch dann wäre die beabsichtigte Wirkung noch nicht erreicht.
Wieder das Analogon:
Die Dioden seien Ventile, durch die Wasser zum Pin strömt (der den
Wasserstand misst.
Wenn deine Lichtschranken nicht unterbrichen sind, dann liefern sie
jeweils Wasser. Soweit so gut.
Wird eine Lichtschranke unterbrochen, dann liefert sie zwar kein Wasser
mehr. Aber die andere tut es! Wenn von 2 Wasserhähnen einer kein Wasser
liefert, wird das Becken trotzdem voll. Und der Wasserstandssensor (der
µC-Pin) registriert natürlich nach wie vor, dass da eine 1 anliegt.
(Nimm die Analogie mit dem Wasser nicht allzu wörtlich. Manchmal
funktioniert das überraschen gut, manchmal weniger. Aber vom Prinzip
her, kommt man mit so einem Wassermodell schon recht weit)
Das Ganze ist ausserdem eine schöne Demonstration der De-Morgan regel
Nicht( A und B ) <==> Nicht A ODER Nicht B
Gast:
> Ist ein Gegenstand in der Lichtschranke, kann am Ausgang des> Transistors etwa 2mV gemessen werden. Um nun eine Aktion> auszuführen, muss man auf LOW-Abfragen.
Aus diesen Worten entnehme ich, daß Du eine Aktion, bzw. den Int0
ausführen möchtest, wenn ein Gegenstand die Lichtschranke unterbricht.
Ist das richtig ?
Wenn ja: lass die Schaltung wie sie ist, pole nur die Dioden um und
setze den internen Pullup an PD2:
1
DDRD|=(1<<PD2);
Lösche diese beiden Zeilen, die brauchst Du nicht wegen der
Pulldown-Widerstände an den Fototranistoren:
1
PORTB|=(1<<PB0);// Pull-up an PB0
2
PORTD|=(1<<PD5);// Pull-up an PD5
Dann sollte es funktionieren. Wird der Lichtstrahl unterbrochen, wird
der Fototransistor hochohmig, der Pulldown zieht den Ausgang des
Fototransitors und damit den Pin auf Minus. Gleichzeitig wird auch der
Int0 über die Diode, die nun andersrum leitet, auf Minus gezogen. Damit
triggert der Int0, der auf fallende Flanke reagiert.
Du kannst auch alles umstricken, die Fototransistoren nach Minus
schalten lassen, und dann die internen Pullups des µC verwenden. Dann
brauchst Du dennoch einen externen Widerstand für die Dioden auf Minus
gehend, die dann wieder andersrum (also wie jetzt) reingehören würden.
Auch müsstest Du auf steigende Flanke triggern. Insgesamt könnntest Du 3
Widerstände einsparen. Du musst selber wissen, ob's Dir den Aufwand wert
ist.
Erst mal vielen Dank an Karl Heinz für die bildhafte Erklärung. Man kann
sich das ganze sehr gut Vorstellen.
In der Zwischenzeit habe ich
- die Dioden umgelötet,
- DDRD |= (1<<PD2) als Ausgang und
- PORTD |= (1<<PD2) den internen Pull-up geschaltet
- die anderern internen Pull-up an PD5 und PD0 sind auskommentiert
@ MWS:
die theoretische Beschreibung leuchtet mir ein. Durch den zugeschalteten
internen Pull-up an PD2 und dem DDRD als Ausgang, messe ich etwa 5V am
PD2. Soweit so gut. Nun müsste die PD2 Spannung, durch den Widerstand am
Fototransistor, gegen Masse abfallen.
Leider verhält sich das Ding nicht so wie grad beschrieben. Die Spannung
sinkt lediglich um etwa 0,5V ab.
Wie schon
Was mache ich falsch?
ist falsch. Muss ein Eingang bleiben, wollte den internen Pullup setzen,
und hab' Dir in temporärer Verwirrung das Datenrichtungsregister
genannt. Ließ sich so schön aus Deinem Text kopieren, und ich hab's dann
auch noch auf ODER geändert. Unwillentlich, aber wissentlich
herbeigeführter Murks ;-)
Also nimm obigen Befehl raus, damit's wieder ein Eingang wird, DANN
sollte es gehen, die Logik des Rests meiner Post ist trotzdem ok.
dafür muss man sich nicht entschuldigen.
ich habe schon gewusst was du gemeint hast.
Nun funktioniert alles so wie ich es mir vorstelle.
Vielen Dank noch mal an alle.