Forum: Mikrocontroller und Digitale Elektronik [Anfängerfrage] kleiner Zähler (7-Segment/Atmega8A in BASCOM) tut nicht was er soll


von Jann K. (jann_k)


Lesenswert?

Hallo,

Ich bin bin ziemlicher (wenn nicht totaler) Anfänger in der 
Mikrocontroller-Programmierung und bräuchte einen Schubs in die richtige 
Richtung:

Ich bastle momentan an einem kleinen Munitionszähler für eine Nerf-Gun, 
der im Prinzip nur zwei Dinge tun soll:

a)auf der angeschlossenen 7-Segmentanzeige über den Taster 1 von "6" 
nach "0" (bzw. "-") runterzählen und dort stehen bleiben.

b)Über den angeschlossenen Taster 2 die Anzeige wieder auf "6"

Sprich, ich öffne die Trommel der Nerf-Gun, lade die 6 Darts rein und 
schließe die Trommel ---> Anzeige springt auf "6".
Ich feuere die Darts ab ---> Anzeige zählt "6", "5", "4", ... "-" und 
nimmt dann keine weiteren Zähler an, sondern erst wieder wenn ich die 
Trommel öffne, lade, schließe usw.

Softwareseitig wollte ich das wie folgt lösen:
1
$regfile "m8adef.dat"
2
$crystal = 1000000
3
4
Config Portd = Output
5
Config Pinc.5 = Input
6
Config Pinc.4 = Input
7
Pinc.5 = 0
8
Pinc.4 = 0
9
10
Dim Dis(8) As Byte
11
Dim Cnt As Byte
12
13
Dis(2) = &B01000000                                         'Symbol -
14
Dis(3) = &B00000110                                         'Ziffer 01
15
Dis(4) = &B01011011                                         'Ziffer 02
16
Dis(5) = &B01001111                                         'Ziffer 03
17
Dis(6) = &B01100110                                         'Ziffer 04
18
Dis(7) = &B01101101                                         'Ziffer 05
19
Dis(8) = &B01111101                                         'Ziffer 06
20
21
Cnt = 8
22
23
Do
24
25
  If Pinc.5 = 1 Then
26
  Portd = Dis(cnt) : Cnt = Cnt - 1
27
  Waitms 100
28
  End If
29
30
  If Cnt = 1 Then
31
  Cnt = 2
32
  End If
33
34
  If Pinc.4 = 1 Then
35
  Portd = Dis(cnt) : Cnt = 8
36
  End If
37
38
Loop

Der Zähler funktioniert tatsächlich auch ABER macht folgende Dinge, aus 
denen ich einfach nicht schlau werde:

1.) Schalte ich den Zähler ein, zeigt das Display "6". Wird jetzt der 
Schalter 1 an Pinc.5 zum ersten mal (und NUR beim ersten mal) betätigt, 
geht das Display komplett aus! Betätige ich dann den Schalter 2 an 
Pinc.4, springt das Display, wie gewünscht, auf "6" und durch betätigen 
von Schalter 1 zählt das Display jetzt, wiederum so wie gewünscht, von 
"6" runter nach "-" allerdings mit der Ausnahme, dass...

2.) ... nach jedem "Reset" jeweils der erste Dart, also die erste 
Betätigung von Schalter 1 nicht gezählt wird. Das Display zählt also 
quasi "6", "6", "5", "4", usw. (das allerdings total zuverlässig...)

Hardwareseitig scheint alles zu stimmen, denn wenn ich die Funktionen 
auf den Taster 1 reduziere, und das ganze einfach nur in "im Kreis" 
zählen lasse, funktioniert das einwandfrei:
1
Do
2
3
  If Pinc.5 = 1 Then
4
  Portd = Dis(cnt) : Cnt = Cnt - 1
5
  Waitms 100
6
  If Cnt = 1 Then Cnt = 2
7
  End If
8
9
Loop

Ich nehme an, dass ich hier irgendwo vor lauter Bäumen den Wald nicht 
sehe (wie gesagt: Anfänger), aber da ich jetzt seit drei Tagen auf 
diesen code starre und nicht dahinter komme und alle vergleichbaren 
Projekte die ich im Netz so finde gleich um Welten komplizierter sind, 
hier mein mittelgroßer Hilfeschrei.

Ich würde mich freuen, wenn sich jemand erbarmt und mir 'nen Tipp gibt 
;-)

Gruß,

Jann

von Karl M. (Gast)


Lesenswert?

Hallo,

Taster prellen, man muss sie also entprellen.
Danach folgt noch eine Mechanismus um Zustandsänderungen zu verarbeiten.
Darauf reagiert dann das Programm entsprechend.
Dazu gibt es ein HowTo hier im Forum.

von Jann K. (jann_k)


Lesenswert?

Hi und danke für die Antwort,

also, angefangen hat dieses Projekt mit einem 7-Segment, dass einfach 
nur von 0 nach 9 zählt und wieder von vorne anfängt - als ich das ganze 
dann "Schaltbar" machen wollte, habe ich mich natürlich mit Prellen, 
Entprellen, Pull-Down-Widerstand usw. beschäftigt (unter anderem auch 
durch das Tutorial hier im Forum) - tatsächlich habe ich mich genau 
daher auch für obige Vorgehensweise entschieden, DENN (zumindest nach 
meinem bisherigen Verständnis):

Das Taster 2 prellt, ist in der Praxis doch eigentlich egal, da das 
Programm nur nach einem HIGH-Signal sucht. Wenn ich jetzt also die 
Trommel der Nerfgun öffne, springt das 7-Segment auf "6" - das tut es 
zwar, mangels entprellen, viele Male hintereinander, aber da dies so 
schnell passiert, dass das Auge es nicht wahrnimmt und das Endergebnis 
sowieso die gewünschte "6" ist, habe ich es vernachlässigt.

Taster 1 ist natürlich auch nicht wirklich "entprellt", aber da so ein 
Nerf-Dart 60-70 km/h draufhat und zwischen "gedrückt" und "losgelassen" 
dementsprechend wenig Zeit vergeht SCHEINT der waitms 200-Befehl hier 
schon zu reichen um das prellen zu überbrücken - jedenfalls funktioniert 
der Zähler, wie gesagt, in der "vereinfachten" Variante ganz 
wunderbar...

von Matthias S. (mat-sche)


Lesenswert?

Hi,

schau mal in der Hilfe unter Debounce nach, damit wird Dein Eingang 
entprellt.

von KingJulian (Gast)


Lesenswert?

Ich bin kein BASIC Spezi, aber würde es vielleicht helfen, wenn du cnt 
dekrementierst bevor du den Port setzt? Also

  If Pinc.5 = 1 Then
    Cnt = Cnt - 1 : Portd = Dis(cnt)
    Waitms 100
  End If

von Jann K. (jann_k)


Lesenswert?

Hi KingJulian,

Danke für den Tipp. Das hat mich schon etwas weitergebracht. Ich poste 
später mal mein neues "Design".

von Jann K. (jann_k)


Angehängte Dateien:

Lesenswert?

Hi,

für den Fall dass jemand Interesse daran hat (oder andere Anfänger nach 
genau so was suchen). So habe ich das jetzt gelöst...:
1
$regfile "m8adef.dat"
2
$crystal = 1000000
3
4
Config Portd = Output
5
Config Pinc.5 = Input
6
Config Pinc.4 = Input
7
Pinc.5 = 0
8
Pinc.4 = 0
9
10
Dim Dis(8) As Byte
11
Dim Cnt As Byte
12
13
Dis(2) = &B01000000                                         'Symbol -
14
Dis(3) = &B00000110                                         'Ziffer 01
15
Dis(4) = &B01011011                                         'Ziffer 02
16
Dis(5) = &B01001111                                         'Ziffer 03
17
Dis(6) = &B01100110                                         'Ziffer 04
18
Dis(7) = &B01101101                                         'Ziffer 05
19
Dis(8) = &B01111101                                         'Ziffer 06
20
21
Cnt = 8 : Portd = Dis(cnt)                                  
22
23
Do
24
25
   While Pinc.4 = 1                                         
26
27
      Waitms 100                                            
28
29
         While Cnt >= 3                                     
30
31
32
         If Pinc.5 = 1 Then                                 
33
         Cnt = Cnt - 1 : Portd = Dis(cnt)
34
         Waitms 100                                         
35
         End If
36
37
         Wend                                               
38
39
      Cnt = 2 : Portd = Dis(cnt)                            
40
41
   Wend                                                     
42
43
   If Pinc.4 = 0 Then                                       
44
   Waitms 500                                               
45
   Cnt = 8 : Portd = Dis(cnt)                               
46
   End If                                                   
47
48
Loop
... und der Zähler funktioniert wunderbar. Das ganze geht nach folgender 
Logik vor: Die Nerf-Gun ist entweder offen oder zu. Solange sie zu ist, 
wird geschossen, also zähle die Darts die abgeschossen werden.

Solange sie auf ist, dann wird sie nachgeladen, also setze das Display 
wieder auf "6".

Die While-Wend Schleife hat auch noch den netten Nebeneffekt, dass wenn 
die Nerf-Gun "zwischendurch" geöffnet wird, der Zähler beim letzten 
Stand wieder weitermacht.

Schaltbild habe ich auch angehängt.

Ich bedanke mich ganz herzlich für die Tipps und wünsche noch ein 
schönes WE!

: Bearbeitet durch User
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.