Forum: Mikrocontroller und Digitale Elektronik Problem mit Int0 unter Bascom


von Max M. (maxse33)


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!

von Klaus D. (kolisson)


Lesenswert?

Taster1 = 0 
'PullUp-Widerstand einschalten

das ist schonmal falsch da pullup = On = 1 ist

von Klaus D. (kolisson)


Lesenswert?

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

Das solltest du nicht tun da du als "Zaehler" ein Byte definiert hast.
255 mal prellen würde wieder zu 0 führen.
Testweise mal word nehmen.

von Klaus D. (kolisson)


Lesenswert?

Von Beileidsbekundungen bzgl. BASCOM im Allgemeinen bitte ich abzusehen!


Das kann ich nicht, da ich Bascom liebe

von Max M. (maxse33)


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.

von mmm (Gast)


Lesenswert?

max müller schrieb:
> Declare Sub Main

Wozu dient diese Codezeile?

Gruß mmm

von Max M. (maxse33)


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.

von Klaus N. (bobo1)


Lesenswert?

Hi,

der Taster-Pullup ist immer noch aus, denn "Taster1 = 1" schaltet den 
Pullup nicht ein da das Pind.2 ist.
Mit Portd.2 = 1 schaltest Du den Pullup ein.
Da TXD direkt daneben liegt könnte das wirklich die Ursache sein.

von MWS (Gast)


Lesenswert?

Sieht alles nach Programmieren by trial and error und Unkenntnis der HW 
aus.
Wenn der RXC-Int verwendet wird, muss UDR gelesen werden, sonst löst der 
immer wieder aus.

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.