Forum: Mikrocontroller und Digitale Elektronik Interrupt reagiert nicht richtig


von Tim (Gast)


Lesenswert?

Hallo,

ich habe ein kleines Programm für eine Schiebersteuerung geschrieben, 
doch ich habe mit dem Interrupt probleme..

Ich habe ihn auf steigende Flanke eingestellt doch er ist immer in der 
ISR.
Nur wenn man an den Eingang eine 1 (5V) legt arbeitet das Programm wie 
es soll. (also wenn der Pin eigentlich eine 0 (0V bzw GND) haben sollte)

Alle Pins haben Pulldown Widerstände von 5,1kOhm und diese sind auch 
funktionstüchtig (gemessen).

Wenn ich den Interrupt aus dem Programm nehme funktioniert alles so wie 
es soll aber da muss ja ein Fehler in der Konfiguration liegen?

Wenn ich den Interrupt auf Falling stelle verändert sich nichts..

Kann mir jemand sagen wo/ob ich ein Fehler gemacht habe?

Der Interrupt liegt am Pin D.2.

(Hier mal der config Ausschnitt)
Config Pinb.0 = Input                                       'Schieber 
offen
Config Pinb.1 = Input                                       'Schieber 
geschlossen
Config Pind.4 = Input                                       'Taster 
Schieber AUF
Config Pind.2 = Input                                       'Taster 
Schieber ZU
Config Portc.1 = Output                                     'Relais 
Schieber AUF
Config Portc.2 = Output                                     'Relais 
Schieber ZU

On Int0 Stop_1
Config Int0 = Rising
Enable Int0
Enable Interrupts

Do


Hoffe ihr könnt mir helfen.. Sitze schon ein paar Tage daran.

von Martin M. (ats3788)


Lesenswert?

Hallo
Um was für eine MCU etc. handelt es sich ?

von Z42 (Gast)


Lesenswert?

Tim schrieb:
> Wenn ich den Interrupt aus dem Programm nehme funktioniert alles so wie
> es soll aber da muss ja ein Fehler in der Konfiguration liegen?

Nö, alles richtig.

von Paul B. (paul_baumann)


Lesenswert?

Tim schrieb:
> Kann mir jemand sagen wo/ob ich ein Fehler gemacht habe?

Wahrscheinlich in der Interuptroutine mit dem Namen "Stop_1", denn deren
Quelltext ist nicht da.

mfG Paul

von Frank (Gast)


Lesenswert?

Ist der interne Pullup an?

von Tim (Gast)


Lesenswert?

Martin Michael schrieb:
> Hallo
> Um was für eine MCU etc. handelt es sich ?

Paul Baumann schrieb:
> Wahrscheinlich in der Interuptroutine mit dem Namen "Stop_1", denn deren
> Quelltext ist nicht da.

Hier nochmal das komplette Programm...
(der interrupt ist gerade nur probehalber da und doch nicht ins programm 
eingebunden.)


Und ja ich weiß es gibt Programme die besser aussehen aber eine bessere 
Variante ist mir grad nicht eingefallen :D

$regfile = "m328pdef.dat"
$crystal = 16000000
$hwstack = 64
$swstack = 64
$framesize = 64

Declare Sub Countinput
Declare Sub Schieber_auf
Declare Sub Materiallaufzeit
Declare Sub Schieber_zu

Dim A As Byte , B As Byte


Config Pinb.0 = Input                                       'Schieber 
offen
Config Pinb.1 = Input                                       'Schieber 
geschlossen
Config Pind.4 = Input                                       'Taster 
Schieber AUF
Config Pind.2 = Input                                       'Taster 
Schieber ZU
Config Portc.1 = Output                                     'Relais 
Schieber AUF
Config Portc.2 = Output                                     'Relais 
Schieber ZU

On Int0 Stop_1
Config Int0 = Rising
Enable Int0
Enable Interrupts

Waitms 50

Do

If Pind.4 = 1 Then A = 1
Waitms 200
If A = 1 And Pind.4 = 1 Then
Gosub Countinput
Null:
If Pind.4 = 0 Then A = 0 Else Goto Null
End If


Loop
End


'----------------------------------------------------------------------- 
--------
Sub Countinput                                              'Auf 5 
Tastendrücke warten
B = B + 1
If B = 5 Then
B = 0
Gosub Schieber_auf
End If
End Sub

'----------------------------------------------------------------------- 
--------
Sub Schieber_auf

Portc.1 = 1                                                 'Motor 
Schieber_auf anschalten
Eins:
If Pinb.0 = 1 Then
Portc.1 = 0                                                 'Auf Sensor 
Schieber_offen warten 
'motor Ausschalten
Else                                                        'und dann 
Motor Schieber_auf abschalten
Goto Eins
End If
Gosub Materiallaufzeit

End Sub

'----------------------------------------------------------------------- 
--------
Sub Materiallaufzeit

Wait 60
                                                 '
Gosub Schieber_zu

End Sub

'----------------------------------------------------------------------- 
--------
Sub Schieber_zu

Portc.2 = 1                                                 'Motor 
Schieber_zu anschalten
Zwei:
If Pinb.1 = 1 Then
Portc.2 = 0                                                 'Auf Sensor 
Schieber_geschlossen warten 
'motor Ausschalten
Else                                                        'und dann 
Motor Schieber_zu abschalten
Goto Zwei

B = 0 
'Tastendrücke zurücksetzen

End If

End Sub

'----------------------------------------------------------------------- 
--------
Stop_1:

Portc.1 = 0
B = 0


Return

von Z42 (Gast)


Lesenswert?

Tim schrieb:
> Hier nochmal das komplette Programm...
> (der interrupt ist gerade nur probehalber da und doch nicht ins programm
> eingebunden.)

Gute Idee. Ich habe ehrlich versucht da durch zu steigen, aber durch die 
Formatiereung kommen Kommentare und Programmm durcheinander. Das mach 
ich nicht mit. Häng es als Textdatei oder formatiert an deinen Post an. 
Die Vorschau hilft dir dabei deinen Post vor Absenden zu überprüfen.

Was ist Eingang?

von Tim (Gast)


Angehängte Dateien:

Lesenswert?

Das Programm befindet sich im Anhang und nochmal komplett leserlich 
formatiert hier.

Wie gesagt das Problem besteht darin das ich immer ein 5V Pegel am 
Interrupt haben muss damit das Programm funktioniert..
1
$regfile = "m328pdef.dat"
2
$crystal = 16000000
3
$hwstack = 64
4
$swstack = 64
5
$framesize = 64
6
7
Declare Sub Countinput
8
Declare Sub Schieber_auf
9
Declare Sub Materiallaufzeit
10
Declare Sub Schieber_zu
11
12
Dim A As Byte , B As Byte
13
14
15
Config Pinb.0 = Input                'Schieber offen
16
Config Pinb.1 = Input                'Schieber geschlossen
17
Config Pind.4 = Input                'Taster Schieber AUF
18
Config Pind.2 = Input                'Taster Schieber ZU
19
Config Portc.1 = Output              'Relais Schieber AUF
20
Config Portc.2 = Output              'Relais Schieber ZU
21
22
On Int0 Stop_1
23
Config Int0 = Rising
24
Enable Int0
25
Enable Interrupts
26
27
Waitms 50
28
29
Do
30
31
If Pind.4 = 1 Then A = 1
32
Waitms 200
33
If A = 1 And Pind.4 = 1 Then
34
Gosub Countinput
35
Null:
36
If Pind.4 = 0 Then A = 0 Else Goto Null
37
End If
38
39
40
Loop
41
End
42
43
44
'-------------------------------------------------------------------------------
45
Sub Countinput                     'Auf 5 Tastendrücke warten
46
B = B + 1
47
If B = 5 Then
48
B = 0
49
Gosub Schieber_auf
50
End If
51
End Sub
52
53
'-------------------------------------------------------------------------------
54
Sub Schieber_auf
55
56
Portc.1 = 1                        'Motor Schieber_auf anschalten
57
Eins:
58
If Pinb.0 = 1 Then
59
Portc.1 = 0                        'Auf Sensor Schieber_offen warten
60
                                   'und dann Motor Schieber_auf Ausschalten
61
Else                                                      
62
Goto Eins
63
End If
64
Gosub Materiallaufzeit
65
66
End Sub
67
68
'-------------------------------------------------------------------------------
69
Sub Materiallaufzeit
70
71
Wait 60
72
                                                 '
73
Gosub Schieber_zu
74
75
End Sub
76
77
'-------------------------------------------------------------------------------
78
Sub Schieber_zu
79
80
Portc.2 = 1                        'Motor Schieber_zu anschalten
81
Zwei:
82
If Pinb.1 = 1 Then
83
Portc.2 = 0                        'Auf Sensor Schieber_geschlossen warten 
84
Else                               'und dann Motor Schieber_zu abschalten
85
Goto Zwei
86
87
B = 0                              'Tastendrücke zurücksetzen
88
89
End If
90
91
End Sub
92
93
'-------------------------------------------------------------------------------
94
Stop_1:
95
96
Portc.1 = 0
97
B = 0
98
99
100
Return

: Bearbeitet durch User
von MWS (Gast)


Lesenswert?

Schreib' mal statt Config Int0 ...:

EICRA = Bits(ISC01, ISC00)

von Tim (Gast)


Lesenswert?

Danke werde ich gleich morgen früh probieren wenn ich wieder Zuhause 
bin.

von Tim (Gast)


Lesenswert?

Also die Funktion des Programmes hat sich nicht geändert..

Ich muss immernoch die 5V an den Interrupt anlegen um das Programm 
ablaufen zu lassen. Er reagiert immernoch auf eine fallende Flanke.

von Klaus (Gast)


Lesenswert?

Au weia.

von Klaus (Gast)


Lesenswert?

Jetzt fängst Du mal schön von vorne an!

Erstmal einfach eine LED toggeln.

Dann mit Flanken-Interrupt.

Und wenn Du damit Probleme kriegst, postest Du Schaltplan, Aufbaufotos 
und Code im Anhang, so wie es in den Hinweisen direkt über dem Feld 
zum schreiben neuer Beiträge steht. "Netiquette" lesen wäre direkt auch 
mal "nett"!

Dabei entdecken wird dann das Prellen. Ja, ja.

Und formatieren geht anders. Das ist ja wohl überhaupt nix gewesen, 
bisher.
Formatieren erfordert selektives Einrücken

Ist denn immer noch Wochenende, oder?

von Karl H. (kbuchegg)


Lesenswert?

Klaus schrieb:
> Jetzt fängst Du mal schön von vorne an!
>
> Erstmal einfach eine LED toggeln.
>
> Dann mit Flanken-Interrupt.

Du bist fies.

Warum sagst du ihm nicht gleich, dass Tastenauswertung mittels Interrupt 
auch BASCOM eine schlechte Idee ist.

Dafür gibt es in BASCOM den DEBOUNCE Mechanismus, der in jedem BASCOM 
Tutorial irgendwo vorkommt.

PS:
1
Zwei:
2
If Pinb.1 = 1 Then
3
Portc.2 = 0                        'Auf Sensor Schieber_geschlossen warten 
4
Else                               'und dann Motor Schieber_zu abschalten
5
Goto Zwei

auch in BASCOM sind while Schleifen schon lange erfunden. Da muss man 
nicht wie ein Wilder mit GOTO um sich werfen.

: Bearbeitet durch User
von Klaus (Gast)


Lesenswert?

> Du bist fies.

Ja! :-)


Ich denke da an diese "Ja" von dem Wirt in der Spelunke, in der Claudia 
Cardinale in "Spiel mir das Lied vom Tod" auf dem Weg zu dem Haus ihres 
Mannes halt macht - gezwungenermaßen - denn, wie der Kutscher so schön 
sagt: "Halten die Dreckszüge nicht auch"?

von Tim (Gast)


Lesenswert?

Ich hatte auch schon die "Debounce" Befehle verwendet. Doch da hatte der 
Interrupt schon nicht funktioniert und ich habe es wieder rausgenommen 
weil ich weiß das die Goto Schleifen auf jedenfall funktionieren.

Also ein paar Grundkenntnisse habe ich schon es ist ja nicht mein erstes 
Programm was ich schreibe. Ich habe auch schon mehrere Lösungsansätze 
gehabt doch leider haben sie nicht geholfen.
Trotzdem gebe ich zu das ich noch in den Kinderschuhen stecke was das 
angeht aber ich bin ja lernwillig :)

Das Bascom nicht die beste Wahl ist, ist mir auch bewusst doch ich 
versteh es irgendwie besser als eine andere (Hoch)sprache..

Zum eigentlichen Problem:
Ich werde versuchen eine LED über eine positive Flanke zu toggeln.
Dann werde ich mich nochmal melden.

Bis dahin bin ich für weitere Vorschläge offen woran es liegen könnte.

von Klaus (Gast)


Lesenswert?

Ich fürchte das Problem liegt im OSI Layer 8.

Man muss zugeben, dass Interrupts auf der einen Seite und Behandlung von 
externen Ereignissen auf der Anderen zu den eher schwierigen Kapiteln 
gehören, bei denen Programmierkenntnisse nur bedingt helfen.

- Der DEBOUNCE-Befehl wird nicht in Interrupts verwendet. Das ist 
nicht nötig und sogar falsch.

- Du hast eher das Problem, dass Du asynchron oder jedenfalls 
quasi-asynchron auf ein Ereignis reagieren musst. Das ist bei Deinem 
Vorhaben aber eher einfach (soweit ich es aus dem Programmtext erkennen 
kann).

Versuche es einfach mal ohne Interrupt und mit Debounce. Falls es nicht 
klappt, frage wieder hier. Karl Heinz wird bestimmt wieder helfen. :-)

von Klaus (Gast)


Lesenswert?

In Bezug auf externe Ereignisse, oder noch relevanter, externe Systeme 
werden Interrupts eigentlich nur verwendet, wenn das Signal das von 
diesem System kommt, ganz bestimmte Kriterien erfüllt.

Im allgemeinen ist die Anstiegszeit und die Dauer des Pegels, der dem 
Ereignis folgt im Datenblatt festgelegt. Mach Dir mal den Spaß und 
versuche das im Datenblatt Deines uC zu finden.

Ausserdem ergibt sich oft aus der Anwendung, das dieses Signal sich nur 
mit einer maximalen Rate wiederholen darf, weil der uC bzw. sein 
Programm sie nur mit dieser Rate verarbeiten kann.


Taster und mit ihnen alle anderen mechanischen Vorrichtungen, die eine 
elektrische Verbindung herstellen oder unterbrechen erfüllen diese 
Voraussetzung sehr oft nicht.

Schaue hier auch mal in den Artikeln zu Interrupts und Entprellen. Dann 
siehst Du ein wenig klarer.

Was die quasi-asynchronen Ereignisse betrifft, gibt es hier auch einige 
Artikel, aber Du solltest zumindest erstmal versuchen es selbst zu 
schreiben. Selbst wenn das fehlschlägt ist es sehr lehrreich.

von MWS (Gast)


Lesenswert?

Tim schrieb:
> Ich hatte auch schon die "Debounce" Befehle verwendet.

Du müsstest das Störfeuer beider Poster in gewissem Umfang ignorieren, 
denn obwohl deren Aussagen grundsätzlich nicht verkehrt sind, so tragen 
sie nichts zur potentiellen Thematik bei, dass der Flanken-Interrupt auf 
Level triggert.

Ein Prellen dürfte keinen Einfluss auf den gezeigten Code haben.

> Das Bascom nicht die beste Wahl ist, ist mir auch bewusst doch ich
> versteh es irgendwie besser als eine andere (Hoch)sprache..

Wenn das Deine Einschätzung ist, dann solltest Du etwas anderes nehmen 
und Dich wundern, welche enorme Schwierigkeiten Du dann damit hast, bis 
Du überhaupt anfangen kannst, etwas in den Controller zu schreiben.
Uns sei es noch so falsch. LOL

Nicht programmieren zu können (das ist aus Deinem Code ersichtlich) ist 
übrigens an keine Programmiersprache gebunden, das funktioniert 
sprachübergreifend.

Zum Thema: um genau erkennen zu können, was passiert, kannst Du beim 
Verändern des PortC.1 noch ein Wait setzen, damit wird der Ablauf 
verzögert und der Ablauf lässt sich besser nachvollziehen. Zum Testen 
kann man das auch im Interrupt machen, was man sonst tunlichst 
vermeidet.

Auch ratsam, schreib' mal die Bascom-Version rein, vielleicht hast Du 
eine alte Version.

Tim schrieb:
> Alle Pins haben Pulldown Widerstände von 5,1kOhm und diese sind auch
> funktionstüchtig (gemessen).

Trifft dies sicher auch auf PD2 zu? Sonst fängt sich der Störsignale 
ein.

Ich würde mal die Hauptschleife leeren und dort nur Testcode 
reinschreiben, um den Flanken-Interrupt auszuprobieren.

von Tim (Gast)


Lesenswert?

MWS schrieb:
> Trifft dies sicher auch auf PD2 zu? Sonst fängt sich der Störsignale
> ein.

Ja Das trifft auch auf diesen Eingang zu.

MWS schrieb:
> Nicht programmieren zu können (das ist aus Deinem Code ersichtlich) ist
> übrigens an keine Programmiersprache gebunden, das funktioniert
> sprachübergreifend.

Ich musste lachen aber es stimmt :D
Ich beschäftige mich auch mit der Thematik erst seit knapp zwei Monaten 
und ich denke jeder hat mal klein angefangen.


Bei dem Interrupt habe ich mich an meinem vorherigen Programm orientiert 
bei dem er tadellos seinen dienst tut. Deswegen kam es mir auch komisch 
vor das es in dem "Programm" auf einmal nichtmehr geht.
Aber in dem anderen Programm habe ich auch nur eine Variable hochgezählt 
die den Programmablauf über ein "Select Case" ändert.

Ich werde wenn ich Zuhause bin ersteinmal hinsetzen und die 
Hauptschleife leeren und schauen was sich dabei ergibt.

Danke schonmal

von MWS (Gast)


Lesenswert?

Wenn Du das hex-File hier einstellst, dann sag' ich Dir, ob der Int0 
richtig konfiguriert wird.

von Tim (Gast)


Angehängte Dateien:

Lesenswert?

Im anhang ist das Hex-File

von Tim (Gast)


Lesenswert?

Also wenn der Interrupt nur eine LED Toggelt reagiert er auf eine 
steigende Flanke.. also scheint die Einstellung ja zu klappen.

Habe nur das Hauptprogramm auskommentiert und den Interrupt auf die LED 
umgestellt.

von MWS (Gast)


Lesenswert?

Das hex schau' ich im Lauf des Tages an.
Um auszuschließen, dass eine wartende Interruptanforderung hier stört, 
lösche ein evtl. gesetztes Interruptflag wie folgt:

> On Int0 Stop_1
> Config Int0 = Rising
> Enable Int0
Set EIFR.INTF0
> Enable Interrupts

von Klaus (Gast)


Lesenswert?

Das ist, vorausgesetzt Du betätigst den Eingang tatsächlich mit einem 
Taster - das hast Du ja bisher weder bestätigt noch bestritten -, 
lediglich Zufall.

Als nächstes machst Du das ohne Interrupt und mit DEBOUNCE.

Und immer schön die Quelltexte zeigen!

von MWS (Gast)


Lesenswert?

Klaus schrieb:
> Das ist, vorausgesetzt Du betätigst den Eingang tatsächlich mit
> einem Taster ... lediglich Zufall.

Man kann problemlos mit wenig Testcode zwischen Flanken- und 
Levelinterrupt unterscheiden, selbst dann, wenn's nur Klingeldraht statt 
'nem Taster ist.

Magst Du vielleicht Deine Aussage näher erläutern, damit alle noch was 
lernen? LOL

Der TO kennt sich in dieser Hinsicht bereits besser aus als Du, denn er 
toggelt eine LED, das taugt als Test.

Tim schrieb:
> Also wenn der Interrupt nur eine LED Toggelt reagiert er auf eine
> steigende Flanke.. also scheint die Einstellung ja zu klappen.

von Simpel (Gast)


Lesenswert?

Erstmal würde ich dem Ganzen eine saubere Struktur verpassen. Die ganzen 
sub-Aufrufe in die Main und nicht innerhalb der subs in die jeweils 
nächste springen und am Ende durch alle Returns wieder zurück.

Dann das Ganze weg vom Schrittschaltwerk-Modus mit seinen ellenlangen 
wait-Narkose-Zuständen, hin  zu einem Freeflow mit Zustands-Auswertung.

Dann kann man z.B. auch jederzeit die Funktionalität erweitern und z.B. 
manuelle Aktionen, bzw. Automatikfunktionen, die einen blockierten 
Schieber erkennen (Timeout) und freifahren, etc. integrieren, oder die 
Sache per UART überwachen und eingreifen... und und und...

Wenn jetzt z.B. der Schieber blockiert, dann kommt der Motor ins 
Schwitzen und die ganze Schrittschaltkette steht endlos. Sowas ist schon 
prinzipiell nicht praxistauglich.

von MWS (Gast)


Lesenswert?

MWS schrieb:
> Das hex schau' ich im Lauf des Tages an.

Int0 wird im hex korrekt konfiguriert, wenn obiger Code also nicht 
klappt, dann nicht weil der Interrupt auf Level arbeitet.

Das kannst Du einfach testen, lass' PD2 offen, also nur per Pulldown an 
GND und füge wie oben beschrieben das Löschen des Interruptflags ein.

Dann müsste Dein Code unbeeinflusst vom Interrupt arbeiten.
Tut er das dennoch nicht, kann es sich auch um ein Hardwareproblem 
handeln, indem z.B. die Hardware gegen die Störimpulse der Relais nicht 
ordentlich abgesichert ist.

Wenn da etwas einstreut, dann wird der Interrupt ausgelöst, und zerwirft 
über das Schalten des Ausgangs, bzw. das Rücksetzen der Variable den 
gewünschten normalen Programmablauf. Der externe Interrupt muss schnell 
reagieren und das macht er auch auf kurze Störimpulse.

Ein weiterer Weg wäre, falls der Interrupt nur in einem bestimmten 
Abschnitt benötigt würde, ihn nur dafür scharf zu schalten und nach 
Auslösung zu deaktivieren. Auch dafür muss das Interruptflag vorher 
gelöscht werden, da sich der µC darin auch Ereignisse merkt, wenn der 
Interrupt nicht aktiv war. Wird der Interrupt dann aktiviert, so löst 
dieser sofort aus, obwohl kein Signal, sondern nur die 
Interruptanforderung da war.

Also z.B.
1
' Aktiviere Int
2
Set EIFR.INTF0
3
Enable Int0
4
'... 
5
6
Stop_1:
7
  Disable Int0
8
    Portc.1 = 0
9
      B = 0
10
Return

Damit sperrt sich der Interrupt, sobald er einmal auslöste und muss von 
der entsprechenden Routine, die darauf reagiert, wieder aktiviert 
werden.

Aber, das ist trotzdem alles Anfängercode, richtig würde man den 
gewünschten Ablauf über eine "State Machine", auf Deutsch 
"Zustandsautomat" erzeugen, man nimm dann auch keine 60 Sekunden langen 
Waits, sondern man setzt einen Timer ein.

Dieser Timer und auch die Schaltkontakte werden im Zustandsautomaten 
laufend abgefragt und im Falle einer bestimmten Aktion wie dem Schließen 
eines Kontakts, wird ein anderer Zustand eingenommen. Den Automaten kann 
man vom Timer antreiben lassen und hat dann automatisch einen zeitlich 
genau definierten Durchlauf.

Interrupts kann man auch dort einsetzen, wenn z.B. eine unmittelbare 
Reaktion gefordert ist, wie Motor geht in den Anschlag -> Kontakt ein -> 
Motor aus, denn da hätte der Zustandsautomat eine gewisse Verzögerung, 
die sich über die Durchlaufzeit ergibt. Dem Automaten kann man die 
interruptgesteuerte Aktion über ein Flag mitteilen.

So ein Zustandsautomat ist nichts Kompliziertes, im einfachsten Fall ein 
Select-Case Block, der in einer Endlosschleife durchlaufen wird, die 
Cases selbst stellen die Zustände dar und in einer Variablen wird der 
momentane Zustand gemerkt.

Wichtig dabei ist: es findet nichts mehr blockierend statt, es gibt 
keine Waits, Waitms mehr, da muss man allerdings erstmal umdenken 
können.

von Tim (Gast)


Lesenswert?

Ich habe das Programm mal ein bisschen bearbeitet..
Jetzt habe ich das Problem das sich das Programm nachdem es 
durchgelaufen ist (was es anstandslos tut) immer wieder in die letzte 
Routine springt..
Der Interrupt funktioniert jetzt auch richtig ich habe ihn nebenbei mal 
eine LED togglen lassen doch er setzt die Variable (Modus) nicht zurück.
Weder im normalen Programm noch beim Interrupt.

Habe jetzt schon verschiedene Versuche durchgeführt die Variable 
zurückzusetzen:
Modus = 0 ,
Reset Modus,
verschiedene If Schleifen und
eine Goto Verknüpfung.
Aber nichts davon setzt den Modus zurück durch den das Programm 
neustartet.

Und ja an den Eingängen die mit Taster bezeichnet sind hängen auch 
wirklich Taster.


Hier das "neue" Programm:

$regfile = "m328pdef.dat"
$crystal = 16000000
$hwstack = 64
$swstack = 64
$framesize = 64

Declare Sub Countinput
Declare Sub Schieber_auf
Declare Sub Materiallaufzeit
Declare Sub Schieber_zu

Dim A As Byte , B As Byte , Modus As Byte


Config Pinb.0 = Input                   'Schieber offen
Config Pinb.1 = Input                   'Schieber geschlossen
Config Pind.4 = Input                   'Taster Schieber AUF
Config Pind.2 = Input                   'Taster Schieber ZU
Config Portc.1 = Output                 'Relais Schieber AUF
Config Portc.2 = Output                 'Relais Schieber ZU

Config Portc.3 = Output                 'LED

On Int0 Stop_1
Config Int0 = Rising                    'Eicra = Bits(isc01 , Isc00)
Enable Int0
Enable Interrupts

Waitms 50


Do


Select Case Modus
   Case 0 : Call Countinput
   Case 1 : Call Schieber_auf
   Case 2 : Call Materiallaufzeit
   Case 3 : Call Schieber_zu
End Select


Loop
End


'----------------------------------------------------------------------- 
--------
Sub Countinput                          'Auf 5 Tastendrücke warten
   Debounce Pind.4 , 1 , Zaehlen
End Sub

'------------
Zaehlen:
   Incr B
   If B = 5 Or B = 10 Then Incr Modus
Return

'----------------------------------------------------------------------- 
--------
Sub Schieber_auf

While Pinb.0 = 0                        'Auf Sensor Schieber_offen 
warten
   Portc.1 = 1                          'Motor Schieber_auf anschalten
Wend

Portc.1 = 0                             'Motor Schieber_auf abschalten
Incr Modus

End Sub

'----------------------------------------------------------------------- 
--------
Sub Materiallaufzeit

Wait 15
Incr Modus

End Sub

'----------------------------------------------------------------------- 
--------
Sub Schieber_zu

While Pinb.1 = 0                   'Auf Sensor Schieber_geschlossen 
warten
   Portc.2 = 1                     'Motor Schieber_zu anschalten
Wend

Portc.2 = 0                        'Motor Schieber_zu abschalten

'Reset Modus                       'Tastendrücke zurücksetzen
Modus = 0
'If Modus > 0 Then Modus = 0

End Sub

'----------------------------------------------------------------------- 
--------
Stop_1:

Modus = 0
Toggle Portc.3                     'LED

Return

Hoffe ihr könnt mir auch dabei helfen

von MWS (Gast)


Lesenswert?

A verwendest Du nicht und B setzt Du nicht zurück, somit bleibt das 
Programm bei Zaehlen hängen. Allerdings, wenn Du den Taster an PD4 so 
oft betätigst, dass die Variable B überläuft, dann geht's auch wieder, 
;D

von Tim (Gast)


Lesenswert?

Ah ich sehe den fehler :D
war vllt doch schon ein bisschen spät :D

von Peter D. (peda)


Lesenswert?

Tim schrieb:
> Portc.1 = 1                          'Motor Schieber_auf anschalten

Man kann sich das Leben deutlich vereinfach, wenn man kryptische 
Portnummern als Klarnamen definiert.
Nimmt man z.B. "Motor_Schieber = 1", kann man sich den Kommentar sparen.

Den Programmierer interessiert nicht der Pin, sondern was daran 
angeschlossen ist. Auch kann man dann leichter die Pinbelegung ändern, 
ohne den sämtlichen Code nach jedem Eintrag durchsuchen zu müssen.

Auch nichts sagende Variablennamen A,B machen das Lesen nur unnötig 
schwer.

Bessere Lesbarkeit bedeutet immer auch geringere Fehlerquote.

von Tim (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Man kann sich das Leben deutlich vereinfach, wenn man kryptische
> Portnummern als Klarnamen definiert.
> Nimmt man z.B. "Motor_Schieber = 1", kann man sich den Kommentar sparen.

Das Habe ich jetzt auch gemacht.

MWS schrieb:
> Also z.B.
> ' Aktiviere Int
> Set EIFR.INTF0
> Enable Int0
> '...
>
> Stop_1:
>   Disable Int0
>     Portc.1 = 0
>       B = 0
> Return

Auch das ist jetzt in meinem Programm.

MWS schrieb:
> Aber, das ist trotzdem alles Anfängercode, richtig würde man den
> gewünschten Ablauf über eine "State Machine", auf Deutsch
> "Zustandsautomat" erzeugen, man nimm dann auch keine 60 Sekunden langen
> Waits, sondern man setzt einen Timer ein.

Da bin ich gerade dabei den Timer1 zu integrieren.


Da das Programm läuft bedanke ich mich ersteinmal bei allen für die 
Hilfen und komme auch gleich dazu das das Interruptproblem nichts mit 
der Software zu tun hatte..
Es war das Verbindungskabel zum Taster (Schieber_auf). Als ich dieses 
Testweise ausgelötet hatte war der Interruptfehler auf einmal weg.
Anderes Kabel eingelötet und es geht immernoch.

von Klaus (Gast)


Lesenswert?

> ... das das Interruptproblem nichts mit der Software zu tun hatte.

Seufz.

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.