PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Interrupt auswertung



cokie
14.09.2004, 21:55
Hy,
ich hab mal wieder ein problem.
Und zwar ich versuche ich das Tachosingal eines Stink normalen Computer lüfters auszuwerten. Bloß irgendwie klappt das nicht wirklich. Mir fällt langsam nichts mehr ein woran es liegt. Das lüftersignal liegt an Pin4 (int0) an.

hier mal der Code:


$regfile = "M8def.dat"
$crystal = 8000000
Config Lcd = 20 * 4
Config Lcdbus = 4
Config Lcdpin = Pin

Dim Zehler As Long

On Int0 Int0_int

Config Timer1 = Timer , Prescale = 256
'Hier wird das Unterprogramm festgelegt, das
'in dem von ihnen eingestellten Intervall aufgerufen wird
On Timer1 Timer_irq
'Diese Vorgabe wurde berechnet um die genaue Intervallfrequenz zu erreichen
Const Timervorgabe = 34286
'Hier werden die Timer aktiviert
Enable Timer1
'Hier wird der Timer und der Teiler festgelegt

Enable Int0
Enable Interrupts
Start Timer1
Zehler = 0
Do
Int0_int:
Incr Zehler
Loop




'Dies ist der Programmteil, der in dem von ihnen gewählten
'Intervall aufgerufen wird
Timer_irq:
Timer1 = Timervorgabe

Cls
Lcd Zehler

Return

End


Die timer sequenz hab ich von dem Tool "rnAvr" hier von der seite. O:)
Als µM nehme ich denn Mega8.
Ich hab schon denn ganzen Tag gesucht und gegoogelt aber nicht so richtig was gefunden...

THX Cokie

Edit:
Achso das zählen scheint mit dem Simulator zu klappen, bloß das anzeigen der Zahl auf dem LCD funkt. nicht.

Frank
14.09.2004, 22:07
Also da ist noch etwas falsches gewurschtel im Code. Was sollen diese Zeilen denn?

Do
Int0_int:
Incr Zehler
Loop

Ein Interrupt in einer Do Loop Schleife. Das kann so nicht gehen.

Ändere das mal so das nach der Konfigurierung folgendes kommt:

do
loop

' und nu Interrupt Routine

Int0_int:
Incr Zehler
return

Und wozu brauchst du überhaupt einen Timer? Soll der dazu dienen das ab und zu das LCD aktuallisiert wird? Ja kann man so machen. Du kannst es aber auch einfach in der do loop Schleife tun.

Gruß Frank

cokie
14.09.2004, 22:13
jetzt wo du das mit dem Timer sagst, kling logisch... werd ich mal probieren :)
Und zu dem interrupt stimmt. Der Interrupt wird ja ausgelöst wenn ein signal ankommt. Ich meisel ein mist in den Code ](*,)

Frank
14.09.2004, 22:24
:-)

cokie
14.09.2004, 22:45
Also richtig funtk das auch nicht. Habs mit Do_loop schleife und dem timer probiert. in der do-loop für das LCD wird dann bloß immer 11111111111 angezeigt, und mit dem timer immer bloß 1 bzw. 0 is ja ein bisschen wenig an umdrehungen....

E-Fan
15.09.2004, 09:42
Und wie siehts aus, wenn Du in der Schleife einen Wartebefehl einfügst, der etwas kürzer ist, als der Timer ist?!? (so 75% der Zeit, in der der Timer den Interrupt auslöst/ musste ausprobieren) Das Display braucht doch seine Zeit um die Zeichen aufzubauen. Wenn während dem Zeichenaufbau der "alten" Informationen aber schon wieder was neues reinkommt, dann kann es durchaus sein, das es zu einem Datenüberlauf kommt und deshalb nur "11111111" zu sehen ist.

mfG aus P
der E-Fan

cokie
15.09.2004, 12:30
Mit dem Wait funkt. das nich weil da anscheind auch keinen Interupts reagieren. Aber mit dem Timer läufts jetzt einiger massen. hab bloß ein Return vergessen. Ich hab aber noch ein problem das das siganl nicht richtig sauber anscheinden kommt. Weil die werte zwischen 2000-8000 Pendeln... Ich denke doch wenn die drehe zahl gleich bleibt sollte doch auch das singnal gleich bleiben, oder sehe ich das falsch?!?.

Frank
15.09.2004, 13:55
Eigentlich hätte es mit Wait auch gehen müssen. Kannst ruhig mal größeres Wait "Wait 3" (3 Sekunden) oder so nehmen.
Du kannst mal einen fertigen Code wie du ihn nu hast posten, damit man weiter sehen kann.
Die Anzeige im Timer könnte eventuell zu lange dauern. Dadurch werden dann Interrupts vom Tachogenerator übersehen.

cokie
15.09.2004, 14:55
So ich hab hier nochmal denn Code:



$regfile = "M8def.dat"
$crystal = 8000000
Config Lcd = 20 * 4
Config Lcdbus = 4
Config Lcdpin = Pin

Dim Zehler As Long

On Int0 Int0_int

Config Timer1 = Timer , Prescale = 256
'Hier wird das Unterprogramm festgelegt, das
'in dem von ihnen eingestellten Intervall aufgerufen wird
On Timer1 Timer_irq
'Diese Vorgabe wurde berechnet um die genaue Intervallfrequenz zu erreichen
Const Timervorgabe = 34286
'Hier werden die Timer aktiviert
Enable Timer1
'Hier wird der Timer und der Teiler festgelegt

Enable Int0
Enable Interrupts
Start Timer1

Int0_int:
Incr Zehler
Return



'Dies ist der Programmteil, der in dem von ihnen gewählten
'Intervall aufgerufen wird
Timer_irq:
Timer1 = Timervorgabe

Cls
Lcd Zehler
Zehler = 0

Return

End


Das dumme is nur jetzt zeigt er wieder bloß 1 manchmal 2 an... Ich fühle mich von dem ding langsam aber sicher verschauckelt :-k [/quote]

Frank
15.09.2004, 17:29
Da haste wieder was falsch in den "Code gemeiselt", wie du es vorher so schön formuliert hast. Du vergisst jedesmal das das Hauptprogramm immer weiterläuft. Bei dir läuft es in die Interrupt Routine rein.
Du musst nach der Konfigurierung eine do:loop Schleife rein hängen.
Probier es mal so:



$regfile = "M8def.dat"
$crystal = 8000000
Config Lcd = 20 * 4
Config Lcdbus = 4
Config Lcdpin = Pin

Dim Zehler As Long

On Int0 Int0_int

Config Timer1 = Timer , Prescale = 256
On Timer1 Timer_irq
Const Timervorgabe = 34286

Enable Timer1
Enable Int0
Enable Interrupts
Start Timer1

do
loop

Int0_int:
Incr Zehler
Return



'Dies ist der Programmteil, der in dem von ihnen gewählten
'Intervall aufgerufen wird
Timer_irq:
Timer1 = Timervorgabe

Cls
Lcd Zehler
Zehler = 0

Return

End



Es kann aber sein das es immer noch nicht geht, weil der LCD Befehl eventuell zu lange braucht. Dann müsstest du in der Interrupt Routine das Ergebnis in einer Variablen ablegen und in der do:loop Schleife dann diese Variable ab und zu ausgeben (ein Wait 2 oder so dann nicht vergessen).

Viel Spaß

cokie
15.09.2004, 20:37
Also ich hab das jetzt nochmal ausprobiert so wei es gesagt hast. Dannach hats auch weider was angezeigt aber allerdings sehr merk würdig. Und zwar im LCD steht dann 82400 zb. Und wenn ich die drehzahl verändere am Lüfter dann gehen bloß die zahlen nach der 8 runter. Die sind dann zwar fast richtig. pendel aber immer noch recht stark zwischen 500-1000, je nachdem wie schnell der Lüfter dreht.
Und das merkwürdigste is, das ich schon von anfang an werte im Im 60000-80000 bereich hab, und das obwohl der Lüfter entweder aus, oder sogar ganz ab is.
Hier mal der veänderte code.


$regfile = "M8def.dat"
$crystal = 8000000
Config Lcd = 20 * 4
Config Lcdbus = 4
Config Lcdpin = Pin
Config INT0 = LOW LEVEL
Dim Zehler As Long
Dim Ausgabe As Long

On Int0 Int0_int


Enable Int0
Enable Interrupts
Do
Wait 2
Ausgabe = Zehler
Cls
Lcd Ausgabe
Zehler = 0
Loop

Int0_int:
Incr Zehler

Return



'Dies ist der Programmteil, der in dem von ihnen gewählten
'Intervall aufgerufen wird


End 'end program

Ach ich hab übrigens mit Rising und Falling bzw. Low Level bei der Int0 config experimentiert. wenn ich Rising bzw. Falling drin stehen hab, kommen werte bloß im Hunderter bereich zustande, die sich auch nicht großartig veränderen wenn man die drehzahl ändert.

cokie
15.09.2004, 21:20
Ah ich habe mal ein bisschen nach geforstet. Und rausgefunden der Ausgang für das Tachosignal ein open-collector-ausgang is(hoffentlich richtig geschrieben). Und ich denke mir mal das dadurch die schaltung nicht richtig funkt.. Aber wie soll ich das jetzt änderen?!? Einfach ein Pull-Up wiederstand dran hängen?!?

Frank
15.09.2004, 23:08
Hi,
also da stecken noch ein paar Mankos in deinem Code. So darf der Interrupt nicht auf LowLevel definiert werden, sonst werden ständig Interrupts ausgelöst wenn das Signal auf GND liegt. Es soll aber nur ein Interrupt pro Takt aufgerufen werden. Der Fehler erklärt auch warum trotz nicht angeschlossenen Tachosignal werte entstehen. Leider hab ich mich mit Tachosignal noch nicht beschäftigt, aber ich nehme doch an das es pro Umdrehung einfach einen Impuls liefert.
Also solltest du erst mal checken ob die Impulse wirklich kommen. Ich hab dir das Programm ein wenig verändert. Probier es so mal.
Jetzt reagiert der Interrupt auf fallende Pegel. Zudem ist ein Pullup Widerstand eingeschaltet, so das der Port generell auf High gelegt wird.
Wenn alles klappt, müsste jetzt der Wert am Display mit den Umdrehungen ansteigen. Ich hab dir noch ein Wait eingefügt, damit du auch was am Display lesen kannst.

Gruß Frank



$regfile = "M8def.dat"
$crystal = 8000000
Config Lcd = 20 * 4
Config Lcdbus = 4
Config Lcdpin = Pin

Config pind.2=input
portd.2=1 'PullUp ein

Config Int0 = Falling
Dim Zehler As Long
Dim Ausgabe As Long

On Int0 Int0_int


Enable Int0
Enable Interrupts
Do
Ausgabe = Zehler
Cls
Lcd Ausgabe
Wait 1
Loop


Int0_int:
Incr Zehler
Return

End

cokie
15.09.2004, 23:34
Ich jetzt gerade mal einen 10KOhm pullup wiederstand dran gelötet und jetzt funkt das, war am anfang bloß ein bisschen Irritiertweil da bloß 35 stand die sich aber reglen ließen. Dann is mir ja eingefallen das ich ja bloß die Umdrehung pro sekunde messe und ich das ganze ja mal 60 rechnen muß und nun funkt das. Freu :cheesy:.

Und jetzt sehe ich denn code von dir wo der Interne Pullup aktiviert wird, und da könnte ich mir in denn hintern tretten das ich nicht selbst dran gedacht hab. ](*,)
Ach und das mit dem Low Level stand da noch drin weil ich damit experimentiert hab. Hatte es auch schon mit Falling ung Rising probiert. Aber jetzt funkts...
\:D/

Frank
15.09.2004, 23:37
Na dann ist ja alles bestens - dann viel Spaß noch bei der Vollendung des Programms