Forum: Mikrocontroller und Digitale Elektronik Interrupt für ein paar Sekunden sperren


von Tobi H. (smoothoperator)


Angehängte Dateien:

Lesenswert?

Guten Tag zusammen,

Der Schaltplan soll ne simple Toranzeige mit Sound für einen Kickertisch 
sein. Nachdem ich meine Lichtschranken (ich weiß das Schaltbild ist 
nicht normgetreu) getestet habe fiel mir auf, dass diese beim Auslösen 
mehrere Spitzen schalten, ähnlich wie beim Tastenprellen. Diese sollen 
aber einen externen interrupt auslösen, und einen Zähler fürs Tor eben 
um genau 1 erhöhen. Dieses will ich verhindern, indem ich eben nur ein 
Signal zulasse, ohne mit nem Delay zu arbeiten. Ich bin im Interrupt 
Programmieren noch nicht so fit. Es müsste doch ne Möglichkeit geben 
nach einem ext. Signal den Interrupt für etwa 3 bis 5 Sekunden zu 
sperren.
Oder reicht es nen Kondensator mit rein zu schalten?

Vielen Dank schon mal.

von Karl H. (kbuchegg)


Lesenswert?

Tobi H. schrieb:

> dass diese beim Auslösen
> mehrere Spitzen schalten, ähnlich wie beim Tastenprellen.

Dann kannst du auch genau dieselben Techniken benutzen, die man fürs 
Tastenentprellen benutzt.

Entprellung

> um genau 1 erhöhen. Dieses will ich verhindern, indem ich eben nur ein
> Signal zulasse, ohne mit nem Delay zu arbeiten.

Gute Einstellung. Delays sind selten die Lösung, aber oft das Problem.

> Ich bin im Interrupt
> Programmieren noch nicht so fit. Es müsste doch ne Möglichkeit geben
> nach einem ext. Signal den Interrupt für etwa 3 bis 5 Sekunden zu
> sperren.

Falscher Ansatz.
Der ganze Ansatz, die Lichtschranke auf einen externen Interrupt zu 
hängen ist schon zweifelhaft. Das würde ich erst mal wie eine ganz 
normale Tastenabfrage behandeln. Ev. kann es höchstens sein, dass man 
die Zeitkonstanten etwas reduzieren muss, da der Ball die Lichtschranke 
nicht besonders lange unterbricht. Ein externer Interrupt für die 
Lichtschranken verkompliziert hier nur alles, ohne dass du etwas dafür 
kriegst.

: Bearbeitet durch User
von Peter II (Gast)


Lesenswert?

Wie bist du auf die Widerstände an der Lichtschranke gekommen?

Das ist doch am ende ein Spannungsteiler, damit stellt sich eine 
Spannung irgendwo bei 3V ein, dieser Bereich ist nicht definiert.

Hast du mal gemessen, welche Spannung jeweils bei offenen und 
geschlossenen Lichtschrank am µC anliegen?

von Stefan S. (sschultewolter)


Lesenswert?

Externe Interupts halte ich auch für überflüssig in diesem 
Anwendungszweck. Bau dir einen Timer auf. z.B. für milliseconds.
1
// ...
2
ISR(TIMER0_COMPA_vect) { millis++; }
3
4
int main(void)
5
{
6
TCCR0A = (1 << WGM01);          // CTC Mode
7
  TCCR0B |= (1 << CS01) | (1 << CS00);  // Prescaler 64
8
  OCR0A = 124;              // (F_CPU/PRESCALER)/1000-1
9
  TIMSK0 |= (1 << OCIE0A);        // Compare Interrupt
10
  sei();
11
12
  while(1)
13
  {
14
    static uint32_t last_millis;
15
    if(millis >= last_millis && /* TOR erkannt */)
16
    {
17
      last_millis = millis + 100; // Zeit, wie lange danach kein Signal mehr reinkommen soll.
18
19
    }
20
  }
21
}

von Karl H. (kbuchegg)


Lesenswert?

Deine Anzeige kann auch nicht funktionieren. Der ULN2803 ist ein Open 
Collector Treiber. D.h. er schaltet seine Ausgänge gegen Masse. So 
werden deine Anzeigen nie die Spannung sehen, die sie zum leuchten 
brauchen.

von Amateur (Gast)


Lesenswert?

Taster und Unterbrechungen sind nicht die besten Freunde.

Frag den Eingang lieber "normal" ab und filtere das Ganze mit einer 
Entprellroutine.

von Tobi H. (smoothoperator)


Lesenswert?

@ Peter II
Ja stimmt der Spannungsteiler ist falsch. Das werde ich noch mal 
korrigieren.
Nein die Spannung hab ich noch nicht gemessen, werd ich mal machen.

@ Karl Heinz

Dein Ansatz scheint mir auch nicht schlecht. Hab mich etwas an dem 
Interrupt festgebissen, da der Ball zu Zeiten doch sehr schnell die 
Schranke unterbricht, und deswegen mein Ansatz über den Interrupt.
Aber dein Vorschlag erscheint mir sehr plausibel, ich werd das mal so 
machen und dann testen.

von Karl H. (kbuchegg)


Lesenswert?

Tobi H. schrieb:
> @ Peter II
> Ja stimmt der Spannungsteiler ist falsch. Das werde ich noch mal
> korrigieren.

Der springende Punkt ist:
Du brauchst überhaupt keinen Spannungsteiler (wenn deine Lichtschranke 
mit 5V betrieben werden kann). Einfach den Pin auf Eingang setzen, den 
Pullup einschalten und vom Pin direkt zum Transistor von der 
Lichtschranke. Der Transistor in der Lichtschranke fungiert wie ein 
Taster (ist auch so eingezeichnet) und zieht den Pin auf 0 wenn die 
Lichtschranke unterbrochen/nicht unterbrochen ist.

> Dein Ansatz scheint mir auch nicht schlecht. Hab mich etwas an dem
> Interrupt festgebissen, da der Ball zu Zeiten doch sehr schnell die
> Schranke unterbricht

rechne mal nach.
Wie schnell ist der Ball?
Sagen wir mal 100km/h. Das sind 27m/s

Welchen Durchmesser hat der Ball?
Ich schätze mal 3cm. Nehmen wir einfach mal 1cm, da der Ball ja nicht 
immer mit seinem Mittelpunkt durch die Lichtschranke laufen wird. D.h. 
die Lichtschranke wird von einem Objekt unterbrochen, welches eine 
Ausdehnung von 0.01m hat und welches mit einer Geschwindigkeit von 27m/s 
da durchrauscht. Wie lang dauert daher die Unterbrechung?
1
   27   ........  1s
2
   0.01 ........  x
3
  --------------------
4
       1 * 0.01
5
   x = ---------- = 0.00037s
6
          27
Also 0.3 Millisekunden oder 300 µs.

Dein µC ist mit 1Mhz getaktet. D.h. pro ca 1.5µs führt der einen Befehl 
aus. In den 300µs, die der Ball die Lichtschranke unterbricht, kann der 
µC also rund 200 Befehle ausführen.

Führst du eigentlich die Lichtschranke per Umlenkspiegel ein paar mal 
hin und her um einen Lichtvorhang zu erzeugen? Würde ich auch jeden Fall 
machen. Auch würde ich ein paar Taster vorsehen, um ev. den µC 
korrigieren zu können, wenn zb jemand versehentlich in die Lichtschranke 
greift bzw. wenn der Ball von der Rückwand abprallt und wieder 
zurückkommt bzw. wenn es einen Lattenpendeler gibt und er Ball nicht im 
Tor landet aber trotzdem die Lichtschranke unterbricht.

: Bearbeitet durch User
von Peter II (Gast)


Lesenswert?

Karl Heinz schrieb:
> Dein µC ist mit 1Mhz getaktet. D.h. pro ca 1.5µs führt der einen Befehl
> aus. In den 300µs, die der Ball die Lichtschranke unterbricht, kann der
> µC also rund 200 Befehle ausführen.

was schon verdammt knapp werden kann, wenn das Programm noch etwas 
größer wird.

Ich würde es hier auch mit einer Interrupt lösen, dort nur ein Flag 
setzen und dann die Auswertung in der Main machen, dann kann man dort 
auch die Sperrzeit prüfen.

von Karl H. (kbuchegg)


Lesenswert?

Peter II schrieb:
> Karl Heinz schrieb:
>> Dein µC ist mit 1Mhz getaktet. D.h. pro ca 1.5µs führt der einen Befehl
>> aus. In den 300µs, die der Ball die Lichtschranke unterbricht, kann der
>> µC also rund 200 Befehle ausführen.
>
> was schon verdammt knapp werden kann, wenn das Programm noch etwas
> größer wird.

Was soll da noch grösser werden? Die Hauptschleife ist im wesentlichen 
einfach nur 2 Flankenerkennungen. Die Technik, die Stefan weiter oben 
zum Ignorieren von Fehlpulsen benutzt hat sieht mir recht brauchbar aus, 
kommt aber nur im Falle einer Flankenerkennung zum Zug. D.h. Die 
Hauptschleife besteht im 'Idle-Mode' aus vielleicht 10 bis 20 Takten. 
Zeit genug. Zumal ich auch mit meiner Meinung nach übertrieben großen 
Zahlen gerechnet habe bzw. die kleinste Taktrate abgenommen habe, die 
praktisch möglich ist. Internen Takt auf 8Mhz und er hat schon ca. 1600 
Befehle pro Unterbrechnung Zeit um die Unterbrechung zu detektieren. Da 
müsste er sich in der Programmierung schon sehr dumm anstellen um da was 
zu verpassen.

: Bearbeitet durch User
von Peter II (Gast)


Lesenswert?

Karl Heinz schrieb:
> Was soll da noch grösser werden? Die Hauptschleife ist im wesentlichen
> einfach nur 2 Flankenerkennungen.

irgendwelche Sounds bei Toor abspielen - woher soll ich das wissen.

Es ist aber auch kein Nachteil es mit einer ISR zu lösen, außerdem kann 
man so den µC auch schlafen legen und er spart Energie.


Karl Heinz schrieb:
> Zumal ich auch mit meiner Meinung nach übertrieben großen
> Zahlen gerechnet habe.

http://www.tischfussball.de/images/maxim/pages/maxim05_jpg.htm

über 200km/h, soviel zu übertrieben großen Zahlen

von Karl H. (kbuchegg)


Lesenswert?

Peter II schrieb:
> Karl Heinz schrieb:
>> Was soll da noch grösser werden? Die Hauptschleife ist im wesentlichen
>> einfach nur 2 Flankenerkennungen.
>
> irgendwelche Sounds bei Toor abspielen - woher soll ich das wissen.

So wie das aussieht hat er da ein Soundmodul dafür.


> http://www.tischfussball.de/images/maxim/pages/maxim05_jpg.htm
>
> über 200km/h, soviel zu übertrieben großen Zahlen

Oh, das wusste ich nicht. Ich hab geschätzt.
Ok, dann sind wir bei 800 Befehlen (bei sinnvollen 8Mhz Taktfrequenz) in 
der Hauptschleife während der Unterbrechung. Immer noch massig für
1
...
2
3
   lightPreviousLeft  = PIND & ( 1 << PD2 );
4
   lightPreviousRight = PIND & ( 1 << PD3 );
5
6
   while( 1 ) {
7
8
      lightNow = PIND & ( 1 << PD2 );
9
      if( lightNow != lightPreviousLeft ) {
10
        if( lightNow ) {
11
          .... Zeit prüfen, ob die Unterbrechung gezählt werden soll
12
        }
13
        lightPreviousLeft = lightNow;
14
      }
15
16
      lightNow = PIND & ( 1 << PD3 );
17
      if( lightNow != lightPreviousRight ) {
18
        if( lightNow ) {
19
          ... Zeit prüfen, ob die Unterbrechung gezählt werden soll
20
        }
21
        lightPreviousRight = lightNow;
22
      }
23
   }
24
}

Im wesentlichen wirds nicht mehr und nach einem Tor hat der µC alle Zeit 
der Welt, die Anzeige auf den neusten Stand zu bringen und das 
Soundmodul zu triggern.

: Bearbeitet durch User
von Peter II (Gast)


Lesenswert?

Karl Heinz schrieb:
> Ok, dann sind wir bei 800 Befehlen (bei sinnvollen 8Mhz Taktfrequenz) in
> der Hauptschleife während der Unterbrechung. Immer noch massig für

ist ja richtig, aber einen Grund warum eine ISR hier nicht sinnvoll ist, 
hast du damit nicht genannt.

Warum ständig etwas prüfen, wenn man sich auch benachrichtigen kann? 
Oder stellst du dein Handy auch auf stumm und schaust jede Sekunde drauf 
ob ein Anruf ankommt?

von Karl H. (kbuchegg)


Lesenswert?

Peter II schrieb:
> Karl Heinz schrieb:
>> Ok, dann sind wir bei 800 Befehlen (bei sinnvollen 8Mhz Taktfrequenz) in
>> der Hauptschleife während der Unterbrechung. Immer noch massig für
>
> ist ja richtig, aber einen Grund warum eine ISR hier nicht sinnvoll ist,
> hast du damit nicht genannt.

Weil ich mich um kein Interrupt Flag kümmern muss, dass nach der 
erlaubten Sperrzeit wieder gelöscht werden muss; weil ich keine 
Kommunikation ISR Hauptschleife dafür brauche.
Den einzigen Vorteil, den ich sehe ist, dass die Flankenerkennung von 
der Hardware gemacht wird.

> Warum ständig etwas prüfen, wenn man sich auch benachrichtigen kann?
> Oder stellst du dein Handy auch auf stumm und schaust jede Sekunde drauf
> ob ein Anruf ankommt?

Nein.
Aber ich wähle die einfachste Lösung. Eine Flankenerkennung in der 
Hauptschleife IST einfach. Die macht das Kraut nicht wirklich fett.

: Bearbeitet durch User
von Peter II (Gast)


Lesenswert?

Karl Heinz schrieb:
> Weil ich mich um kein Interrupt Flag kümmern muss, dass nach der
> erlaubten Sperrzeit wieder gelöscht werden muss; weil ich keine
> Kommunikation ISR Hauptschleife dafür brauche.

dafür spart man sich die Abfrage von Pin und eine globale Variabel würde 
ich noch nicht als IPC bezeichnen.

von Karl H. (kbuchegg)


Lesenswert?

Peter II schrieb:
> Karl Heinz schrieb:
>> Weil ich mich um kein Interrupt Flag kümmern muss, dass nach der
>> erlaubten Sperrzeit wieder gelöscht werden muss; weil ich keine
>> Kommunikation ISR Hauptschleife dafür brauche.
>
> dafür spart man sich die Abfrage von Pin und eine globale Variabel würde
> ich noch nicht als IPC bezeichnen.

Ich sträub mich nicht gegen einen Interrupt, so ist das auch wieder 
nicht. Ich seh nur keinen wesentlichen Vorteil da drinnen.
Du kannst das ja mal als Code ausformulieren, wenn du ihm helfen willst.

: Bearbeitet durch User
von Peter II (Gast)


Lesenswert?

Karl Heinz schrieb:
> Du kannst das ja mal als Code ausformulieren, wenn du ihm helfen willst.

er soll erst mal die Schaltungsfehler beheben, eventuell geht ja dann 
sein Code schon, denn Lichtschranken prellen meist nicht so stark.

von Karl H. (kbuchegg)


Lesenswert?

Peter II schrieb:

> er soll erst mal die Schaltungsfehler beheben, eventuell geht ja dann
> sein Code schon, denn Lichtschranken prellen meist nicht so stark.

Darüber hab ich mir auch schon Gedanken gemacht, woher dieses Prellen 
kommen könnte.

Nichts desto trotz gefällt mir der Ansatz nach einem Tor die Erkennung 
für ein paar Sekunden zu sperren nicht so schlecht. Es kommt schon mal 
vor, dass nach einem Tor der Ball wieder aus dem Tor rausspringt. So 
eine Sperre würde dieses Problem recht einfach entschärfen. Zumal ja 
nicht 2 Sekunden nach einem Tor schon wieder weiter gespielt wird. Von 
daher gefällt mir Stefans Lösung (ich nenn das mal den Arduino-Ansatz) 
von weiter oben mit einer entsprechend langen Zeit da recht gut.

von Martin V. (oldmax)


Lesenswert?

Hi
An dieser Stelle bin ich auch (fast) der Meinung, das hier die Erfassung 
über ISR gelöst und mit einem Flag an die main übergeben werden sollte. 
Die Bälle sind schon ziemlich fix unterwegs. Allerdings stellt sich auch 
die Frage: Sind die Lichtschranken dem Signal gewachsen? Wenn da 
Kontakte drin verbaut sind, mag ich das bezweifeln.
Das Flag in der Main zu verlängern und so eine wiederholte Auslösung zu 
verhindern ist (auch in C) völlig unproblematisch. Sorry für das C, ich 
werd diese Sprache vermutlich nie mehr lernen.....
Gruß oldmax

: Bearbeitet durch User
von Ingo (Gast)


Lesenswert?

Stefan S. schrieb:
> if(millis >= last_millis && /* TOR erkannt */)
>     {
>       last_millis = millis + 100; // Zeit, wie lange danach kein Signal
> mehr reinkommen soll.
>
>     }
Nicht so gut! Was ist wenn millis auf 64000 steht, dann bei 2^16 - 1 
überlauft? Dann hast du dich verdammt lange ausgesperrt. Noch schlimemer 
wenn millis 32 Bit breit ist. Dann kannste haste dich knapp 50 Tage 
ausgesperrt ;).

von Stefan S. (sschultewolter)


Lesenswert?

Ingo schrieb:
> Stefan S. schrieb:
>> if(millis >= last_millis && /* TOR erkannt */)
>>     {
>>       last_millis = millis + 100; // Zeit, wie lange danach kein Signal
>> mehr reinkommen soll.
>>
>>     }
> Nicht so gut! Was ist wenn millis auf 64000 steht, dann bei 2^16 - 1
> überlauft? Dann hast du dich verdammt lange ausgesperrt. Noch schlimemer
> wenn millis 32 Bit breit ist. Dann kannste haste dich knapp 50 Tage
> ausgesperrt ;).

Ich bezweifel mal, dass der Kickertisch länger als 50 Tage läuft ;)
Irgendwann ist der Batteriewechsel nötig und dauerhaft ein Netzteil in 
der Steckdose lassen?
Hatte aber in dem Fall auch nur in der Abfrage vergriffen.

millis war als uint32_t.

Richtig hätte es meinerseit heißen sollen:
if(millis - last_millis >= 1000) { last_millis = millis; /* */ }
Der würde dann, wenn wir von einem uint8_t ausgehen,

millis = 5 (einmal rum)
last_millis = 250 (noch nicht rum)
interval = 5

millis(5) - last_millis(250) >= interval("255"-245)
richtig funktionieren, da die Variable bei unterschreiten von 0 wieder 
bei ihren Max-Wert anfängt zu subtrahieren

: Bearbeitet durch User
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.