Taster als Schalter

Gast #230548
Lesenswert?

Ich versuche nun schon seit 2 Tagen einen einfachen Taster als Schalter
zu benutzen. Ich habe einen ATmega8 und benutze Bascom.
LEDs blinken usw. habe ich alles schon hinbekommen nur halt das mit dem
Taster nicht.
Kann mir mal bitte jemand den Code sagen? Ich weiss das ich entprellen
muss, blos verstehe ich das nicht so ganz in Bascom.

Wenn ich den Taster an Pind.2 drücke soll die LED an portd.7 angehen,
wenn ich nochmal den Taster drücke soll sie wieder ausgehen.

Damke schonmal.
Gast #230550
Lesenswert?

Ich habe es nun alleine hinbekommen! Hänge aber beim nächsten problem.
Möchte nun mit 2 Tastern 2 Verschiedene "Programme" Starten und
stopen können.

Hier mal mein Code:

$regfile = M8def.dat
$crystal = 3638400

Ddrd = &B11100000
Portd = &B00001100

Declare Sub An
Declare Sub Aus
Declare Sub Prg1
Declare Sub Prg2

Dim T1 As Bit
Dim T2 As Bit


Do

Debounce Pind.2 , 0 , An , Sub
Debounce Pind.3 , 0 , Aus , Sub


Loop
End

If T1 = 1 Then
Gosub Prg1

End If

If T2 = 1 Then
Gosub Prg2

End If

An:
Toggle T1

Aus:
Toggle T2


Prg1:

 Portd.5 = 1
 Waitms 100
 Portd.5 = 0
 Portd.6 = 1
 Waitms 100
 Portd.6 = 0
 Portd.7 = 1
 Waitms 100
 Portd.7 = 0

 Return

Prg2:
 Portd.5 = 1
 Waitms 400
 Portd.5 = 0
 Portd.6 = 1
 Waitms 400
 Portd.6 = 0
 Portd.7 = 1
 Waitms 400
 Portd.7 = 0

 Return
Gast #230553
Lesenswert?

Dein Problem dürfte sein, daß, sobald ein Programm läuft, ja nicht mehr
die Loop mit den Debounces ausgeführt wird. Du mußt also sehr lange
drücken.

Als Lösung wüßte ich daher nur, das Entprellen und gedrückt erkennen in
einem Timerinterrupt quasi im Hintergrund ausführen zu lassen.
In der Codesammlung ist dazu ein Beispiel in C oder Assembler für bis
zu 8 Tasten, d.h. der Code ist der gleiche, egal ob eine Taste oder 8.


Ich kenn mich mit Basic nicht aus, aber geht Dein Programm nicht von
"An:" über "Aus:" direkt rein in "Prg1:" ?


Und ist nicht das "If T1 = 1 Then" nach dem "Do...Loop"
unerreichbarer Code ?


Peter
Gast #230554
Lesenswert?

Hallo Peter,

ich bin leider noch so ziemlich am Anfang was Uc angeht, deswegen
verstehe ich nicht so ganz was du da geschreiben hast.

Gibts hier jemand der auch mit Bascom codet und mir sagen kann wo der
Fehler liegt?

mfg
roman
Gast #230555
Lesenswert?

Hi,

der Code ist nicht richtig aufgebaut nach deinen Anforderungen. Peter
hat schon recht mit den tasten in einen Timer abzufragen.

Aber fuer Anfaenger sollte das Polling der Tasten einfacher sein.


An:
Toggle T1

-- hier fehlt ein return

die Hauptschleife sollte dann so aufgebaut sein:

Do

Debounce Pind.2 , 0 , An , Sub
Debounce Pind.3 , 0 , Aus , Sub
If T1 = 1 Then
Gosub Prg1
End If
If T2 = 1 Then
gosub Prg2
End If
Loop
End

prg1:
.......
return

prg2:
......
return

Gruß,
Dirk
Gast #230556
Lesenswert?

Hi Roman,
programmiere schon lange in Bascom.
"Debounce" ist schon lange her, hatte aber nie Erfolg damit, daher
weg damit.
Ich mache es immer wie folgt:


1) Wichtig ist die Deklaration z.b:

Const Pressed = 0     ' kommt später
Config Portd = Input  ' Port D ist Eingang
Btn_up Alias Pind.0   ' Portd.0 gibt Mist ;-) WICHTIG !!!!!

2) Abfragen, ob Taste gedrückt

If Btn_up = Pressed Then

3) ein bischen warten zum Entprellen

  Waitms 200
' Vielleicht geht auch weniger als 200, vielleicht auch ein
Debounce!

4) Aktion auslösen z.b. led togglen

  Toggle LED
end if

So geht es, viel Glück!

lg Ralf
#230557
Lesenswert?

Und so vertrödelt der MC wieder seine Rechenzeit in Zeitschleifen,
anstatt sich in dieser Zeit anderen Aufgaben zu widmen...

Ist es denn so schlimm, in einem Timer-Interrupt alle 4...20ms den Port
einzulesen, den Wert mit dem vorhergehenden zu vergleichen und
Änderungen zu übernehmen (nachdem sie 2mal oder besser 4mal
hintereinander stabil aufgetreten sind)?

Es ist schon schlimm genug, dass immer wieder mit Warteschleifen
programmiert wird, aber noch schlimmer ist, dass das Programmieren von
(ellenlangen) Warteschleifen immer wieder als "gutes Beispiel"
angepriesen wird.

...
Gast #230558
Lesenswert?

@Hannes,
viele Wege führen nach Rom!
Sorry, aber meine Interruptroutinen haben was Besseres zu tun, als
Taster abzufragen, kannst natürlich gerne so machen.
Denke mal, dass in ner Schleife für Anfänger so einfacher geht.
Warum sich noch Ärger mit nem Interrupt einhandeln?
"Debounce" wird auch warten, bis der Portpin sich nicht mehr ändert.
Hätte auch besser gefunden, wenn ein konkretes Beispiel beigefügt
hättest, damit Roman damit was anfangen kann.
Und wenn du meinst, daß der MC seine Zeit vertrödelt, wenn er auf
Eingaben wartet, dann ist mir das rätselhaft.
Es gibt z.b. Messaufgaben, die erst dann gestartet werden sollen, wenn
eine Taste gedrückt wurde.
Sehe auch wenig Sinn, wenn in einer komplexen Schleife trotzdem alle
4ms die Interruptroutine nach Tasteneingaben abfragt.
Wie gesagt: kannst natürlich gerne so machen, Hauptsache es funzt.

Ich hatte dieses Forum mal so Verstanden, dass man sich bei konkreten
Problemen Anregungen einholen kann, über die man natürlich auch
diskutieren kann.
Leider driften oft die Themen ab oder es wird Haarspalterei betrieben.
Schau dir mal einige Threads an, dann weisst was ich meine.

Schönes Wochenende
lg Ralf :-)
#230559
Lesenswert?

@Ralf:
> Sorry, aber meine Interruptroutinen haben was Besseres zu tun, als
> Taster abzufragen, kannst natürlich gerne so machen.

Das wird nicht in einem eigens für die Taster reserviertem Interrupt
gemacht, sondern in einem Timer-Interrupt der weitere Aufgaben der
Programmsteuerung hat (Blinken, Verzögerungen, LCD-Synchronisierung
usw...) und in fast jedem Programm sowiso benötigt wird. Die Abfrage
und Entprellung von bis zu 8 Tastern benötigt ganze 12 Takte in der ISR
und stellt dem Hauptprogramm (oder welchem Task auch immer) für jede
Taster ein (entprelltes) Zustandsbit zur Verfügung und zusätzlich ein
Flag (je Taster), das anzeigt, dass ein Taster erneut betätigt wurde
und dieser Tastendruck noch nicht abgearbeitet wurde. Und das alles
ohne Warteschleifen, bequemer geht es nicht...

> Denke mal, dass in ner Schleife für Anfänger so einfacher geht.

Ja, wenn man dem "Anfänger" auch dazusagt, dass man es so nicht
machen sollte. Denn wer sich einmal an das Verheizen von
Prozessortakten gewöhnt hat, kommt nur schwer wieder von diesem
Programmierstil weg. Es gibt genügend Beispiele hier im Forum, wo ein
(übertakteter) Mega128 mit BASCOM seine (wenige) Arbeit nicht schafft.

> Hätte auch besser gefunden, wenn ein konkretes Beispiel beigefügt
> hättest, damit Roman damit was anfangen kann.

Auf dieses Beispiel hat Peter Dannegger (der Urheber dieser Routine)
bereits verwiesen (Codesammlung). Wenn es aber sein muss, dann gibt es
das Beispiel eben hier nochmal. Es ist allerdings in Assembler. Die
folgenden Codezeilen sind Bestandteil der Timer-ISR, die noch andere
Aufgaben hat.

TIM1_COMPA:             ;ISR Timer1-Interrupt (alle 10ms)
 in srsk,sreg               ;SREG sichern (Exklusivregister)
 push xh                    ;benutzte Register
 push xl                    ;sichern
 in xl,ocr1al               ;Weckzeit
 in xh,ocr1ah               ;holen,
 subi xl,low(-tim1zu)       ;Intervall
 sbci xh,high(-tim1zu)      ;dazu,
 out ocr1ah,xh              ;und wieder
 out ocr1al,xl              ;in den Timer
 ;xl und xh können jetzt innerhalb dieser ISR frei benutzt werden
Tastenabfrage:          ;Entprellroutine geklaut bei Peter
Dannegger...
 in xl,tap      ;Tastenport einlesen (gedrückt=L)
 com xl         ;invertieren (gedrückt=H)
 eor xl,tas     ;nur Änderungen werden H
 and tz0,xl     ;Prellzähler unveränderter Tasten löschen (Bit0)
 and tz1,xl     ;Prellzähler unveränderter Tasten löschen (Bit1)
 com tz0        ;L-Bit zählen 0,2,->1, 1,3,->0
 eor tz1,tz0    ;H-Bit zählen 0,2,->tz1 toggeln
 and xl,tz0     ;Änderungen nur dann erhalten, wenn im Prellzähler
 and xl,tz1     ;beide Bits gesetzt sind (Zählerstand 3)
 eor tas,xl     ;erhaltene Änderungen toggeln alten (gültigen)
Tastenstatus
 and xl,tas     ;nur (neu) gedrückte Tastenbits bleiben erhalten
 or tfl,xl      ;und zugehörige Bits setzen (gelöscht wird nach
Abarbeitung)
 ;in "tas" steht jetzt der gültige Tastenzustand,
 ;in "tfl" die Flags der neu gedrückten, noch nicht abgearbeiteten
Tasten...
 ;xl ist jetzt wieder frei für weitere temporäre Zwecke in der ISR
 ;...
 ;Weitere Aufgaben der ISR...
 ;...
tim1_ovf_ende:
 pop xl                     ;benutzte Register
 pop xh                     ;wiederherstellen
 out sreg,srsk              ;SREG wiederherstellen
 reti                       ;fertig...

> Sehe auch wenig Sinn, wenn in einer komplexen Schleife trotzdem
> alle 4ms die Interruptroutine nach Tasteneingaben abfragt.

Ich schon, wobei ich mich nicht an den 4ms festhalte. Ich nutze den
Abstand, der für die restliche Interruptarbeit günstig ist. Wird z.B.
(für Messungen) eine "Uhr" mit Hundertstel Sekunden benötigt, dann
ist der Abstand 10ms. Brauche ich den Timer-Int für eine mehrkanalige
Software-PWM, dann wird der Zeitabstand halt soweit wie möglich
reduziert, so dass zwischen den ISRs noch genügend Zeit für die
Funktionen des Hauptprogramms bleibt, aber eben nicht mehr als nötig.

Es gibt eben (unter anderem) 2 Arten von Programmierstil.
Der eine wartet in einer Warteschleife, wenn eine Aktion nicht sofort
(sondern etwas später) ausgeführt werden soll.
Der andere springt sofort zur Mainloop zurück und schaut nach, ob es
nicht noch andere Arbeit gibt, die man zwischendurch erledigen kann.
Was soll daran falsch sein?

> Ich hatte dieses Forum mal so Verstanden, dass man sich bei
> konkreten
> Problemen Anregungen einholen kann, über die man natürlich auch
> diskutieren kann.
> Leider driften oft die Themen ab oder es wird Haarspalterei
> betrieben.
> Schau dir mal einige Threads an, dann weisst was ich meine.

Da hast du das Forum richtig verstanden.
Ich sehe meinen Beitrag auch nicht als Flamwar oder Haarspalterei,
sonern als einen Hinweis, dass man vorteilhafter programmieren kann.
Vielleicht auch darauf, dass nicht auf den Beitrag mit der Lösung
reagiert wurde.

...
Gast #230560
Lesenswert?

@ Togger
Wenn ichs mit waitms 200 mache blinkt die LED ja so lange bis ich die
taste loslasse, weil ja jede 200ms neu getoggelt wird.

@ Dirk
Ich hab nun die 2 vergessenen Returns hinzugefügt mit dem Ergebnis das
es schon fast funktioniert. Blos muss ich beim Ausschalten den Taster
immer so lange gedrückt halten, bis das ganze Programm einmal
durchgelaufen ist.
#230561
Lesenswert?

"Blos muss ich beim Ausschalten den Taster immer so lange gedrückt
halten, bis das ganze Programm einmal durchgelaufen ist."


Genau das hatte ich doch schon gesagt.

Interrupts sind gar nicht so schlimm. Und wenn man sie erstmal kapiert
hat, erleichtern sie das Programmieren ungemein.


Peter
Gast #2153740
Lesenswert?

Hallo,

hab einen Atmega32-Grundschaltung aufgebaut und an folgenden Ports je 
eine LED angeschlossen:

PD5
PD6
PD7

Zwei Taster habe ich an PD und PD3 angeschloßen.

Nun wollte ich folgenden Code mal ausprobieren, aber es funktioniert 
nicht richtig:
1
$regfile = "m32def.dat"
2
$framesize = 32
3
$swstack = 32
4
$hwstack = 32
5
$crystal = 1000000
6

7
Ddrd = &B11100000
8
Portd = &B00001100
9

10
Declare Sub An
11
Declare Sub Aus
12
Declare Sub Prg1
13
Declare Sub Prg2
14

15
Dim T1 As Bit
16
Dim T2 As Bit
17

18

19
Do
20

21
Debounce Pind.2 , 0 , An , Sub
22
Debounce Pind.3 , 0 , Aus , Sub
23

24

25
Loop
26
End
27

28
If T1 = 1 Then
29
Gosub Prg1
30

31
End If
32

33
If T2 = 1 Then
34
Gosub Prg2
35

36
End If
37

38
An:
39
Toggle T1
40

41
Aus:
42
Toggle T2
43

44

45
Prg1:
46

47
 Portd.5 = 1
48
 Waitms 100
49
 Portd.5 = 0
50
 Portd.6 = 1
51
 Waitms 100
52
 Portd.6 = 0
53
 Portd.7 = 1
54
 Waitms 100
55
 Portd.7 = 0
56

57
 Return
58

59
Prg2:
60
 Portd.5 = 1
61
 Waitms 400
62
 Portd.5 = 0
63
 Portd.6 = 1
64
 Waitms 400
65
 Portd.6 = 0
66
 Portd.7 = 1
67
 Waitms 400
68
 Portd.7 = 0
69

70
 Return


Es leuchten alle drei LEDs auf und wenn ich den Taster an PD2 betätige, 
dann läuft Prg1 einmal durch und die LEDs leuchten wieder.
Daselbe spiel mit dem Taster PD3, da läuft auch Prg:1 einmal durch...

Also eigentlich kein Unterschied bei den Tastern.

Woran könnte das liegen? Oder besser gesagt, was mach ich falsch?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren