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.
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
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?
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 | }
|
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.
Taster und Unterbrechungen sind nicht die besten Freunde. Frag den Eingang lieber "normal" ab und filtere das Ganze mit einer Entprellroutine.
@ 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.
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
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.
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
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
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
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?
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
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.
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
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.
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.
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
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 ;).
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.