[erledigt] Flankenerkennung: Wie?

Hallo allerseits!

Ich möchte die beiden Räder meines Langzeitgebastels synchronisieren. Hierfür habe ich mir Kodierscheiben gebastelt, an den Rädern befestigt und einen CNY70 (IR-Reflextaster) zum „Lesen“ der Kodierscheiben drangebaut. Was die CNY70 liefern, habe ich mit GNUplot zu dem hier gemacht. Da ist zu sehen, dass man die Hell-/Dunkel-Wechsel zwar klar identifizieren kann, aber ich weiß nicht, mit welchen mathematischen Hilfsmitteln ich eine Flankenerkennung hinbekomme. Einfach einen festen Wert als „Grenze“ zwischen hell und dunkel zu benutzen, würde bei Kurve A noch hinkommen (ungefähr 480), aber bei Kurve B geht das nicht.

Nunja, also ... wie kann ich diese Kurven bzw. Folgen von Einzelwerten so behandeln, dass eine zuverlässige Flankenerkennung entsteht? Ich bin mir zwar sicher, dass das mit Mitteln der Statistik funktioniert, aber das Thema hatten wir damals nicht, als ich zur Schule ging.

Vielen Dank vorweg!

Gregor

Du könntest Versuchen:
Die Farbe der Räder zu ändern damit Du eine bessere reflektion zusammenbekommst.
Den Widerstand des Empfängers ändern damit Du mehr signal bekommst
Den Sensor gegen Licht abzuschirmen.
Grüße Uwe

uwefed:
Du könntest Versuchen:
Die Farbe der Räder zu ändern damit Du eine bessere reflektion zusammenbekommst.
Den Widerstand des Empfängers ändern damit Du mehr signal bekommst
Den Sensor gegen Licht abzuschirmen.

Das mit der Farbe ist schwierig. Mein Laserdrucker kann nur schwarz. Das mit der Abschirmung gegen Streulicht ist wohl gut gelungen. Die Kurven bei Tageslicht sehen quasi so aus wie die bei Nacht. Da sind kaum Unterschiede drin.

Ich denke auch nicht, dass ich damit erreiche, was ich möchte, denn die Hell-/Dunkel-Erkennung funktioniert ja. Ich weiß nur nicht, wie ich da ein „true“ oder „false“ draus machen kann.

Gruß

Gregor

Nachtrag:
Hier mal ein kurzer Ausschnitt einer Aufzeichnung (das sind je Zeile millis(), analogRead(A) und analogRead(B))

5050, 561, 592
5060, 507, 599
5060, 501, 600
5070, 435, 594
5070, 428, 592
5080, 359, 575
5080, 354, 573
5090, 325, 548
5090, 325, 546
5100, 357, 521
5100, 363, 519
5110, 433, 505
5110, 440, 504
5120, 510, 508

Hallo,

wie sehen denn deine Scheiben aus? Und wofür sind die gedacht?
Im Moment denke ich da an Scheiben mit versetzten schwarz/weiß Muster. Das liefe dann auf den Graycode hinaus.

analogRead liefert Werte größer 1023?
Du mußt Schwellwerte einstellen. < X gleich LOW und > X gleich High

Hmmm, beim Betrachten der Diagramme kamen mir ein paar Erinnerungen aus dem Amateurfunk in den Sinn, hier spezell das Thema "Funkfernschreiben / RTTY". Damals habe ich auch via OP-Amps mit Begrenzern, Filter und ähnlichen Dingen gebastelt, damit aus dem Wellensalat eindeutige und lesbare Signale gefiltert werden konnten. Vielleicht ist meine Idee Bullshit, aber so rein spontan würde ich zunächst versuchen, das Signal zu glätten und anschließend über einen Schmitt-Trigger zu schicken. Daraus könnte man theoretisch eindeutige 1/0-Signale ableiten. Wie / ob sich das mit reiner Software lösen lässt entzieht sich meiner Kenntnis :confused:

Doc_Arduino:
wie sehen denn deine Scheiben aus? Und wofür sind die gedacht?
Im Moment denke ich da an Scheiben mit versetzten schwarz/weiß Muster. Das liefe dann auf den Graycode hinaus.

Die Scheiben sind auf starkes Papier gedruckte „Siemenssterne“ (PDF). Die starken Schwankungen, die die Kurven zeigen sind auf gewellte Scheiben zurückzuführen.

Doc_Arduino:
analogRead liefert Werte größer 1023?

Da musst Du Dich verguckt haben.

Doc_Arduino:
Du mußt Schwellwerte einstellen. < X gleich LOW und > X gleich High

Das funktioniert zwar für Kurve A, aber keinesfalls für Kurve B.

Eine Flankenerkennung hätte den großen Vorteil, dass nicht so akurate Kurven trotzdem zuverlässig ausgewertet werden würden. Wenn sich mal die Lichtverhältnisse ändern (Tag/Nacht, dran gebastelt, ...) würde sich das nicht negativ auswirken.

Eine Überlegung ist, eine Art „Fifo“-Container zu programmieren, der ständig mit aktuellen Werten beliefert wird (der älteste Wert fliegt jeweils raus) und eine Methode/Funktion, die mir true oder false liefert (Flanke erkannt oder nicht erkannt).

Dass ich damit zum Ziel käme, da bin ich mir sicher. Ich möchte nur erstens das Rad nicht neu erfinden und zweitens etwas über derlei Rechnerei lernen.

Gruß

Gregor

RudiDL5:
... via OP-Amps mit Begrenzern, Filter und ähnlichen Dingen gebastelt, damit aus dem Wellensalat eindeutige und lesbare Signale gefiltert werden konnten.

Operationsverstärker kamen mir auch schon in den Sinn. Oder die Frage, ob man das mit elektronischen Mitteln erreichen kann, was ich möchte. Blöd ist, dass ich mich in Sachen Elektronik nicht sonderlich auskenne (mit OPs hatte ich noch nie zu tun) und die Elektronik nicht geändert werden kann ohne einen H-e-i-d-e-n-a-u-f-w-a-n-d zu veranstalten (Platz).

RudiDL5:
Vielleicht ist meine Idee Bullshit, aber so rein spontan würde ich zunächst versuchen, das Signal zu glätten und anschließend über einen Schmitt-Trigger zu schicken. Daraus könnte man theoretisch eindeutige 1/0-Signale ableiten. Wie / ob sich das mit reiner Software lösen lässt entzieht sich meiner Kenntnis :confused:

Nee, die Idee ist gut! (IMO :slight_smile:

Das Signal ist eigentlich in Ordnung, mir fehlen nur die (programmier-) Mittel bzw. die Kenntnisse dazu, das in C/C++ zu lösen.

Gruß

Gregor

*nachdenk... Ich schätze mal, dass dein Gedanke mit dem FiFo dann eigentlich der einzige Weg sein kann. In beiden Diagrammen sind deutliche Schwankungen erkennbar. Vielleicht bietet sich hier an, aus einer Meßreihe bestimmter Länge einen Mittelwert zu errechnen. Ist der Mittelwert deutlich größer als der Grenzwert (Hysterese-Schwelle), dann gibt's 'ne "Null", andernfalls 'ne "Eins". Stichwort "Ringspeicher" oder so. Bei einem Wechsel von 0 auf 1 hätte man seine "Flanke". Kann aber auch sein dass ich vollkommen daneben liege, müsste man auf jeden Fall testen wie gut das funktioniert...

Hallo,

welche Kurve B? Mit dem Siemensstern wie in dem .pdf hast du nur eine einzige Kurve?
Was möchtest du denn mit dem Signal auswerten? Drehzahl? Drehrichtung?

Doc_Arduino:
welche Kurve B? Mit dem Siemensstern wie in dem .pdf hast du nur eine einzige Kurve?
Was möchtest du denn mit dem Signal auswerten? Drehzahl? Drehrichtung?

Im PDF mit den Plots sind zwei Kurven drin. Erste Seite ist A, zweite Seite ist B. Mir ist erst heute aufgefallen, dass die Kurven einen stark unterschiedlichen Wertebereich für die Senkrechte haben. Nunja, ich sehe von links auch anders aus als von rechts :slight_smile:

Die Scheiben dienen lediglich dazu, „Schritte“ zu erfassen (und zu synchronisieren eben). Die Drehzahl ist mir wurscht und die Drehrichtung weiß ich, weil ich sie festlege.

Gruß

Gregor

Wenn man das Signal differenziert, bekommt man Wendestellen, die man auswerten kann. Also nicht den Absolutwert auswerten, sondern die Differenz zum Vorgängerwert. Wenn diese Differenz das Vorzeichen wechselt, dann merken.

Nur so eine Idee, mit der ich mal probieren würde. Läßt sich leicht per Programm realisieren.

agmue:
Wenn man das Signal differenziert, bekommt man Wendestellen, die man auswerten kann. Also nicht den Absolutwert auswerten, sondern die Differenz zum Vorgängerwert. Wenn diese Differenz das Vorzeichen wechselt, dann merken.
Nur so eine Idee, mit der ich mal probieren würde. Läßt sich leicht per Programm realisieren.

Wenn ich wüsste, wie man das Signal differenzieren könnte ...

Das mit der Differenz zweier Werte klappt nicht, weil es Messungen gibt, die leichte Schwankungen zeigen, die sich aber allesamt im „Plus-Bereich“ der Schwingung bewegen.

Wenn mir nichts Besseres einfällt, werde ich mal anfangen, einen Container zu programmieren. Blöd, dass es in Arduino-C keine STL gibt.

Gruß

Gregor

Ich würde das so versuchen:

uint16_t arrayA[] = {561, 507, 501, 435, 428, 359, 354, 325, 325, 357, 363, 433, 440, 510, 500, 435, 325, 376, 400, 510};
uint16_t arrayB[] = {592, 599, 600, 594, 592, 575, 573, 548, 546, 521, 519, 505, 504, 508, 578, 595, 603, 600, 587, 480};

uint16_t lastA = 0;
uint16_t lastB = 0;

void setup() {
  Serial.begin(9600);
  for (int i = 0; i < 20; i++) {
    uint16_t readValA = arrayA[i]; // soll das auslesen des Sensors A simulieren
    uint16_t readValB = arrayB[i]; // soll das auslesen des Sensors B simulieren
    Serial.print(i);
    if (readValA < lastA) {
      Serial.print(" A = LOW, ");
    }
    if (readValA >= lastA) {
      Serial.print(" A = HIGH, ");
    }
    if (readValB < lastB) {
      Serial.print(" B = LOW");
    }
    if (readValB >= lastB) {
      Serial.print(" B = HIGH");
    }
    lastA = readValA;
    lastB = readValB;
    Serial.println();
  }

}

void loop() {
  // put your main code here, to run repeatedly:
}

Hallo,

dachte ich mir schon fast. Eigentlich baust du dir einen Drehgeber. Um das wirklich optimal zu erfassen, braucht man pro Scheibe mindestens 2 Kurven. 2 reichen aber auch aus. Damit sind wir beim schon erwähnten Graycode. Diesen auswerten und du erhälst die Schritte. Dazu gäbe es die Richtungsanzeige noch gratis obendrauf. Auch wenn du diese nicht benötigst. Ist mit einfachen Mitteln sehr genau.

Sowas nur mit 2 Spuren.

Das hat Peter D. hier schön erklärt. Habe mich da auch vor kurzem durchgewurschelt bis ich verstanden habe wie er das macht mit seinen Kniffen. Jede Scheibe hat dann letztlich ihren Zähler, die kannste dann miteinander vergleichen.

http://www.mikrocontroller.net/articles/Drehgeber
http://www.mikrocontroller.net/topic/drehgeber-auslesen

An die Lichtschranken einen Schmittrigger und das saubere Digitalsignal geht zum µC.
Ansonsten mußte wie gesagt mit Hysterese und Schwellwert den eingelesenen analogen Wert umformen.

slartibartfast:
Ich würde das so versuchen:

Das gibt den Daumen nach oben!

Alternativ könnte man auch den schwankenden Mittelwert berechnen und den aktuellen Wert damit vergleichen. Letztlich mußt Du ausprobieren, was zu Deinen Scheiben am einfachsten und sichersten paßt.

Hallo,

der Code verhaspelt sich irgendwann. Weil keine eindeutige Erkennung möglich ist. Wenn zum Bsp. beide Scheiben/Sensoren um den hell-dunkel Wechsel rumeiern. Lest bitte das vom Peter durch und die andere Erklärung, dann wisst ihr warum, weshalb und wieso.

Doc_Arduino:
Drehgeber – Mikrocontroller.net
Drehgeber auslesen - Mikrocontroller.net

Super, danke!

Gruß

Gregor

Hallo,

Hartnäckigkeit andersherum zahlt sich manchmal auch aus. :slight_smile:

Also nochmal auf die Encoder zurückzukommen mir scheint daß die Breite der hell-dunklen Striche einfach zu fein sind für die Reflektionslichtschranke. Wenn der Durchmesser der Lichtschranke auf dem Rad größer ist als ein weißer oder schwarzer Balken dann hast Du einfach weniger Signal.

Hast Du es mit breiteren Streifen versucht?

Doc_Arduino:
Hartnäckigkeit andersherum zahlt sich manchmal auch aus. :slight_smile:

Du meinst Deine Geduld, stimmts :-)))

Mal sehen, was herauskommt, wenn ich das alles gelesen habe.

Meine Container-Idee ist übrigens etwas, das sich oberallerbestens als Beispiel für den Sinn von Klassen eignet. Vielleicht programmiere ich sowas trotzdem mal und gebe Bescheid.

Gruß

Gregor