Ich stehe gerade auf dem Schlauch und bitte um einen Vorschlag. Vermutlich ist es trivial. Ein AVR wertet zwei Pins aus und soll sie nach vier Zustandsänderungen auf zwei Möglichkeiten überprüfen: Möglichkeit 1: PIN 1 PIN 2 1 1 1 0 0 1 1 1 Möglichkeit 1: PIN 1 PIN 2 1 1 0 1 1 0 1 1 Wie kann ich das prüfen?
Jasper schrieb: > Wie kann ich das prüfen? Bist du sicher, dass deine Zustände sich wie in deinen Tabellen angegeben ändern? Irgendwie sollte bei 2 Bits und 4 Zuständen auch der Zustand 0 0 auftreten. Außerdem sollte die Zustandsfolge einem Gray-Code entsprechen. Sonst hast du störende Zwischenzustände. Algorithmen zur Encoderauswertung mit AB-Signalen gäbe es dann genug.
Jasper schrieb: > Ich stehe gerade auf dem Schlauch und bitte um einen Vorschlag. > Vermutlich ist es trivial. > > Ein AVR wertet zwei Pins aus und soll sie nach vier Zustandsänderungen > auf zwei Möglichkeiten überprüfen: > > Möglichkeit 1: > PIN 1 PIN 2 > > 1 1 > 1 0 > 0 1 > 1 1 > > > > Möglichkeit 1: > PIN 1 PIN 2 > > 1 1 > 0 1 > 1 0 > 1 1 > > Wie kann ich das prüfen? Schiebe die 2 Bits einfach nacheinander in ein 8-Bit Register und vergleiche dann den Wert als Unsigned Int. 1: 11 10 01 11 = 0xE7 = 231 2: 11 01 10 11 = 0xDB = 219
Miramare schrieb: > Schiebe die 2 Bits einfach nacheinander in ein 8-Bit Register und > vergleiche dann den Wert als Unsigned Int. > > 1: 11 10 01 11 = 0xE7 = 231 > 2: 11 01 10 11 = 0xDB = 219 damit weiss er vllt 30% dessen was er wissen muss solltest ihm vllt noch den Rest offenbaren
Jasper schrieb: > soll sie nach vier Zustandsänderungen > auf zwei Möglichkeiten überprüfen: Das bis 4 Zählen hat schwerwiegende Nachteile. Der Drehgeber darf nicht prellen und der Benutzer muß immer schön brav von Rastpunkt zu Rastpunkt drehen. Übliche Drehgeberroutinen werten daher nicht die Anzahl der Änderungen, sondern die Zustände selber aus. Ein Prellen wird damit sofort wieder abgezogen bzw. ein Richtungswechsel ist an beliebigen Positionen erlaubt.
Jasper schrieb: > Ich stehe gerade auf dem Schlauch und bitte um einen Vorschlag. > Vermutlich ist es trivial. > > Ein AVR wertet zwei Pins aus und soll sie nach vier Zustandsänderungen > auf zwei Möglichkeiten überprüfen: > > Möglichkeit 1: > PIN 1 PIN 2 > > 1 1 > 1 0 > 0 1 > 1 1 > > Möglichkeit 1: > PIN 1 PIN 2 > > 1 1 > 0 1 > 1 0 > 1 1 > > Wie kann ich das prüfen? Nimm 2 Positionsvariablen die bei 0 starten wenn die aktuelle Kombination mit der für die beiden Möglichkeiten übereinstimmt dann inkrementiere die Positionsvariable hat sie den Wert 4 erreicht dann hast du einen Treffer gefunden wenn die aktuelle Kombination nicht übereinstimmt dann setze die Positionsvariable zurück auf 0. Peter D. schrieb: > Das bis 4 Zählen hat schwerwiegende Nachteile. Der Drehgeber darf nicht > prellen und der Benutzer muß immer schön brav von Rastpunkt zu Rastpunkt > drehen. > Übliche Drehgeberroutinen werten daher nicht die Anzahl der Änderungen, > sondern die Zustände selber aus. Ein Prellen wird damit sofort wieder > abgezogen bzw. ein Richtungswechsel ist an beliebigen Positionen > erlaubt. Prellen musst du natürlich vorher schon entsprechend vermeiden!
Jasper schrieb: > Ein AVR wertet zwei Pins aus und soll sie nach vier Zustandsänderungen > auf zwei Möglichkeiten überprüfen Warum musst du da auf 4 Zustandsänderungen warten (wobei sowieso nur 3 Änderungen zwischen diesen 4 Zuständen sind...) Jasper schrieb: > Wie kann ich das prüfen? Was soll passieren, wenn ein anderes Bitmuster hereinkommt? Oder wenn der Wechsel von 01 oder 10 über 00 bzw 11 geht (das tut er für ein paar ns sicher, denn diese beiden Signale kommen garantiert nicht gleichzeitig an den AVR-Pins an). Also müssen dei Eingangssignale erst mal konditioniert (aka entprellt) werden. Danach kommt die Erkennung, ob sich was geändert hat, dann kommt die FSM, die abhängig von der Änderung weiterschaltet. BTW: musst du da unbedingt alle 3 Zustandswechsel abwarten? Wenn nicht, dann wäre das Programm recht einfach. Kommend von 11 müsstest du nur jeweils abfragen, ob eines der beiden Bits auf 0 geht, und dann wieder warten, bis beide (entprellten) Eingänge 11 sind. Wie schnell wechseln da eigentlich die Zustände?
:
Bearbeitet durch Moderator
Hallo Jasper, hier mal ein Beispiel wie das mit Arduino IDE aussehen könnte. Gibt natürlich noch 100 andere Möglichkeiten. --------------------------------------------------------------- // statt bin 6,7 kann auch jeder andere Pin (D3-D13) gewählt werden. #define PIN1 6 #define PIN2 7 int entprell_zeit = 100; long millis_alt = 0; void setup() { pinMode(PIN1, INPUT); pinMode(PIN2, INPUT); } void loop() { // Checkt alle 100ms die Eingänge und schaltet entsprechend if(millis() - millis_alt >= entprell_zeit){ millis_alt += entprell_zeit; int status_pin1 = digitalRead(PIN1); int status_pin2 = digitalRead(PIN2); if(status_pin1 == 0 && status_pin2 == 0){ // was auch immer er machen soll } else if(status_pin1 == 1 && status_pin2 == 0){ // was auch immer er machen soll } else if(status_pin1 == 0 && status_pin2 == 1){ // was auch imemr er machen soll } else if(status_pin1 == 1 && status_pin2 == 1){ // was auch immer er machen soll } } // Hier kann noch anderer Code stehen } ---------------------------------------------- p.s Ja ich weiß die Leute hier sollen selber denken, aber das hat gerade mal eine Minute gedauert es runter zu schreiben ;) Gruß
Ich hatte da was von Entprellen geschrieben. Das war ernst gemeint. Denn wenn die Eingänge nicht absolut zeitgleich wechseln (und das tun sie nicht!), dann geht das simple direkte Abfragen früher oder später schief. Nach Murphy wird das Problem laufend auftreten...
Beitrag #5908221 wurde von einem Moderator gelöscht.
Und nochmal schrieb im Beitrag #5908221: > Wo war von einem Drehgeber die Rede? Keine Ahnung. Ich habe nichts derartiges ins Gespräch gebracht. > Wo war von Prellen die Rede? Es ist die Rede von asynchronen Eingängen eines uC , die gemeinsam abgefragt werden sollen, als ob sie gleichzeitig den Pegel zum jeweils anderen Potential wechseln würden. Das tun sie nicht. Ein Übergang von 01 nach 10 geht zwangsläufig für ein paar ns über 00 oder 11. Immer. Und wenn gerade dann die Eingänge eingelesen werden, dann... ja, was dann? Und mit "Entprellen" ist hier gemeint, dass mindestens 2 Abfragen hintereinander an beiden Pins zusammen das selbe Bitmuster anliegen muss. Damit wird das oben beschriebene Problem behoben. Den Rest des Posts lasse ich besser mal unkommentiert...
:
Bearbeitet durch Moderator
Lothar M. schrieb: > Ein Übergang von > 01 nach 10 geht zwangsläufig für ein paar ns über 00 oder 11. Immer. Nicht wenn ich (oder besser, Jasper, der TO ;-)) die beide Pins nur jede 10ms pollt. Aber auch dann kann es natürlich passieren, dass der Weg von 01 zu 10 nicht über Los geht.
Eric B. schrieb: > Nicht wenn ich (oder besser, Jasper, der TO ;-)) die beide Pins nur jede > 10ms pollt Wahrscheinlich... ? Wenn alle 10ms gepollt wird und die undefinierte Transision 10ns dauert, dann geht rechnerisch 1 von 1 Million Abfragen schief. Wenn Murphy mitmacht, dann passiert das immer Donnerstags nach der Frühstückspause. Aber garantiert nicht dann, wenn man gerade den Fehler sucht. Deshalb verhindert man so einen Fehler einfach, indem man die Wahrscheinlichkeit aus dem Spiel nimmt.
Lothar M. schrieb: > Deshalb verhindert man so einen Fehler einfach, indem man die > Wahrscheinlichkeit aus dem Spiel nimmt. Spitzen Idee Das würde viele Probleme lösen Sry
Ich würde es folgendermaßen machen: Falls ich irgendwas periodisch abfragen wollen würde, stünde in der init:
1 | #define MUSTER_A 0b11100111
|
2 | #define MUSTER_B 0b11011011
|
3 | ...
|
4 | unsigned char input_folge = 0, matched_muster = 0; |
5 | unsigned char *input_pointer = &input_folge; |
In der loop:
1 | if (timer_10ms_flag) |
2 | matched_muster = ExamineInputs(input_pointer); |
und die Funktion ExamineInputs sähe so aus:
1 | unsigned char ExamineInputs (unsigned char *input_pointer) { |
2 | *input_pointer = ((PORTB&(1<<PB3))&(*input_pointer)>>1); |
3 | *input_pointer = ((PORTB&(1<<PB7))&(*input_pointer)>>1); |
4 | if (((*input_pointer) == MUSTER_A)||((*input_pointer) == MUSTER_B)) |
5 | return 1; |
6 | else
|
7 | return 0; |
wobei hier exemplarisch PORTB und Pins PB3 und PB7 gewählt wurden. Es lässt sich beliebig verkomplizieren oder auch etwas leichter machen, wenn man die Variable input_folge als global deklariert - dann müsste man nicht mit Pointern rumwerfen und das Programm wäre noch übersichtlicher.
Viktor B. schrieb: > Ich würde es folgendermaßen machen Das funktioniert aber bestenfalls mur genau dann, wenn die Eingänge den Pegel immer zuverlässig mitten in dem 10ms Raster wechseln. Mal angenommen, der zeitliche Abstand zwischen 2 Zustandsänderungen schwankt beliebig zwischen 5 und 50ms. Oder zwischen 2 und 200ms. Oder zwischen 9 und 11ms. Was dann? Oder schlimmer noch: die Eingänge ändern sich mit exakt 10,1ms Abstand. Dann geht es 100 mal gut, aber dann rasselt es... Fazit: der Automat, der hier benötigt wird, hat prinzipiell keine zeitliche Abhängigkeit, sondern seine Reaktion hängt nur von Änderungen seiner Eingänge ab.
:
Bearbeitet durch Moderator
Entschuldigung für die später Rückmeldung. Ich versuche mal etwas Licht ins Dunkel zu bringen. Ich habe quasi einen optischen Drehgeber aus einer gelöcherten Holzscheibe gebaut (8 Löcher). Hier erfassen zwei Fototransistoren die Zustände. Eingentlich wollte ich diese per INT0 und INT1 am AVR auswerten. Dabei ist es dann zum angesprochenen Prellen gekommen. Ich hatte mir beholfen, indem ich die Fototransistoren einfach per ADC auswerte. Wert > 900: Highpegel, Wert < 900: Lowpegel Das funktioniet bisher ohne Probleme. Hier ein Auszug aus meinem Code:
1 | uint8_t s1_hilo=0, s2_hilo=0, s1_hilo_alt=0, s2_hilo_alt=0; |
2 | uint8_t shiftregister=0; |
3 | uint8_t rechtslauf = 30; //(00011110) |
4 | uint8_t linkslauf = 45; //(00101101) |
5 | |
6 | if ((s1_hilo != s1_hilo_alt) || (s2_hilo != s2_hilo_alt)) |
7 | {
|
8 | shiftregister = (shiftregister<<1) | s1_hilo; |
9 | s1_hilo_alt=s1_hilo; |
10 | shiftregister = (shiftregister<<1) | s2_hilo; |
11 | s2_hilo_alt=s2_hilo; |
12 | }
|
13 | |
14 | if (shiftregister==rechtslauf) |
15 | {
|
16 | rechtsschritt++; |
17 | if (linksschritt != 0) |
18 | {
|
19 | linksschritt--; |
20 | }
|
21 | shiftregister=0; |
22 | }
|
23 | |
24 | if (shiftregister==linkslauf) |
25 | {
|
26 | linksschritt++; |
27 | if (rechtsschritt != 0) |
28 | {
|
29 | rechtsschritt--; |
30 | }
|
31 | shiftregister=0; |
32 | }
|
Lothar M. schrieb: > seine Reaktion hängt nur von Änderungen > seiner Eingänge ab. Dann würde man das mit Pin change Interrupts machen und hätte das Problem, dass die Pins zwichen dem Zustand 1,0 und 0,1 kurz durch 1,1 oder 0,0 gehen. Vielleicht würde es besser gehen, wenn man jede 1 ms sampelt und dann unterscheidet, ob sich die Eingänge geändert haben oder nicht. Ist aber ziemlich viel Overhead. Upd.: Wie ich sehe, hat der TO schon ein funktionierendes Programm. Dann lohnt es sich ja nicht wirklich, mein Beispiel zu aktualisieren
Naja, mein Programm ist aus meiner Unwissenheit entstanden. Bisher läuft es aber ich lasse mir gerne erklären wie man es besser macht. Hatte nur gelesen das Fototransistoren relativ träge sind. Von daher dachte ich das somit vielleicht ein mögliches Prellen gar nicht erfasst wird weil die Dinger zu langsam reagieren und ich dann mit ADC-Werten > 900 im sicheren Bereich lande.
Jasper schrieb: > Von daher dachte ich Ich würde das mit.einem Oszilloskop messen. Soooo arg teuer sind die Dinger gar nicht... ? Denn eigentlich kannst du nur etwas das du kennst, wirklich zuverlässig auswerten. Jasper schrieb: > Das funktioniet bisher ohne Probleme. Ist ja auch kein Wunder. Das ist ja ganz im Gegensatz zu der "war nur exemplarisch gemeint"en Frage aus dem Eröffnungspost ein Gray-Code, bei dem "aus Gründe" eben niemals 2 Bits gleichzeitig wechseln. Und deshalb die ganzen Probleme mit dem Übergang von 01 nach 10 (oder 10 nach 01) niemals auftreten können.
:
Bearbeitet durch Moderator
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.