Problem mit Int0 unter Bascom

OP #2396772
Lesenswert?

Hallo liebes Forum,

Was ich vorhabe: Ich möchte eine Scheibe definiert drehen.

Wie? Mit einem Getriebemotor (funktionert soweit) und einem optischen 
Encoder und (erstmal nur) einer hellen Markierung (funktionert nicht so 
gut).
Also "Drehen, bis die Markierung x mal vorbeigekommen ist" oder auch 
"Drehen und dabei Zählen", vorgegeben per RS232.

Programmierung des µC in BASCOM 2.0.5.0 (funktioniert bis hierhin)

Der Encoder besteht aus einem IR Emitter und einem IR Empfänger in 
Einfachstbeschaltung (1MOhm, etc.).

Ich möchte also im Prinzip nichts weiter tun, als die Impulse, die vom 
Empfänger kommen, mit einem Atmega16 zählen und im Programm 
weiterverarbeiten bzw. per "Print" ausgeben.

Hier stehe ich nun aber vor einem Rätsel.
Folgender Code funktioniert einwandfrei:
1
$regfile = "m16def.dat"
2
$crystal = 16000000
3
Declare Sub Main
4

5
$baud = 9600
6
$hwstack = 100
7
$swstack = 100
8
$framesize = 100
9

10
'Dim Zaehler As Byte
11

12
'LED1 an PD7
13
Led1 Alias Portc.7
14
Config Led1 = Output
15

16
'LED2 an PD6
17
Led2 Alias Portc.6
18
Config Led2 = Output
19

20
'TASTER1 an PD2
21
Taster1 Alias Pind.2
22
Config Taster1 = Input
23
Taster1 = 0                                                 'PullUp-Widerstand einschalten
24

25
'Wenn der Interrupt INT0 auftritt, dann springe zum Label On_int0
26
On Int0 On_int0
27

28
'Der Interrupt INT0 wird ausgelöst wenn der Pin PD2 gegen GND gezogen wird.
29
'Also beim Übergang von HIGH nach LOW. Der Interrupt wird nicht ausgelöst, wenn
30
'der Pin bereits gegen GND zieht.
31
Config Int0 = Falling                                       'fallende Flanke
32

33
'INT0 einschalten
34
Enable Int0
35

36
'Interrupts global einschalten. Das ist der Hauptschalter für alle Interrupts
37
Enable Interrupts
38

39

40
Do
41
   Toggle Led1
42
   Waitms 500
43
Loop
44
End
45

46
On_int0:
47
   Toggle Led2
48
Return

Er tut was ich erwarte: LED 1 blinkt, LED2 wird durch drehen der Scheibe 
an- und wieder ausgeschaltet.

Sobald ich jedoch soetwas schreibe:
1
Do
2
   Toggle Led1
3
   Print Zaehler
4
   Waitms 500
5
Loop
6
End
7

8
On_int0:
9
   Toggle Led2
10
   Incr Zaehler
11
Return

Wird der Interrupt immer wieder angesprungen und es werden aufsteigende 
Zahlen ausgegeben. Die Stellung der Scheibe zum Encoder spielt keine 
Rolle mehr.

Wie ist dieses Verhalten zu Erklären?

Auch dieses Beispiel: 
http://www.rn-wissen.de/index.php/Beispiel_Drehzahlmessung_mit_RN-Control
liefert glaubhafte Ergebnisse.
Kommentiere ich hier jedoch das Rücksetzten des Zählers "Zaehlerirq0 = 
0" aus, wird wieder "unkontrolliert" hochgezählt, nicht nur bei jedem 
Durchgang der Scheibe durch den Sensor.

Die etwas unsauberen Pegel und etwaiges Prellen würde ich angesichts der 
Funktionierenden Beispiele als Ursache ausschließen.

Diverse "If Zaehler > x Then  Led3 = 1..." Experimente zeigten, dass das 
Problem wohl eher im "Print" liegt also im Zählen selbst.

Woher kommt dieses "Aufhängen" des Interrupts?
Wie funktioniert es richtig? Was mache ich falsch?

Ein kurzer Versuch mit "Debounce" führte zu ähnlichen Ergebnissen. Das 
Ereignis wurde immer wieder ausgelöst, während die Markierung vor dem 
Sensor lag... also scheint mir der Interrupt besser geeignet.
Ich lasse mich jedoch immer gern für einfachere / bessere Lösungen 
begeistern.

Für jegliche Tipps und Hinweise bin ich dankbar, Codebeispiele sind dem 
Verständnis natürlich äußerst zuträglich.

Von Beileidsbekundungen bzgl. BASCOM im Allgemeinen bitte ich abzusehen!

Vielen Dank schonmal!
OP #2396879
Lesenswert?

Danke, Klaus De lisson,

Der Pullup war tatsächlich noch aus, allerdings hatte ich dies schon 
vorher ausprobiert. Lag wohl an der Uhrzeit.
Ich habe es nun nochmals probiert mit "Taster1 = 1" und keine 
Veränderung festgestellt. Gleicher Fehler.

Nächster Schritt: Zaehler AS WORD hat leider nur den Effekt, dass der 
Zähler nun bis 65535 hochzählt bevor wider von  0 anfängt.
OP #2396891
Lesenswert?

Weiterhin habe ich jetzt probiert, den Zählerstand per Urxc-Interrupt 
abzufragen.
1
On Urxc Onrxd                                   'Interrupt-Routine setzen
2
Enable Urxc
3

4
Onrxd:
5
Print Zaehler
6
Return

Resultat: Es wird wieder fortlaufend hoch gezählt und sofort ausgegeben.

Hierbei ist es auch egal, ob ich den Zaehler als Wert ausgebe oder 
"Zaehler", dann wird dieser String fortlaufend gesendet.

Der Int0-Interrupt löst hier das Hochzählen aus, solange nichts 
empfangen wurde, wird die Led2 brav weiter getoggelt bei jeder 
Umdrehung.
Wird dann der Urxc ausgelöst, rennen beide Interrupts los...

Was stimmt denn da nicht, bzw. wo funkt "Print" den Interrupts 
dazwischen?


@mm
Die Zeile ist hier natürlich überflüssig, sie stammt von früheren 
Experimenten. Sie hat jedoch keinen Einfluss auf das geschilderte 
Verhalten. Habs probiert.

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