Forum: Mikrocontroller und Digitale Elektronik Bitmuster erkennen und vergleichen


von Jasper (Gast)


Lesenswert?

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?

von Wolfgang (Gast)


Lesenswert?

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.

von Jasper (Gast)


Lesenswert?

War nur exemplarisch gemeint.

von Miramare (Gast)


Lesenswert?

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

von Miramare (Gast)


Lesenswert?

Ich meinte natürlich vergleiche mit "unsigned char".

von H. D. (c3po)


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

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.

von H. D. (c3po)


Lesenswert?

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!

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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
von mmmmmm (Gast)


Lesenswert?

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ß

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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.
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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
von Eric B. (beric)


Lesenswert?

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.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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.

von C3po (Gast)


Lesenswert?

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

von Viktor B. (coldlogic)


Lesenswert?

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.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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
von Jasper (Gast)


Lesenswert?

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
    }

von Viktor B. (coldlogic)


Lesenswert?

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

von Jasper (Gast)


Lesenswert?

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.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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
Noch kein Account? Hier anmelden.