Forum: Mikrocontroller und Digitale Elektronik arduino encoder problem


von Stephan R. (dacker01)


Lesenswert?

Hallo leute!
Ich habe an meinem arduino ein encoder an 2 digitale pins angeschlossen. 
Die gezählten impulse gebe ich über den seriellen monitor aus. Leider 
werden die impulse nicht richtig gezählt. Wo könnte der fehler liegen?

von Christian D. (chris83)


Lesenswert?

42

Oder Schaltplan und Code. Mit den Infos wird das nix.

von Ulrich F. (Gast)


Lesenswert?

Stephan R. schrieb:
> Wo könnte der fehler liegen?
Irgendwo bei dir zuhause!
;-)

Ich sehe ihn nicht.

von Dieter S. (Gast)


Lesenswert?

Stephan R. schrieb:
> Leider werden die impulse nicht richtig gezählt. Wo könnte der fehler liegen?

Kontaktprellen.

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


Lesenswert?

Stephan R. schrieb:
> Wo könnte der fehler liegen?
Mit an Wahrscheinlichkeit grenzender Sicherheit in der Software. Der uC 
selber ist nämlich schnell genug, um auch schnellste Encoder auswerten 
zu können. also lass doch mal deine Software sehen...

> ein encoder ... angeschlossen.
Welchen "Encoder"? Es gibt nicht nur einen einzigen...

> Leider werden die impulse nicht richtig gezählt.
Was erwartest du? Und was erhältst du stattdessen?

: Bearbeitet durch Moderator
von Stephan R. (dacker01)


Lesenswert?

Lothar M. schrieb:
> Mit an Wahrscheinlichkeit grenzender Sicherheit in der Software. Der uC
> selber ist nämlich schnell genug, um auch schnellste Encoder auswerten
> zu können. also lass doch mal deine Software sehen...
______________________________________________________________________ 
__

/* Encoder Library - Basic Example
 * http://www.pjrc.com/teensy/td_libs_Encoder.html
 *
 * This example code is in the public domain.
 */

#include <Encoder.h>

// Change these two numbers to the pins connected to your encoder.
//   Best Performance: both pins have interrupt capability
//   Good Performance: only the first pin has interrupt capability
//   Low Performance:  neither pin has interrupt capability
Encoder myEnc(10,11);
//   avoid using pins with LEDs attached

void setup() {
  Serial.begin(9600);
  Serial.println("Basic Encoder Test:");
}

long oldPosition  = -999;

void loop() {
  long newPosition = myEnc.read();
  if (newPosition != oldPosition) {
    oldPosition = newPosition;
    Serial.println(newPosition);
  }
}

von Wolfgang (Gast)


Lesenswert?

Dieter S. schrieb:
> Kontaktprellen.

Bei einem Encoder? Üblicherweise verwenden die einen 2 Bit Gray-Code. 
Das ist Kontraktprellen bei vernünftiger Auswertesoftware ziemlich 
schnuppe.

von Stephan R. (dacker01)


Angehängte Dateien:

Lesenswert?

Lothar M. schrieb:
>> Leider werden die impulse nicht richtig gezählt.
> Was erwartest du? Und was erhältst du stattdessen?

_______________________________________________________
Hallo Lothar M.
Wenn ich den Encoder z.B 2 Raster nach rechts drehe, erkennt er den Wert 
5.
Logischerweise sollte ich durch 2 Raster zurückdrehen wieder auf Null 
kommen.
Stattdessen kommt einmal 400, das nächste mal -20 usw. raus.
Zum Entprellen habe ich folgende Schaltung zusammengelötet. Hatte aber 
statt den 10 nF nur 100nF hier. Leider ergab dies keine Änderung

von Wolfgang (Gast)


Lesenswert?

Stephan R. schrieb:
> long newPosition = myEnc.read();

Und was steckt hinter der Methode?

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


Lesenswert?

Stephan R. schrieb:
> //   Best Performance: both pins have interrupt capability
> //   Good Performance: only the first pin has interrupt capability
> //   Low Performance:  neither pin has interrupt capability
Aua...

Stephan R. schrieb:
> Wenn ich den Encoder
Da war noch eine Frage offen:
>>> Welchen "Encoder"? Es gibt nicht nur einen einzigen...

> Zum Entprellen habe ich folgende Schaltung zusammengelötet.
Dreh mal den Encoder gaaaaaaaannnnnnzzzz 
lllllaaaaaaannnnggggssssaaaaammmm und miss die Spannung an den Pins. Was 
siehst du da? Wenn du gut bist kannst du sogar beide Pins messen und die 
"typische" Encoder-Wellenform finden:
1
E1   ...000001111111000000000111111110000000...
2
E2   ...001111111000000000111111110000000111...
Wenn nicht, dann solltest du da mal genauer kontrollieren...

: Bearbeitet durch Moderator
von Dieter S. (Gast)


Lesenswert?

Wolfgang schrieb:
> Dieter S. schrieb:
> Kontaktprellen.
>
> Bei einem Encoder? Üblicherweise verwenden die einen 2 Bit Gray-Code.
> Das ist Kontraktprellen bei vernünftiger Auswertesoftware ziemlich
> schnuppe.

Da ein nackter Encoder immer prellt, ich habe bisher keinen kennen 
gelernt, der nicht prellt und bis zu diesem Zeitpunkt der Code geheim 
gehalten wurde ist diese Vermutung sicher nicht so daneben. Wenn die 
Software das dann hergibt, ist ja alles gut.

von bianchifan (Gast)


Lesenswert?

Stephan R. schrieb:
> Wenn ich den Encoder z.B 2 Raster nach rechts drehe, erkennt er den Wert
> 5.

Ich spiele gerade mit einem WS2812-Ringlicht herum und einem ATTiny85 
herum.
Zum Antesten der Adafruit lib habe ich mir ebenfalls ein billige 
Chinadrehteil ins Steckbrett genagelt, schien mir einfacher als direkt 
mit zwei Tastern zu starten.
Ich hatte genau dasselbe Problem, allerding sprangden die Werte oftmals 
sogar um 4 Werte pro Rastposition weiter. Du darfst nicht vergessen, 
dass pro Rast durchaus mehrere Impulse erzeugt werden können, dazu kommt 
die wackelige Mechanik. Gelöst habe ich das ganz brutal mit einem Delay, 
das schluckt alles was da so kommt, im Endeffekt habe ich das erreicht, 
was ich wollte: 1 LED / Rast bei der Auswahl von Position und 
Streifenbreite.
Nicht sonderlich elegant, tut aba..

//ENCODER ROUTINES

void digitalReadEncoder(int &rotate, int& press)
{
  rotate = (digitalRead(PHASE_B) * 2) + digitalRead(PHASE_A);
  press = digitalRead(PRESS_BUTTON);
}

void readEncoder()

{
  int Position, Press;
  int Position2, Press2;

....

  digitalReadEncoder(Position, Press);
  do  {
    digitalReadEncoder(Position2, Press2);
  }
  while ((Position2 == Position) && (Press2 == Press));
  if (Position2 != Position) {
    delay (50);                                     // longer wait for 
debouncing and multiple pulses
    if (Position2 != Position)
    {
      // "Grey Code"
      // (0 to 1) or (1 to 3) or (3 to 2) or (2 to 0).

      int isFwd = ((Position == 0) && (Position2 == 1)) ||
                  ((Position == 1) && (Position2 == 3)) ||
                  ((Position == 3) && (Position2 == 2)) ||
                  ((Position == 2) && (Position2 == 0));

      if (isFwd == 1) {
        if (modePos == 0 || modePos == 1 && mode == 2) {
          encoderValue = encoderValue + (int(encoderValue*0.15)+1); 
//non-linear change
        }
        else
        {
          encoderValue++;
        }
      }
      else if (isFwd == 0)
      {
        if (modePos == 0 || modePos == 1 && mode == 2) {
          encoderValue = encoderValue - (int(encoderValue*0.15))-1;
        }
        else {
          encoderValue--;
        }
        if ((mode != 0) && (encoderValue < 0)) {
          encoderValue = 0;
        }
      }
    }
....
  }
....
}

von Wolfgang (Gast)


Lesenswert?

Dieter S. schrieb:
> Da ein nackter Encoder immer prellt, ...

Eine vernünftige Software zähle bei jedem Preller einmal vor und zurück 
(oder umgekehrt), solange sich während dessen das zweite Signal ruhig 
verhält, i.e. nicht unter Kontaktproblemen leidet. Bei einem 
vernünftigen Schalter sollte Prellen doch wohl nur nach einem 
Schaltvorgang auftreten.

von Dieter S. (Gast)


Lesenswert?

Wolfgang schrieb:
>
> Eine vernünftige Software zähle bei jedem Preller...
Sag ich doch.

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


Lesenswert?

bianchifan schrieb:
> delay (50);       // longer wait for debouncing and multiple pulses
Ein Programm, das (abseits der Initialisierung) ein delay() im 
Millisekundenbereich braucht, ist Murks.

> "Grey Code"
Frank hieß Gray. Grau wurde er erst im Alter...
https://de.wikipedia.org/wiki/Frank_Gray_%28Physiker%29

> Nicht sonderlich elegant, tut aba..
Es ist Zufall, dass das tut, oder du hast Glück gehabt mit deinem 
Encoder. Denn wenn du dich für 50ms blind stellst, kannst du niemals 
zuverlässig dem Geber folgen.
Zu den Grundlagen siehe das da:
http://www.lothar-miller.de/s9y/categories/46-Encoder
Dabei geht es zwar um VHDL, aber an der Waveform in der Mitte der Seite 
sieht man dass man eben nicht blind sein darf, sondern schnell 
genug, um auch kurze Pegelwechsel abtasten zu können.

: Bearbeitet durch Moderator
von Dieter S. (Gast)


Lesenswert?

Hallo Stephan,

ich wollte das mit dem Encoder doch selber nochmal durchspielen und habe 
folgende Library dazu genommen:

https://github.com/mathertel/RotaryEncoder

Diese funktioniert bei mir mit den beigefügten Demoprogrammen 
einwandfrei.
Mit oder ohne Interrupt. Teste es mal damit.

von Stephan R. (dacker01)


Angehängte Dateien:

Lesenswert?

Dieter S. schrieb:
> ich wollte das mit dem Encoder doch selber nochmal durchspielen und habe
> folgende Library dazu genommen:
>
> https://github.com/mathertel/RotaryEncoder

Hallo Dieter!
Ich habe deine Libary ausprobiert und bekomme über den seriellen Port 
keine Werte in Form von Zahlen, sonder nur Buchstaben.

Ist das so gewollt?

von Frank (Gast)


Lesenswert?

Stephan R. schrieb:
> Ist das so gewollt?

Was fällt uns da auf wenn man wenigstens ein mal in den Code geschaut 
hat?
1
Serial.begin(57600);

von Wolfgang (Gast)


Lesenswert?

Stephan R. schrieb:
> Ist das so gewollt?

Die Library gibt von sich aus gar nichts auf die serielle 
Schnittstelle aus. Du hast also vermutlich irgendein Programm, was die 
Library benutzt und in dem Programm wird eine bestimmte Übertragungsrate 
für die Schnittstelle gesetzt, die natürlich zu den 9600Bd passen muss, 
die du im Seriellen Monitor eingestellt hast. Sonst kommen bestenfalls 
kryptische Zeichen raus ;-)

von Frank (Gast)


Lesenswert?

Wolfgang schrieb:
> Die Library gibt von sich aus gar nichts auf die serielle Schnittstelle
> aus.

Die Beispiele im Link schon ;-)

von Dieter S. (Gast)


Lesenswert?

Wie schon geschrieben wurde musst du die baudrate anpassen.

von bianchifan (Gast)


Lesenswert?

Lothar M. schrieb:
> Denn wenn du dich für 50ms blind stellst, kannst du niemals
> zuverlässig dem Geber folgen.

Das war doch auch gar nicht meine Absicht, das Geknatter sollte 
übersprungen werden genauso wie die überzähligen Impulse pro 
Raststellung, es war zum Ausloten einer lib am Steckbrett gedacht.

von Wolfgang (Gast)


Lesenswert?

Frank schrieb:
> Die Beispiele im Link schon ;-)

Meine Glaskugel sagt zum verwendeten Programm überhaupt nichts und von 
den Beispielen würden maximal zwei überhaupt nur etwas auf der seriellen 
Schnittstelle ausgeben ;-)

Stephan R. schrieb:
> Ich habe deine Libary ausprobiert ...

von Dieter S. (Gast)


Lesenswert?

Stephan R. schrieb:
> Dieter S. schrieb:
> ich wollte das mit dem Encoder doch selber nochmal durchspielen und habe
> folgende Library dazu genommen:
> https://github.com/mathertel/RotaryEncoder
>
> Hallo Dieter!
> Ich habe deine Libary ausprobiert und bekomme über den seriellen Port
> keine Werte in Form von Zahlen, sonder nur Buchstaben.
>
> Ist das so gewollt?

Ich wollte nur noch kurz anmerken:
Das ist nicht meine Library. Ich verwende diese nur. Und wenn du die 
Baudrate richtig eingestellt hast, wird es auch gehen.

von Dieter S. (Gast)


Lesenswert?

Hallo Stephan,
konntest du hier schon weitere Versuche starten?
Die beiliegenden Beispielprogramme funktionieren doch prima.

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.