PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : INT mehrmals auslösen



fauldrache
27.06.2004, 11:52
Hallo zusammen.

Ich bin gerade fleissig am Programmieren und habe unteranderem einen Notstop für meinen Robo miteingebaut (Schalter vorne ->int0). Ich benutze BasCom und in der Hilfe ist das alles ja wunderschön erklärt.
Nur eines bekomme ich nicht auf die Reihe:
Wenn der Interrupt auslöst, dann läuft mein Label dafür ab, wie es sollte, dann gehe ich mit return zurück und dann geht das Hauptprogramm weiter. Aber jetzt ist der Interrupt tot, es ist also egal, ob ich den Taster drück oder nicht. Ich habe schon probiert, die "on int0" an verschiedene Stellen zu schreiben, hat aber nichts genützt.
Hier ist mein Code, zuerst wird alles configuriert dann

Config Int0 = Low Level 'collision(notstop) an d.2
Config Int1 = Low Level 'collision(ir-warnung) an d.3

On Int0 Notstop Nosave
On Int1 Ausweichen Nosave

Start Adc
Enable Interrupts
Enable Int0
Enable Int1

dann kommt das programm und zum schluss


Notstop:
Compare1a = 0
Compare1b = 0 'Motoren Stop
For Z0 = 0 To 3 Step 1
Portd.5 = 1 'BEEP
Waitms 300
Portd.5 = 0
Waitms 400
Next
Print "------------------"
Print "ACHTUNG ! Kollision erfolgt! Bitte Hindernis enfernen !"
Print "------------------"
Wait 2
Haltep1:
C0 = Pind.3 'Abfrage des Kolli-Tasters
If C0 = 1 Then
Return
Else
Goto Haltep1
End If
Return

Es geht mir nur darum, wie ich die INT eingänge "wieder Scharfmachen" kann, der rest läuft wunderbar.
Ich wäre für eine kleine Hilfe sehr dankbar.

Schönen Sonntag noch
Basti

Flite
27.06.2004, 13:07
Hallo Basti!

Ich kann dir jetzt nicht sicher sagen, an was genau es liegt. Aber vielleicht ist es einer der Punkte,die ich an dem Programm noch verbessern würde ...

1. Wenn dein Roboter nicht gerade mit Schallgeschwindigkeit durch den Raum fährt (natürlich übertrieben - aber die meisten Roboter fahren doch recht langsam) benötigst du weder für den Abstandssensor noch für den taster eine Interrupt Routine. Ohne zu wissen mit welchem uC du arbeitest noch welche Taktfrequenz du verwendest würde ich mal mutmaßen, dass das ganz einfach mit Polling auch funktionieren sollte. Wenn nicht, dann reicht auf jeden Fall ein einzelner Interrupt für beide Ereignisse aus ...

2. Du solltest den Taster auf jeden Fall hardwaremäßig (oder besser softwaremäßig entprellen). Jeder mechanische Taster hat die angewohnheit mehrmals auszulösen (innerhalb von wenigen us). Damit dann nicht deine Interruptroutine 10 Mal aufgerufen wird musst du nach eiem Interruptereignis ein paar us (je nach Tasterqualität) warten, bis du das nächste Interruptereignis zulässt. In deinem Fall würde ich einfach zu Beginn der Interruptroutine den Int0 und Int1 abschalten und vor dem Return wieder anschalten. Das sollte ausreichend sein.

3. So - jetzt noch meine Vermutung, warum dein Programm nicht richtig geht: Bei dir im Programm fehlt die Hauptschleife. Ich denke, dass dein uC irgendow im nicht genutzen Flash rumgeistert und das etl. Probleme macht. Also füg mal unter der Initialisierung eine Hauptschleife ein...

Hoffe dir geholfen zu haben.

Grüße
Flite

fauldrache
27.06.2004, 14:45
Hallo Flite,

Zu 1.
Ich habe einen Mega 8 mit 4MHz und fahre ca. mit 1-2 km/h, also recht langsam.
Ich habe gerade in der Hilfe rumgesucht, aber nichts über "polling" gefunden. Ich hatte auch zuerst nur einen Interrupt, aber da ich sowiso beide Sensoren anschliessen muss, und den Int1 nicht andersweitig brauche, habe ich das mit beiden gemacht. In der Hilfe steht, dass der INT0 den INT1 überlagern kann. Kannst du mir einen Tipp geben, wo ich was über polling finde?

Zu 2.
Meine Taster, die die Kollision anzeigen, sind hardwaremässig über ein FlipFlop entprellt. Brauche ich dann noch die Software ?

ZU 3.
Die Hauptschleife gibt es natürlich. Ich habe nur, um das Posting nicht zu lang zu machen, nur die config int... und das Label, auf das der int springt angehängt. In der Hauptschleife werden dann die SUBs aufgerufen, die die Motoren steuern.

Ich habe gerade von anderer Seite gehört, dass man bei Interrupts mit "Reti" wieder rausgehen muss, finde aber auch dazu nichts sinnvolles in der Hilfe. Sagt dir das Irgendwas?

Ok, trotzdem Danke für die schnelle Antwort.

Basti

Flite
27.06.2004, 14:59
Hallo Basti,

zu 1:
Polling ist das 'Gegenteil' zu Interrupt.
Beim Interrupt wird bei einer Änderung des Eingangpins (z.B. fallende Flanke) das Hauptprogramm vom Prozessor selbst unterbrochen und sofort in die Interruptroutine gesprungen um möglichst schnell (wenige us) auf ein Ereignis reagieren zu können.

Polling (zu deutsch: abfragen) heißt einfach nur, dass du in deiner Hauptschleife immer wieder abfrägst, ob der Pin jetzt High ist oder immernoch low. Das hat eine weit geringere (je anch größe der Hauptschleife) Ansprechgeschwindigkeit, aber reicht z.B. bei einem Taster, der durch einen Menschen bedient wird in der Regel weit aus ...
Je nach größe der Hauptschleife sollte das bei dir auch gut ausreichen.

Wenn du natürlich die ext. Interrupts nicht anderweitig benötigst, kannst du das auch so weiterlaufen lassen. Nur falls du vor hast den Roboter später weiter auszubauen und du gegebenenfalls die ext. Interrupts brauchst kannst du dieses sicherlich guten gewissens entbehren ...

zu 2.
Wenn die Taster korrekt hardwaremäßig entprellt sind (was über ein Flipflop möglich ist) bruachst du natürlich nicht mehr softwaremäßig zu entprellen.

zu 3.
Dann ist natürlich alles klar. Falls du den fehler nicht finden solltest - wäre es evtl nicht schlecht mal das gesamte Programm zu posten ...


Ich habe noch nie in Bascom programmiert. In Assembler ist es tatsächtich so, dass du mit RET von einem Unterprogramm zurückspringst und eine Interrupt Routine mit reti verlässt. In wieweit das in Bascom notwenidg ist weiß ich nicht. Aber dass sollte ja eigentlich in der Hilfe stehen.

Viele Grüße
Flite

Flite
27.06.2004, 16:04
Hallo Basti,

ich hab grade mal bei Bascom nachgeschaut und folgendes gefunden (wie du auch bei Elektronik Projekt):



Label2:
Dim A As Byte
If A > 1 Then
Return 'generates a RET because it is inside a condition
End If
Return 'generates a RETI because it is the first RETURN
Return 'generates a RET because it is the second RETURN


Und nun ein Stück deines Codes:



If C0 = 1 Then
Return
Else
Goto Haltep1
End If
Return


Wenn ich das richtig interpretieren, dann erzeugt Bascom für dein erstes RETURN ein RET (da innerhalb einer Bedingung) und beim zweiten Mal ein RETI

Also ich denke, das ist der Fehler. Am besten du definierts eine Sprungmarke vor dem letzten Return und springst aus der Bedingung dahin mit Goto.

Grüße
Flite

fauldrache
27.06.2004, 19:33
Ich habe deinen Tipp beherzigt, und den Schalter nun einfach jedes Mal mitabgefragt. Das langt immer noch dicke von der Geschwindigkeit her. Ausserdem ist das zurückhupfen viel einfacher. (und es funktioniert mehrmals...).
So, dann lass ich den INT halt mal frei, vielleicht benutze ich ihn mal für was anderes.

Danke nochmal.

Basti