Hallo zusammen, ich möchte gerne 8 Lichtschranken in einer Slotbahn verbauen um damit vorbeifahrende Autos zu erfassen. Es geht nicht um Rundenzeitmessung, sondern um eine Plazierungsanzeige. Also wer ist im Rennen erster, zweiter, dritter, usw. Die Ausgabe soll dann auf kleinen 7 Segment Anzeigen im oder am Regler der Fahrer gemacht werden. Die Autos werden vermutlich 10 Meter/Sekunde schnell und der Leitkiel der die Lichtschranke unterbricht, wird ca. 1cm lang sein. Das macht eine Unterbrechungsdauer von 1 Millisekunde. Nun suche ich nach einer Möglichkeit die Lichtschranken auszuwerten. Es gibt ja zwei grundsätzlich unterschiedliche Ansätze. Zum einen könnten die Lichtschranken per externem Interrupt das Auslesen initiieren. Egal welche Lichtschranke unterbrochen wird, wird der ext. Interrupt aktiviert und alle Lichtschranken werden ausgelöst. Und zum anderen könnte ein interner Timer das Auswerten auslösen. Also entweder per Polling oder per Interrupt. Mir fehlt noch jegliches Gefühl dafür, ob sich ein µController bei so was eher langweilt, oder ob er da schon kräftig arbeiten muss. Schön wäre ersteres, da der µController dann zukünftig auch noch andere Aufgaben übernehmen könnte. Im Moment setze ich einen ATmega8515 ein. Und die Lichtschranken könnten zur Zeit einen Port blockieren (8 Eingänge). Worauf muss ich bei meiner Planung achten, damit ich hierbei kein Timingproblem bekomme? Gruß Martin
Martin Brehme schrieb: > Mir fehlt noch jegliches Gefühl dafür, ob sich ein µController bei so > was eher langweilt, oder ob er da schon kräftig arbeiten muss. Lass ihn zwischendurch noch 'teuflisch schwierige quadratische Gleichungen lösen' (TM: Douglas Adams) sonst begeht dein AVR gleich Suizid, weil er nichts zu tun hat.
Das Aufnehmen der Einlaufreihenfolge ist kein besonders grosses Problem, Polling sollte da Dicke reichen. > Die Ausgabe soll dann auf kleinen 7 Segment > Anzeigen im oder am Regler der Fahrer gemacht werden. Darüber solltest du dir mehr Gedanken machen. Wie schliesst du 8 Stück 7-Segment Anzeigen an einem µC an?
8 Pins zur Auswahl der Anzeige und noch mal 8 gemeinsame Datenpins. Das ganze lässt sich doch dann ganz gut multiplexen
Karl heinz Buchegger schrieb: > Wie schliesst du 8 Stück > > 7-Segment Anzeigen an einem µC an? MAX7219
Martin Brehme schrieb: > damit ich hierbei kein > Timingproblem bekomme? und Martin Brehme schrieb: > der Leitkiel > der die Lichtschranke unterbricht, wird ca. 1cm lang sein. mmh, also wenn mehr als 2 im Abstand von 2-3mm hereinkommen hast du ein Problem, da hilft dann nur noch ein Zielfoto.
Also verstehe ich Euch richtig: Polling wäre Eure Wahl. Mit meinem bisherigen Wissen ist das wohl auch einfacher umzusetzen. > mmh, also wenn mehr als 2 im Abstand von 2-3mm hereinkommen hast du ein > Problem, da hilft dann nur noch ein Zielfoto. Also lassen wir die Kirche mal im Dorf! Wenn soetwas passiert, dann können die Autos gerne als Zeitgleich gewertet werden. Das muss dann halt nur bekannt sein, das es da Messgrenzen gibt. Aber mal was anderes. Es wäre schön, wenn Ihr das mit den 2-3 mm noch mal ausführlicher erklären würdet. Ich möchte einfach verstehen, wie Ihr zu den Aussagen kommt. Wie oft z.B. sollte ich die Lichtschranken abfragen? Wie geht Ihr an solche Timingfragen heran?
Wenn du einen ATmega64A nimmst hättest du 8 ext.Interrupt-Eingänge, die auf negative oder positive Flanke getriggert werden können. An jedem Eingang hängt eine Lichtschranke (wichtig für die Unterscheidung der Bahn). Der 1.Platz startet einen Timer und und der Startwert des Timers wird zwischengespeichert (0000). Die folgenden Plätze speichern nur die entsprechenden Zählerstände. Aus den Zählerstandswerten ermittels du die Rangfolge, setzt den Timer zurück und gibst die Rangfolge aus.
Die Probleme werden wohl woanders liegen... Zum erkennen ob eine Lichtschranke ausgelöst hat genügt wenn man alle verodert im einfachsten Fall über ein Diodenarray. Den veroderten Wert dann an den externen Interrupt und im Interrupt alle 8 Lichtschrankenstati solange auslesen bis alle wieder auf nicht mehr unterbrochen sind. So kann man auch erkennen wenn ein 2. Fahrzeug in eine Lichtschranke fährt wenn noch ein anderes drin ist. Doch zur Berechung wer 1., 2., etc ist muss man auch die Rundenzahl der Fahrzeuge kennen. Da eine Lichtschranke im Slot rel. empfindlich für ne Fehlmessung ist kann das ins Auge gehen. Ausserdem, wie steuert er die Displays in den Drückern an? Die sind normalerweise über eine oder mehrere Anschlussboxen mit 3 * 1 qmm CU Litze und 4mm Bananenstecker angeschlossen. Will er da noch ein 8pol Kabel mit passendem Stecker dazubinden? Besser wäre wahrscheinlich eine Lösung, die die Impulse an den wahrscheinlich vorhandenen PC zur Rennsteuerung / Rundenzeiterfassung etc. weiterleitet und dem die Anzeige überlässt.
Martin Brehme schrieb: > wenn Ihr das mit den 2-3 mm noch Habe ich jetzt mal so geschätzt.... Martin Brehme schrieb: > Polling wäre Eure Wahl. Also meine Wahl nicht, weil unter polling verstehe ich einen Eingang so lange abzufragen, bis sich was am Eingang ändert. Aber das würde den Proz. ja blockieren, es sei denn, ich hätte ein rtos laufen.
>Also meine Wahl nicht, weil unter polling verstehe ich einen Eingang so >lange abzufragen, bis sich was am Eingang ändert. Aber das würde den >Proz. ja blockieren, Und was hindert dich, in der Pollingschleife noch mehr zu machen, als nur den Eingang abzufragen ?
doc schrieb: > Und was hindert dich, in der Pollingschleife noch mehr zu machen, als > > nur den Eingang abzufragen ? Die Möglichkeit, dass in der Zeit wo ich was anderes mache, ein Ereignis an dem Eingang auftreten kann das ich dann nicht mitbekomme.
Man kann den Eingang auch mehrfach innerhalb der Schleife abfragen. Aber irgendwann wirds unhandlich, stimmt, dann ist ein Interrupt besser. Bis dahin gehts aber auch ohne ;-)
doc schrieb:
> Bis dahin gehts aber auch ohne ;-)
Es geht immer ohne, man muss sich nur des Risikos bewußt sein ;)
... schrieb: > doc schrieb: >> Und was hindert dich, in der Pollingschleife noch mehr zu machen, als >> >> nur den Eingang abzufragen ? > > Die Möglichkeit, dass in der Zeit wo ich was anderes mache, ein Ereignis > an dem Eingang auftreten kann das ich dann nicht mitbekomme. Kommt drauf an, was sonst noch so alles passieren soll. So wie ich das sehe, muss er sich nicht aktiv um die Anzeige kümmern. D.h. die Pollschleife ist im wesentlichen
1 | // alles auf Urzustand
|
2 | for( i = 0; i < 8; ++i ) |
3 | Einlauf[i] = 0; |
4 | Counted = 0; |
5 | |
6 | alterWert = 0; |
7 | |
8 | // und los gehts
|
9 | while( alterWert != 0xFF ) { // oder sonst irgendein Kriterium, das mir |
10 | // sagt, dass jetzt alles vorbei ist
|
11 | |
12 | neuerWert = PINB; // wenn dort alle 8 Eingänge der Lichtschranke hängen |
13 | changed = ( neuerWert ^ alterWert ); |
14 | if( changed ) { |
15 | // welches Bit ist in Changed gesetzt, das sagt mir, wer seine
|
16 | // Lichtschranke ausgelöst hat
|
17 | // Behandeln, indem zb die Bit-Nummer in Einlaufarray vermerkt wird
|
18 | mask = 0x01; |
19 | for( i = 0; i < 8; ++i ) { |
20 | if( ( changed & mask ) && ( neuerWert & mask ) ) { |
21 | // TODO: die Nummer 'Counter' zum Kontroller i schicken
|
22 | Einlauf[Counted++] = i; |
23 | }
|
24 | mask <<= 1; |
25 | }
|
26 | alterWert = neuerWert; |
27 | }
|
28 | }
|
Das erzeugt im Array Einlauf die (fast) richtige Einlaufreihenfolge. 'Fast' deswegen, weil bei 'zeitgleichen' Einläufen die Lichtschranke mit der kleineren Nummer den Vorzug bekommt, auch wenn beide registriert werden. Bei den Zeitvorgaben, die er hat, ist das denke ich mal schnell genug. Die Nummer mit dem Versenden der Einlaufnummer an den jeweiligen Kontroller könnte allerdings etwas Zeit verschlucken. Das müsste man jetzt durchrechnen, ob sich das ausgeht, dass in der Zeit nicht ein Einlauf unentdeckt bleibt.
Noch mal ein paar Basics: Ob die Anzeige jetzt tatsächlich in oder an den Regler kommt, steht noch nicht fest. Es würde aber dann wohl ein eigenes Kabel genutzt, da man ja nicht extra den Regler umbauen will, wenn man die Anzeige nutzen will. Die Anzeige würde wohl eher an die Regler "angesteckt" da die Fahrer ja in der Regel alle eigene Regler nutzen. Im ersten Schritt werden die Anzeigen vermutlich "nur" in direkter Nähe zum Fahrerstand sein. Die Daten sollen nicht an einen PC weitergegeben werden. Es geht gerade darum unabhängig von einem PC zu sein. Zu Euren Ausführungen: > Zum erkennen ob eine Lichtschranke ausgelöst hat genügt wenn man alle > verodert im einfachsten Fall über ein Diodenarray. Den veroderten Wert > dann an den externen Interrupt und im Interrupt alle 8 > Lichtschrankenstati solange auslesen bis alle wieder auf nicht mehr > unterbrochen sind. Genau das war mein ursprünglicher Plan. Für jede Unterbrechung einer Lichtschranke wird dann ein Rundenzähler für diese Lichtschranke inkrementiert. Bei gleicher Rundenzahl muss ich aber noch wissen, wer zuerst durch die Lichtschranke durchgefahren ist. Wie würdet Ihr Euch das merken? Timer starten und den Timer speichern? Bei der Auswertung würde man dann erst die Rundenzähler auswerten und nur bei Gleichstand auch den Timer. > Da eine Lichtschranke im Slot rel. empfindlich für ne > Fehlmessung ist kann das ins Auge gehen. Lichtschranken in Slots sind in dem Bereich der absolute Standard und ausgereift. Da würde ich einfach auf vorhandene Technik zurückgreifen. Auf den Bahnen die ich kenne gibts da wegen der Lichtschranken die wenigsten Probleme. Martin
Karl heinz Buchegger schrieb: > Die Nummer mit dem Versenden der Einlaufnummer an den jeweiligen > > Kontroller könnte allerdings etwas Zeit verschlucken. Das kann er ja machen wenn alle Bits gesetzt sind, d.h. wenn alle im Ziel angekommen sind. Kleine Zeitschleife davor und alle warten gespannt auf das Ergebniss ;)
@Karl heinz Buchegger: Wenn ich deinen Code richtig lese, dann funktioniert das nur dann, wenn alle Wagen in der gleichen Runde sind. Sobald ein Wagen den letzten Wagen überrundet steht er an der falschen Position im Array.
Martin Brehme schrieb: > Genau das war mein ursprünglicher Plan. Für jede Unterbrechung einer > Lichtschranke wird dann ein Rundenzähler für diese Lichtschranke > inkrementiert. Bei gleicher Rundenzahl muss ich aber noch wissen, wer > zuerst durch die Lichtschranke durchgefahren ist. Wie würdet Ihr Euch > das merken? Timer starten und den Timer speichern? Bei der Auswertung > würde man dann erst die Rundenzähler auswerten und nur bei Gleichstand > auch den Timer. Ich würde mir was ähnliches ausdenken wie weiter oben: Gleich wenn die ISR aktiviert wird, wird die neue Platzierung erstellt. Wie ist das eigentlich: Gibt es bei solchen Rennen eine Rundenvorgabe oder wird da eine bestimmte Zeit gefahren und wer die meisten Runden fertig fährt gewinnt? Je nachdem würde ich mir eine andere Strategie ausdenken. Bei einer fixen Rundenzahl bietet sich zb an. Alle starten mit der Rundenzahl. Bei aktivierung seiner Lichtschranke wird die zugehörige Rundenzahl um 1 verringert. Ist die dann 0, dann ist er im Ziel und die Slotnummer wird im Einlaufarray eingetragen. Ob das dann über Polling oder Interrupt funktioniert, ist gleichgültig.
Martin Brehme schrieb: > @Karl heinz Buchegger: Wenn ich deinen Code richtig lese, dann > funktioniert das nur dann, wenn alle Wagen in der gleichen Runde sind. > Sobald ein Wagen den letzten Wagen überrundet steht er an der falschen > Position im Array. Ja. Daran hab ich nicht gedacht. Aber siehe Folgeposting. Das kann man leicht lösen, indem man die Runden mitzählt.
Möchtest du eigentlich auch zwischendurch die momenatenen Positionen wissen? Dann würde sich zb ein stabiles Sortieren anbieten. Bei 8 Teilnehmern ist das noch trivial. Am Anfang hast du ein Platzierungsarray in dem alle Teilnehmer mit ihren Slotnummern und ihrer Rundenzahl enthalten sind. Löst eine Lichtschranke aus, so wird der Eintrag dort anhand der Slotnummer gesucht und die entsprechende Rundenzahl erhöht bzw. erniedrigt. Dann wird der Eintrag nach vorne verschoben, solange die Rundenzahl größer (kleiner) ist, als mit einem anderen Eintrag (oder man ganz vorne im Array angelangt ist :-) Macht man das konsequent, so liegt in diesem Array ständig die aktuelle Reihung vor und natürlich auch das Endergebnis bei Rennende.
Ich würde mit einem Abfragetakt von etwa 100µs, getriggert durch einen Timer-Interrupt, alle 8 Lichtschrankensignale (das ist gerade eine Port-Breite) als ein Byte einlesen und mit dem zuletzt gelesenen Byte per XOR-Verknüpfung vergleichen. Ist das Ergebnis 0, ist nichts weiter zu tun. Ist es von 0 verschieden, wird überprüft, welche Bits sich von 0 nach 1 geändert haben. Für die zugehörigen Fahrspuren wird der Runden- zähler weitergezählt und die Zeit abgespeichert. Am Schluss hast du für jedes Auto die Gesamtzeit und alle Rundenzeiten. Das Abfragen und Vergleichen im Interrupt kostet nur wenige Taktzyklen, lassen wir es, pessimistisch geschätzt, 30 sein. Wird eine Lichtschranke unterbrochen, wird etwas mehr gerechnet, aber das passiert ja nur selten und fällt rechenzeitmäßig kaum ins Gewicht. Bei einem CPU-Takt von 16MHz entsprechen die o.g. 100µs 1600 Zyklen. Davon werden durch die Lichtschrankenauswertung 30 Zyklen verbraucht, also weniger als 2%. Die restlichen 98% stehen für das Lösen teuflisch schwieriger quadratischer Gleichungen zur Verfügung :) Die damit erreichbare 100µs Zeitauflösung entspricht einer Wegauflösung von 1mm, was nach deiner Aussage weiter oben ja locker ausreichen sollte. Wenn deine Lichtschranken präzise genug sind, kannst du den Abfragetakt auch noch schneller machen. Mit 8 Pin-Change-Interrupts geht es natürlich ebenso, wenn der Control- ler über solche verfügt. Es gibt noch viele andere Möglichkeiten, die Aufgabe zu lösen, was zeigt, dass diese zu leicht ist, um noch lange darüber zu diskutieren. Fang mit der Arbeit einfach an und hab Spaß :)
> Wie ist das eigentlich: > Gibt es bei solchen Rennen eine Rundenvorgabe oder wird da eine > bestimmte Zeit gefahren und wer die meisten Runden fertig fährt gewinnt? Es gibt beides. Gängig ist aber eigentlich ein Rennen mit fest vorgegebener Zeit.
Karl heinz Buchegger schrieb: > Möchtest du eigentlich auch zwischendurch die momenatenen Positionen > wissen? Dann würde sich zb ein stabiles Sortieren anbieten. Bei 8 > Teilnehmern ist das noch trivial. Ja, hatte ich vergessen. Es geht um die aktuelle Plazierung WÄHREND des Rennens!
yalu schrieb: > Es gibt noch viele andere Möglichkeiten, die > Aufgabe zu lösen, was zeigt, dass diese zu leicht ist, um noch lange > darüber zu diskutieren. Fang mit der Arbeit einfach an und hab Spaß :) LOL - schließ nicht von dir auf meine Wenigkeit. Für mich ist das schon eine Herausforderung. Aber du hast recht ... learning by doing. Das Projekt ist - aufgrund seiner Einfachheit - vielleicht aber besonders geeignet für mich um einen Einstig in die µController zu finden.
Karl heinz Buchegger schrieb: > Am Anfang hast du ein Platzierungsarray in dem alle Teilnehmer mit ihren > Slotnummern und ihrer Rundenzahl enthalten sind. In Code skizziert
1 | struct Rank { |
2 | uint8_t Slot; |
3 | uint8_t Rounds; |
4 | };
|
5 | |
6 | struct Rank Ranking[8]; |
7 | |
8 | void StartRace() |
9 | {
|
10 | for( i = 0; i < 8; ++i ) { |
11 | Ranking[i] = i; // slots werden bei 0 beginnend gezählt |
12 | Rounds[i] = 0; // alle stehen am Start |
13 | }
|
14 | }
|
15 | |
16 | void PassedBy( uint8_t slotNr ) // am Slot slotNr wurde eine Durchfahrt |
17 | // registriert
|
18 | {
|
19 | for( i = 0; i < 8; ++i ) { |
20 | if( Ranking[i].Slot == slotNr ) { // da ist er ja |
21 | Ranking[i].Rounds++; // er hat jetzt 1 Runde mehr fertig |
22 | // die Reihung entsprechend umstellen
|
23 | j = i - 1; |
24 | while( j > 0 && Ranking[j].Rounds < Ranking[i].Rounds ) { |
25 | tmp = Ranking[i]; |
26 | Ranking[i] = Ranking[j]; |
27 | Ranking[j] = tmp; |
28 | i--; |
29 | j--; |
30 | }
|
31 | |
32 | // ev. Anzeigetafel aktualisieren. Das Ranking ist wieder aktuell
|
33 | // Erster im Rennen ist Ranking[0].Slot
|
34 | // Zweiter im Rennen ist Ranking[1].Slot
|
35 | // Dritter ist Ranking[2].Slot
|
36 | // etc.
|
37 | return
|
38 | }
|
39 | }
|
40 | }
|
Ich hab das jetzt schnell runtergeschrieben. Da werden sicher noch kleiner Fehler sein, aber das Prinzip sollte hinkommen (und Datentypen darfst du dir selbst ausdenken :-) Das läuft dann so Am Anfang ist die Situation die (die erste Zahl ist die Slotnummer, die zweite Zahl die Rundennummer) 0/0 1/0 2/0 3/0 4/0 5/0 6/0 7/0 8/0 jetzt wird bei Slot 3 ausgelöst. Der Eintrag mit der Slotnummer 3 wird gesucht und seine Rundenzahl erhöht 0/0 1/0 2/0 3/1 4/0 5/0 6/0 7/0 8/0 und anschliessend wird der Eintrag solange nach links verschoben, wie seine Rundenzahl größer ist als aller seiner linken Nachbarn 3/1 0/0 1/0 2/0 4/0 5/0 6/0 7/0 8/0 Das heisst also: momentan liegt die Slotnummer 3 vorne und ist erster Jetzt löst Slot 6 aus. Wieder: suchen und erhöhen 3/1 0/0 1/0 2/0 4/0 5/0 6/1 7/0 8/0 und nach links verschieben, solange der linke Nachbar eine kleinere Rundenzahl aufweist 3/1 6/1 0/0 1/0 2/0 4/0 5/0 7/0 8/0 Aha. 3 ist erster, 6 ist zweiter. Alle anderen dahinter Auf Slot 1 wird ein Durchgang registriert 3/1 6/1 1/1 0/0 2/0 4/0 5/0 7/0 8/0 Slot 3 war weit vorne, hatte aber einen Unfall. Slot 6 kommt als nächster bei Start/Ziel vorbei (bei 6 eine Runde raufzählen und nach links verschieben, weil seine Rundenzahl höher ist als die seines linken Nachbars) 6/2 3/1 1/1 0/0 2/0 4/0 5/0 7/0 8/0 1 kommt durchs Ziel 6/2 1/2 3/1 0/0 2/0 4/0 5/0 7/0 8/0 3 hat sich erfangen und kommt auch durch 6/2 1/2 3/2 0/0 2/0 4/0 5/0 7/0 8/0 Auch 4 hat sich nach einem Unfall nach dem Start gefangen und kommt jetzt erstmals durchs Ziel 6/2 1/2 3/2 4/1 0/0 2/0 5/0 7/0 8/0 (Beim linksschieben ist er über die '3' nicht drübergeschoben worden, weil ja '3' mehr Runden aufweist als '4') Jetzt haben 6, 1 und 3 einen Unfall und 4 holt eine Runde auf 6/2 1/2 3/2 4/2 0/0 2/0 5/0 7/0 8/0 6, 1, und 3 sind immer noch auf der Bahn, aber 4 holt eine weitere Runde auf ... 4/3 6/2 1/2 3/2 0/0 2/0 5/0 7/0 8/0 ... und ist plötzlich erster, weil er die meisten Runden hat etc. Das Array enthält zu jedem Zeitpunkt die aktuellen Platzierungen :-)
Schöne Erklärung! Zur Einweihung kommst du vorbei? Wenn du keinen Bock aufs fahren hast, darfst du auf jeden Fall die Rennen kommentieren. :-) Ich schau mir das alles heute Abend in Ruhe noch mal an ...
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.