Forum: Mikrocontroller und Digitale Elektronik AVR und Lichtschranke


von Christoph M. (cmoeka)


Lesenswert?

Hallo,

ich bin hier bereits ein langer stiller Leser in eurem Forum.

Nun habe ich auch ein Problem. Ich habe eine Lichtschranke. Mithilfe 
eines ATtiny 2313 möchte ich ein Relais eine bestimmte Zeit schalten, 
wenn ein Objekt die Lichtschranke unterbricht. Da ich (Schüler) 
allerdings noch Anfänger in der Bascom Programmierung bin, habe ich noch 
ein paar Fragen bei der Gestaltung dieses kleinen Projektes.

Ich möchte, egal wie lange die Lichtschranke unterbrochen ist, das 
Relais bzw. den Port nur eine bestimmte Zeit (ca. 10s) schalten. Ich 
habe leider noch keinen Ansatz gefunden, wie ich diese Problematik 
angehen kann.

Meine Idee war, einen Timer bei Unterbrechung der Lichtschranke zu 
starten und diesen hochzählen lasse. Zusätzlich soll der Ausgang 
eingeschaltet werden. Eine Variable sollte bei jedem Timer-Interrupt um 
+1 hochgezählt werden, bis ich meine Zeit von ca. 10 Sekunden erreiche. 
Wenn meine Variable meine 10 Sekunden abgezählt hat, soll sie sich 
rücksetzen und der Ausgang ausgeschaltet werden.

Kann das funktionieren? Habt ihr andere Ideen oder Vorschläge, wie das 
zu realisieren ist?


Ich danke euch schon im Voraus.
Gruß Christoph

von Hubert G. (hubertg)


Lesenswert?

Dein Ansatz ist schon richtig.

von oldmax (Gast)


Lesenswert?

Hi
Timer ist ein Teil. Allerdings da<rfst du den Eingang nicht statisch 
verarbeiten, sondern musst eine Flanke auswerten. In deinem Fall die 
erste.
Da ich in Assembler spreche, bleib ich mal mit meiner Beschreibung etwas 
oberflächlich:
Eingang einlesen und mit einem alten abgelegten Wert Exclusiv-Oder 
verknüpfen. Ergebnis ist "1", wenn alt <> neu. Nun noch ein Und mit dem 
Ergebnis aus der Exclusiv Oder Geschichte und du hast die steigende 
Flanke. Danach Neu--> Alt. Da die meisten die Eingänge gegen GND 
schalten, umm die internen Pullup zu nutzen, musst du in diesem Fall 
evtl. das Bit drehen, um bei einem Signal eine "1" zu erhalten. Das 
Flankenbit startet nun deine Zeit  und schaltet das Relais ein. Danach 
löscht du das Flankenbit. Ist die Zeit abgelaufen, fällt das Relais ab 
und es ist ein erneuter Wechsel mit einer entsprechenden Flanke des 
Signales erforderlich, um diesen Vorgang erneut zu starten. In Assembler 
sieht's etwa so aus
1
  In    R16, Portx      ; Port lesen
2
  COM   R16             ; evtl. drehen
3
  ANDI  R16, 0b00011100 ; Maske für gültige Eingängge
4
  LDS   R17, old_In
5
  EOR   R17, R16        ; Exclusiv Oder, Ergebnis in R17
6
  AND   R17, R 16       ; Neues Bit Wechsel auf "1"
7
  STS   Flanken, R17
8
  STS   Old_In, R16

Aud die Entprellerei hab ich hier mal verzichtet. Wird eine 
Entprellroutine erforderlich, macht es Sinn, die Zeile "In R16, Portx" 
durch eine Anweisung "LDS R16, Neu_In" zu ersetzen und die Variable 
"Neu_In" aus dem gelesenen Port und der Entprellroutine zu bilden.
In der Programmschleife wird dann das Flankenbit bearbeitet:
1
   LDS  R16, Flanke
2
   ANDI R16, 0b00001000   ; z.B. Bit 3
3
   BREQ  Ende             ; keine Flanke, dann ende Subroutine
4
   LDI  R 16, 10          ; Zeit = 10 sek.
5
   STS   Relaiszeit, R16
6
   In    R 16, PortX      ; kann auch anders gelöst werden
7
   ORI   R16, 0b00000001  ; Relais ein
8
   OUT   Portx, R16       ; aber ich arbeite auch hier oft mit Variablen
9
   LDS   R16, Flanke
10
   ANDI  R16, 0b11110111   ; Flankenbit löschen
11
   STS   Flanke, R16
12
Ende:

Bleibt noch das Abschalten des Relais. Dazuu generieerst du dir einen 
Sekundentakt und setzt dafür auch ein Bit. Ich nenne diese Bits 
"TimeFlags". Das ist ein Byte, in das die Zeitereignisse, die innerhalb 
einer Timer_ISR erfasst werden, eingetragen werden. In der 
Programmschleife werden diese dann bearbeitet, ohne die ISR zu belasten.
1
   LDS  R16, Timeflags
2
   ANDI R16, 0b00100000    ; Sekundenbit abfragen
3
   BREQ  ende1              ; kein Bit gesetzt, dann Ende
4
   LDS  R16, TimeFlags
5
   ANDI R16, 0b11011111    ; Sekundenbit löschen
6
   STS  Timeflags, R16
7
   LDS  R16, Relaiszeit    
8
   DEC  R16                ; Relaiszeit runterzählen
9
   STS  Relaiszeit, R16
10
   BRNE Ende1               ; wenn nicht "0" dann ende
11
   LDS  R16, Portx
12
   ANDI R16, 0b11111110    ; Relais aus
13
   Out Portx, R16
14
Ende1:
Statt einen direkten Portzugriff setze ich hier meist auch Variablen ein 
und weise dann aam Schluss der Programmschleife die Ausgänge zu. Du 
kannst hier auch direkt die Portbits setzen oder löschen.
Gruß oldmax

von Rainer U. (r-u)


Lesenswert?

Evtl. tut es auch ein Monoflop, ggf. retriggerbar.. (nicht für alles 
braucht man einen uC :-)

von oldmax (Gast)


Lesenswert?

Hi

Rainer Unsinn schrieb:
> Evtl. tut es auch ein Monoflop, ggf. retriggerbar.. (nicht für alles
>
> braucht man einen uC :-)

>Mithilfe
>eines ATtiny 2313 möchte ich ein Relais eine bestimmte Zeit schalten

Natürlich braucht man für alles einen µC. Da kommt doch in der Regel 
noch was hinterher.....
Gruß oldmax

von Christoph M. (cmoeka)


Lesenswert?

Hi oldmax,

Zuerst einmal vielen Dank, dass du dir die Mühe gegeben hast, mir einen 
Code zu stricken und ihn so schön zu kommentieren. :) Das hat mir das 
verstehen des Assembler-Codes um einiges erleichtert.

Da ich mir aber noch nicht ganz sicher bin, möchte ich deine Idee noch 
einmal zusammenfassen:
Zuerst wird der Port ausgelesen, welches Signal (logisch 0 oder 1) 
anliegt. Man könnte auch sagen, dass auf eine positive Flanke „gewartet“ 
wird. Sorry, wenn ich frage, aber eine z.B. positive Flanke ist ja eine 
Änderung des Ports von 0 auf 1, oder? In deinem Programm wird der alte 
Wert des Eingangs mit dem Neuen verglichen. Könntest du bitte das mit 
dem „Neu--> Alt“ nochmal genauer erläutern? Im nächsten Teil schaltest 
du dann das Relais an, wenn eine Flanke vorliegt? Sehe ich das richtig 
mit meinen beschränkten Kenntnissen? Das Ausschalten erfolgt dann, wenn 
die Zeit abgelaufen ist.

Ich schätze das Entprellen wird nicht notwendig sein, da es sich um eine 
Lichtschranke (effector OC5208) mit Transistor handelt.

Rainer Unsinn schrieb:
> Evtl. tut es auch ein Monoflop, ggf. retriggerbar.. (nicht für alles
> braucht man einen uC :-)
Das kann gut sein dass das reichen würde, aber wie oldmax schon 
vermutete, werden noch mehrere Funktionen implementiert. :)


Ich danke euch nochmals im Voraus für eure schnelle Hilfe.
Gruß Christoph

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.