PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Sprung aus ISR?



Robtec
10.12.2009, 11:16
Hallo,

Für ein automatisches Regalsystem wird ein Notausschalter über einen Interrupteingang ausgewertet (INT2, ATMega32). Tritt der Interrupt auf, möchte ich sämtliche Motoren anhalten, danach Referenzfahrten durchführen. Damit die Auswertung der Gabellichtschranke (Int0 und Int1) sowie der Regelkreis (Zeitmessung über Timer0) funktionieren muss aber erst die ISR des Notaus beendet werden, damit die anderen ISR wieder funktionieren (wenn ich das so richtig verstanden hab).

Nun die Frage: wie kann ich in der Notaus-ISR eine Subroutine aufrufen, die abgehandelt wird nachdem die ISR beendet ist?

Eine Variable setzen wäre eine Möglichkeit, doch dann müsste ich in jede Programmschleife in der das Programm verweilt einen verweis auf die sub einbauen.

Vielen dank schon mal für eure Antworten

mws-h
10.12.2009, 11:33
Wenn ich das richtig in Erinnerung habe muss ein NOT-Aus tatsächlich alles lahm legen auf der Energieführenden Seite.

Also müsste nach dem Not Aus der Atmel wieder gestartet werden. Da wird doch sicher eine Startroutine den Startzustand herstellen oder?

Robtec
10.12.2009, 16:52
Hallo,

mein Notaus schaltet nicht den Strom aus, sondern leitet bei den Motoren eine Vollbremsung ein. Alles ist weiterhin mit Strom versorgt.

Besserwessi
10.12.2009, 17:19
Wenn es möglich ist, sollte beim Notaus der Strom direkt unterbrochen werden, also ohne einen µC.

Es kann aber auch sein, dass man den Motor noch Bremsen muß oder sonstige nicht so einfache Aktionen (z.B. Licht an, Türen entriegeln, Lüftung noch ein paar Sekunden weiterlaufenlassen) ausführen muß, dann ist es OK das auch per µC zu machen. Der µC sollte dann in aller Regel aber auch einen Watchdogteimer und ähnliches haben.

Man wird deshalb vermutlich von der ISR mehr oder weniger einen Klatstart ausführen müssen, fast so als wäre ein Reset ausgeführt. Das Wäre z.B: ein Sprung an die Addresse 0.
Allerdings kann man dann kaum das normale Programm weiterführen - bei einem Notaus auch kaum sinnvoll.

PICture
10.12.2009, 18:40
Hallo!

Am einfachsten ist es in der ISR ein Flag setzen und dem Hauptprogramm das Flag überwachen lassen. Wenn das Flag gesetzt wird, sollte bestimmtes Unterprogramm aufgerufen werden. Das Flag muss während der Ausführung des Unterprogramms gelöscht werden.

MfG

TurboBusen
10.12.2009, 18:50
Besserwessi hat Recht!
Ein NOTAUS hat eine Anlage in einen gefahrlosen Zustand zu versetzen. Wie das zu geschehen hat - aktiv oder passiv - hängt von der Anlage ab, und ist von einer verantwortlichen Person festzulegen, also z.B. der Projektingenieur.

Ein Notaus per Software wird auch durch Verwendung eines ext. Interrupts nicht sicherer.

TurboBusen

TurboBusen
10.12.2009, 19:21
Hallo!

Am einfachsten ist es in der ISR ein Flag setzen und dem Hauptprogramm das Flag überwachen lassen. Wenn das Flag gesetzt wird, sollte bestimmtes Unterprogramm aufgerufen werden. Das Flag muss während der Ausführung des Unterprogramms gelöscht werden.

MfG

Na dann könnte ich mir ja gleich den Interrupt sparen und den Eingangspin im Hauptprogramm abfragen.

Ein NOTAUS ist in Hardware zu realisieren, ggf. durch eine spezielle redundante Steuerungen auch in Software. Der AVR darf allenfalls mitbekommen, dass ein NOTAUS betätigt wurde und die Wiedereinschaltung nach einem Bedienereingriff einleiten.

TurboBusen

Robtec
11.12.2009, 10:04
Hallo,


Na dann könnte ich mir ja gleich den Interrupt sparen und den Eingangspin im Hauptprogramm abfragen.


Genau das ist mein Problem. Ich wollte über einen Interrupt gehen, um nicht überall in den verschiedenen Schleifen des Hauptprogramms den Pin bzw. Flag überprüfen lassen zu müssen (ca. 15 verschiedene Schleifen in denen das Programm verweilen kann).

Ein Sprung an Zeile 0 wäre eine Option, ich möchte aber eher eine Subroutine "Notaus" aufrufen, welche die Motoren bremst und bestimmte Stellungen anfährt. Damit dies möglich ist müssen aber meine anderen ISR wieder funktionieren. Also entweder muss ich meine ISR ohne Return verlassen oder die anderen ISR müssen weiterarbeiten obwohl ich mich noch in der ISR "Notaus" befinde.
Geht das irgendwie?

Danke für eure Hilfe
Robtec

PicNick
11.12.2009, 10:21
Du kannst in der ISR die Interrupts auch wieder enablen
"enable interrupts"
und dann die Not-Sub normal "gosubben"

CAVE: es kann dann aber auch die gegenständliche ISR nochmals aufgerufen werden. also aufpassen

Besserwessi
11.12.2009, 10:25
Man kann zur Not ISRs wieder Zulassen in einer ISR. Das ist schon in C nicht einfach, bei BASCOM hat man da zusätzliche Probleme mit sehr hohem Stackverbrauch. Auch muß man sicher gehen das der gleiche Interrupt nichtnochmal auftritt. Gerade für eine Sache die zuverlässig sein soll, sollte man nicht eine solch fehlerträchtige Methode wählen.

Der bessere Weg wäre wohl der Kaltsstart.
Das Programm muß dazu am Anfang klären, was den Reset ausgelöst hat und ggf. über Werte im IO Registern klären ob es ein echter Reset, oder der Sprung nach 0 war. Dann fängt das Programm sozusagen mit einem Notaus an, wenn kein echter Reset die Ursache war.
Wenn da was schief geht, hat man am ehesten einen versehentlichen Notaus. Denn kann man über Störungen am Int Pin aber auch so bekommen.

Wenn der Notaus sicherheitsrelevant ist, dann muß / sollte man das aber schon direkter in Hardware haben - Je einfacher desto besser, also eher Relais als Halbleiter. Vermutlich so, daß die Hardware die Motoren ausschaltet und die Software sich die Postionen usw. merkt damit danach wieder kontrolliert angefahren werden kann und ggf. ein Notbetreib möglich ist.

Die Referenzfahrten usw. sollte man ohnehin erst wieder beim Einschalten danach durchführen.

Robtec
11.12.2009, 10:44
Danke,

wenn die Sache so ausfändig ist werd ich es über ein Flag realisieren. Hab nur gehofft dass es (über einen mir noch unbekannten Befehl) eleganter gehen würde.

Robtec

wassermann
11.12.2009, 11:25
Hallo Robtec,

ich kann zwar nicht zur Lösung beitragen. Trotzdem ein Tip.
"Automatisches Regalsystem" hört sich nach gewerblicher Nutzung einer Anlage aus dem Maschinenbau an. Und da würde ich aus Erfahrung ganz genau die Vorschriften beachten. Not-Aus ist klar definiert bzw. wird nach SIL eingestuft und muss entsprechend realisiert werden.
Vielleicht kannst du es in deiner Anwendung als "Anlagen-Aus" einstufen; dann wird das ganze technisch und rechtlich viel einfacher.

Nicht falsch verstehen. Aber da bewegt man sich im Schadensfall mit einem Fuss im Kerker und der Staatsanwalt/TÜV zerfleischt dich.

gruss,
wassermann

guenter1604
11.12.2009, 11:27
Hallo Robtec,

beim Thema Notaus würde ich keine Kompromisse machen. Ein Schütz sollte die Stromversorgung der Motoren trennen, außerdem kannst du den MCU auf Reset ziehen. Das würde auch Überraschungen beim wiedereinschalten vorbeugen, da ein definierter Zustand eintritt.

Günter

Robtec
11.12.2009, 11:35
Hi,

Zur Info: Ich studiere Maschinenbau an der Uni Stuttgart und das System ist im Rahmen einer Studienarbeit entstanden. Es ist ein kleines System, an dem die Funktionweise von Sensoren und Aktoren gezeigt werden soll, sowie deren Verknüpfung zu einem mechatronischen System. Bei dem Notaus geht es rein um die Funktion dass ich im alles jederzeit anhalten kann. Sonst müsste ich noch ganz andere Sicherheitsvorschriften beachten. Evtl. kann dies eine Folgearbeit leisten.
Ich finde aber wirklich gut wie eindringlich hier auch vor möglichen Folgen gewarnt wird, es gibt sicher den ein oder anderen der sich was zusammenschustert ohne die rechtliche Seite zu beachten.

Gruß
Robtec

TurboBusen
11.12.2009, 11:42
"Automatisches Regalsystem" hört sich nach gewerblicher Nutzung einer Anlage aus dem Maschinenbau an.

War auch mein erster Gedanke.

@Robotec: Poste uns doch bitte mal ein Bild von diesem Regalsystem, damit wir alle wissen womit wir es überhaupt hier zu tun haben.

TurboBusen

yaro
12.12.2009, 10:26
Wie schon gesagt wurde, ist es durchaus möglich während eines Interrupts einen weiteren Interrupt zu bedienen. Dafür muss das I-bit im SREG gesetzt werden. Zu Stack-Problemen sollte sowas eigentlich nicht führen, wenn dieser Not-Aus-Interrupt nicht sehr häufig hintereinander ausgeführt wird (=> Taste entprellen!!!).

Gruß, Yaro

radbruch
12.12.2009, 11:02
Hallo

Das RETI am Ende einer ISR ist eigentlich ein normales Return das zusätzlich noch das betreffende Interruptflag löscht. Und da ein Return nur den Programmcounter mit dem obersten Wert des Stacks lädt, würde es ausreichen, wenn man in der ISR die orginale Rücksprungadresse vom Stack entfernt und durch die Adresse des Befehls ersetzt, bei dem das Programm nach dem Return fortgesetzt werden soll. Die ISR sollte wohl am Besten mit NOSAVE aufgerufen werden...

Wie man das umsetzt kann ich als Bascomlaie im Moment auch nicht sagen. Der Ansatz wird u.A. hier diskutiert:
http://robotikportal.de/phpBB2/viewtopic.php?p=425913#425913

Gruß

mic

yaro
12.12.2009, 12:58
Das mit dem RETI ist glaub ich nicht ganz richtig....
Soweit ich weiß, wird das Flag von der Hardware gelöscht, sobald die ISR ausgeführt wird.
Das RETI unterscheidet sich von einem normalen RET dadurch, dass das I-bit im SREG gesetzt wird.
Nichtsdestotrotz sollte das mit dem Austauschen der Rücksprungadresse theoretisch möglich sein. Die Frage ist nur, ob das mit dem Bascom Compiler so einfach funktioniert, denn es könnte sein, dass dann irgendwelche Daten, verloren gehen (z.B. die, die sich während des Aufrufs der ISR gerade in Arbeitsregistern befanden).... da müsste man sich eingehend mit dem Compiler beschäftigen und ggf. nötige Daten zwischenspeichern.
Außerdem könnte sowas zu Problemen mit dem Speicher führen, weil Variablen, die auf dem Stack oder sonstwo vom normalen Programm zwischengespeichert wurden nicht wieder freigegeben werden, da das Programm an einer anderen Stelle weiterläuft, als geplant.

Gruß, Yaro

Besserwessi
12.12.2009, 13:45
Die Hardware löscht das Flag zum Signaliseren des Interrupts und das I.Flag im SREG damit kein weiterer Interrupt angesprungen wird.

Ein Austauschen der Rücksprung adresse ist nicht gut. Dann kann man nicht mehr zurück zum Hauptprogramm und kann den rest des Stacks, was immer da noch von Unterprogrammen USW drauf ist nicht nutzen.
Wenn man nicht zurück will, sollte man den Stack gleich ganz neu initialisieren, da sammelt sich nur Müll.

Zum sprung nach der ISR könnte man die Sprungadresse auf den Stack tun und dann per RETI springen, oder man macht es übersichtlicher per SEI und eien normalen Sprung.

Wenn man später noch zurück zu der Stelle will, wo der Interrupt auftrat, kann man das auch: dann bleibt aber die alte Rücksprungadresse auf dem Stack und wird dann, wenn man wietermachen will mit einem RET genutzt.

MagicWSmoke
12.12.2009, 15:23
Dann kann man nicht mehr zurück zum Hauptprogramm...

Ist so nicht richtig, das ist möglich indem man sich die Adresse merkt, an der vom Interrupt unterbrochen wurde.


Die Frage ist nur, ob das mit dem Bascom Compiler so einfach funktioniert, ...

Mit einem bisserl ASM tut es das ohne Weiteres. :)

Besserwessi
12.12.2009, 17:12
Es sollte zumindest meistens gehen. Bei zugriffen auf 16 Bit register (Timer, AD) könnte man schon ein paar überraschungen kriegen, wenn man nicht überall darauf achtet diese extra zu schützen. Es sind aber schon noch einige extra Maßnahmen nötig um damit klar zu kommen, das da so eine Art Superinterrupt zwischenkommen kann der vieles Verändern kann.

Es genügt nicht sich nur die Adresse zu merken um zurück in Hauptprogramm zu kommen, man braucht schon den ganzen Stackinhalt, incl. der geretteten Registerinhalte.

MagicWSmoke
12.12.2009, 17:30
man braucht schon den ganzen Stackinhalt, incl. der geretteten Registerinhalte.

Guter Einwand, aber Ersteren komplett zu sichern ist nicht notwendig, denn dann müsste auch jede ISR den Stack komplett sichern, was nicht der Fall ist, Letzteres dagegen ist notwendig.

Dabei gehe ich von einer Subroutine aus, die genau ein Label und ein Return besitzt.

Besserwessi
12.12.2009, 17:46
Man muß den Stackinhalt nicht extra Retten, man muß in nur einfach da lassen wo er ist. Das gleiche gilt auch die Rücksprungadresse. Damit hat man relativ viele Daten auf dem Stack und muß daher auch genügend Speicher dafür reservieren, das ist aber eine der leichteren Übungen.

MagicWSmoke
12.12.2009, 17:54
...man muß in nur einfach da lassen wo er ist.

So hab' ich das auch geschrieben.

guenter1604
18.12.2009, 11:25
Hallo Robtec,

ich habe mir nochmal dein erstes Posting durchgelesen. Was spricht eigentlich dagegen im Notausinterrupt nur ein Flag zu setzen, daß dann in der Hauptschleife abgearbeitet wird?
Wie wärs mit einer Variable Status?
Oder im Notausinterrupt erstmal alles abschalten und den Status setzen.
Dann kann in der Hauptschleife nach ein paar Tests wieder alles nach und nach eingeschaltet werden.

select case Status
case Notaus
'taster checken
'wenn ok Status auf Boot setzen
case Boot
'Initdinge abarbeiten
case Run

undsoweiter

Günter