Forum: Mikrocontroller und Digitale Elektronik [PIC 16F88] Impulserkennung/Zeitmessungs-/Interruptproblem


von Thomas M. (xt-fahrer)


Angehängte Dateien:

Lesenswert?

Hallo zusammen und einen schönen 1. Weihnachtsfeiertag!

Ich habe folgendes Problem zu lösen bzw. ich habe schon eine Idee, die 
aber in der Praxis nicht funktioniert und ich hoffe auf ein paar gute 
Vorschläge.

Ich habe eine rotierende Scheibe, auf der im Abstand von 90° 4 Magnete 
aufgebracht sind, ein langer und drei kurze. Diese Magnete flitzen an 
einer Spule vorbei, die eine positive und ein negative Spannung 
induziert: Wenn der Nordpol vorbeiflitzt, gibts eine positive und beim 
Südpol eine negative (es kann auch umgekehrt sein, spielt hier aber 
keine Rolle). Um diese Spannungen, 0 bis ca. 20V und 0 bis -20V, 
PIC-gerecht zu bekommen, wird die positive Spannung auf 5V begrenzt und 
die negative Spannung invertiert und auf 5V begrenzt. Wenn ich im 
folgenden von "positivem" und "negativem" Impuls rede, so bezieht sich 
das auf die ursprüngliche Spannungsform und nicht auf die PIC-gerecht 
aufbereitete.
Wie Ihr seht, ist bei den drei kurzen Magneten der Abstand zwischen 
positiv und Negativimpuls praktisch nicht vorhanden, wohl aber beim 
langen.

Diesen langen gilt es zu detektieren, bzw. den Positivimpuls des langen.

Der Abstand zwischen positiver fallender Flanke und negativer steigender 
Flanke beträgt 3,8 ms bei einer Scheibendrehzahl von 1340 U/min. Die 
maximale Drehzahl der Scheibe ist 7000 U/min, also ergibt sich nach dem 
Dreisatz ein minimaler positiv-negativ-Abstand beim langen Magneten von 
3,8ms*1340/7000=0,73ms

Meine Lösung sieht so aus:
Der PIC ist ein 16F88 mit 8MHz-Quarz, und ich nutze die ISR. Das 
Positivsignal geht auf RB0 und INT0 ist aktiviert. Das negative Signal 
geht auf RB4 und das RBIE-Bit von INTCON ist aktiviert -> bei jedem 
Positivimpuls und bei jedem Signalwechsel des Negativimpulses wird ein 
Interrupt ausgelöst.
Bei der ISR werden zu Beginn die Flags abgefragt: Ist INT0IF gesetzt, 
geht's zum INT0-Teil, ist RBIF gesetzt, wird der RB-Block abgearbeitet. 
Nur diese beiden Ereignisse können Interrupts auslösen.
Beim INT0-Teil wird TMR2 gestartet. Er wurde so mit Pre- und Postscaler 
konfiguriert, daß er nach 0,73 ms überläuft.
Beim RBIE-Teil wird TMR2 gestoppt und resettet.
Ein gesetztes TMR2IF zeigt den Überlauf und somit die Erkennung des 
langen Magneten an. Dieser ist zwar in diesem Moment schon wieder 
"vorbei", aber ich iniitiere beim nächsten positiven Impuls einen 
Counter, der von 3 runterzählt. Dieser Counter wird bei jedem folgenden 
Positivimpuls dekrementiert; bei 0 angekommen, weiß ich, jetzt ist es 
der lange Magnet.
RB5,6 und 7 ändern sich nicht und lösen keinen Interrupt aus.

Soweit die Theorie. Leider funktioniert es so in der Praxis nicht. Habt 
Ihr ein paar gute Tips, wo noch die Fehlerquellen sein könnten?

Gruß
Th.
von iaoffline (Gast)


Lesenswert?

Thomas M. schrieb:
> Soweit die Theorie. Leider funktioniert es so in der Praxis nicht. Habt
> Ihr ein paar gute Tips, wo noch die Fehlerquellen sein könnten?

Was funktioniert nicht? Eingrenzen ist das Prinzip fast jeder 
Fehlersuche. Also erstmal schauen ob der Pic
1. das Signal empfängt,
2. den Interrupt auslöst
3. der Timer läuft usw.

Das ist über einen Port an dem der Status H/L ausgegeben wird leicht 
machbar.
von Alex (Gast)


Lesenswert?

Mit dem Interrupt des Port B ist das so ne Sache.

Ich kenne das von der 18F... Serie:
Wenn du den "Interrupt on change" des Port B nutzen möchtest, musst du 
nach dem der Interrupt ausgelöst wurde immer (!) den Port lesen. Du 
kannst den Wert lesen und verwerfen, wenn du die Information nicht 
brauchst. Nur nach einem Lesen des Ports wir bei einer erneuten Änderung 
am Port ein erneuter Interrupt ausgelöst, sonst nicht. Bei den normalen 
Interrupteingängen ist das Lesen nicht erforderlich.

Auf diesen Umstand bin ich bei der Implementierung eines DCF77 Empfänger 
gestoßen. Habe dabei einiges an Zeit verlohren, da dieser Hinweis etwas 
versteckt im Datenblatt steht.

Vielleicht hilf dir das ja weiter? Eine genauere Fehlerbeschreibung wäre 
aber auf jeden Fall noch hilfreich.

Gruß Alex
von Thomas M. (xt-fahrer)


Lesenswert?

Das ist der Beginn meiner ISR:
[code]
    btfss INTCON,INT0IF
    btfss INTCON,RBIF
    goto Int0
    movf PORTB,W    ; PORTB auslesen
    BCF INTCON,RBIF
    bcf T2CON,TMR2ON  ; TMR2 stoppen
    goto isr_end
Int0
[\code]

Du siehst, das hatte ich bereits berücksichtigt. Ich dachte vielleicht, 
es liegt daran, daß positiv- und negativsignal so dicht beieinander 
liegen. INT0 wird bei steigender Flanke ausgelöst, aber es gibt ja diese 
Latenzzeit von 3-4 Maschinenzyklen vom Ansteigen der Flanke bis zum 
Sprung zu Adresse 4h. Eigentlich dürfte das kein Problem sein: Die 
Pulsbreite von ca. 1,3ms bei 1340 U/min nimmt umgekehrt proportional zur 
Drehzahl ab. Bei 7000 U/min haben wir demnach 1,3ms*1340/7000=250µs. Bei 
einem Taktzyklus von 500ns und 2µs Maschinenzyklus bin ich doch locker 
innerhalb der toleranz,oder?

Th.
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.