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
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
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
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