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!