100PPR Encoder Pulse an Arduino richtig zählen

Gast #5302818
Lesenswert?

Guten Tag,

ich versuche einen 100PPR Pulse Encoder an einem Arduino zu betreiben.
https://www.ebay.de/itm/100PPR-6-Terminal-Eletronic-Hand-Wheel-Manual-Pulse-Encoder-Generator-CNC-Lathe/252100823685
Mein Code sieht wie folgt aus:
1
int encoder0PinA = 2;
2
int encoder0PinB = 3;
3
int encoder0negPinA = 4;
4
int encoder0negPinB = 5;
5
int encoder0Pos = 0;
6
int encoder0PinALast = LOW;
7
int current = LOW;
8

9
void setup()
10
{
11
  pinMode (encoder0PinA, INPUT);
12
  pinMode (encoder0PinB, INPUT);
13
  pinMode (encoder0negPinB, INPUT);
14
  pinMode (encoder0negPinB, INPUT);
15
  Serial.begin (9600);
16
  Serial.println("Ready\n0");
17
}
18

19
void loop()
20
{
21
  current = digitalRead(encoder0PinA);
22
  if ((encoder0PinALast == LOW) && (current == HIGH))
23
  {
24
    if (digitalRead(encoder0PinB) == HIGH)
25
    {
26
      encoder0Pos++;
27
    if(encoder0Pos == 100) { encoder0Pos = 0; }
28
    }
29
    else
30
    {
31
      encoder0Pos--;
32
      if(encoder0Pos == -1) { encoder0Pos = 99; }
33
    }
34
    Serial.println (encoder0Pos);
35
  }
36
  encoder0PinALast = current;
37
}

Den Wert encoder0Pos zu erhöhen klappt auch, er wird erhöht, nachdem der 
Encoder eingerastet ist.
Den Wert encoder0Pos zu erniedrigen klapp nicht sauber, da der Arduino 
schon vor dem Einrasten zählt.
So kommt es durch schnelleres Drehen zu anderen Werten, wie beim 
langsamen Drehen.

Der Encoder hat neben A und B auch noch neg. A und neg. B Ausgänge.
Wie kann ich (mit diesen) das Problem umgehen?
Oder gibt es eine andere Lösung?

Danke für eure Hilfe
Gast #5302880
Lesenswert?

Peter schrieb:
>Den Wert encoder0Pos zu erniedrigen klapp nicht sauber, da der Arduino
>schon vor dem Einrasten zählt.

Das Einrasten hat nichts mit dem Zählen oder den Kontakten
zu tun, daß ist eine föllig unabhängige mechanische Sache.
Der Fehler liegt woanders, vielleicht in deinem Programm.

>Der Encoder hat neben A und B auch noch neg. A und neg. B Ausgänge.

Was hat er überhaupt für Kontakte? Sind das Mechanische Kontakte,
oder ist da Elektronik drinn?
Wenn das zwei mechanische Umschaltekontakte sind, kann
man damit mit RS-Flipflops prima Kontaktentprellschaltungen
aufbauen, die 100% funktionieren.
Gast #5302922
Lesenswert?

Habe nun mal direkt nach Inkrementalgeber gesucht, danke für den 
Hinweis.

Mit folgendem Code klappt es besser aber auch noch nicht richtig.
1
int encoder0PinA=3;
2
int encoder0PinB=2;
3
int encoder0Pos = 0;
4

5
void setup ()
6
{
7
 attachInterrupt(0,CHAInt,CHANGE); // Call Channel A of ENCODER Function while on CH1 Signal Changing
8
 pinMode(encoder0PinA,INPUT);
9
 pinMode(encoder0PinB,INPUT);
10
 digitalWrite(encoder0PinA,HIGH);
11
 digitalWrite(encoder0PinB,HIGH);
12
 Serial.begin (9600);
13
 Serial.println("Ready\n0");
14
}
15

16
void loop()
17
{
18

19
}
20

21
void CHAInt ()
22
{
23
 boolean a=false;
24
 boolean b=false;
25
 a = digitalRead(encoder0PinA);
26
 b = digitalRead(encoder0PinB);
27
 if (a==true && b==false||a==false && b==true){
28
   encoder0Pos++;
29
 }
30
 if (a==false && b==false ||a==true&& b==true){
31
   encoder0Pos--;
32
 }
33
 Serial.println(encoder0Pos/2);
34
}


Ich denke da ist "Elektronik drin".
Da 5V und GND benötigt wird, ohne kommt kein Output zustande.
#5302930
Lesenswert?

Dein Algorithmus für den Encoder funktioniert nicht. Kannst ja mal 
folgendes ausprobieren:

int drehencodertask(int A,int B)
{
static int enc_last=0,enc_delta=0;
    char i = 0;

    if (A) i = 1;
    if (B) i ^= 3;
    i -= enc_last;
    if (i & 1)
    {
        enc_last += i;
        enc_delta += (i & 2) - 1;
    }
    return enc_delta;
}

Bei meinem Drehencoder (mechanisch) ändert sich enc_delta von Rast zu 
Rast Stellung jeweils um 4. Das kann bei Dir anders sein. Ergebnis würde 
mich interessieren.

Bei Dir einfach in loop() folgende Zeile:
Serial.println 
(drehencodertask(digitalRead(encoder0PinA),digitalRead(encoder0PinB));
#5302951
Lesenswert?

Peter schrieb:
> Ist bei mir genauso.

Das ging ja schnell. Danke für den Test.

Solltest Du verwenden können, wenn Du enc_delta um 2 shiftest. Ich 
initialisiere Enc_deta mit 2, weil der Encoder bei manchen 
Raststellungen die Kontakte nicht sauber stehen. Dann gibts beim shiften 
weniger Fehler.


P.S.
Der Code ist schwer verständlich, weil optimiert. Nur eine if Abfrage!
Gast #5307822
Lesenswert?

Shiftoperator habe ich noch nie verwendet. Ich stehe grade etwas auf dem 
Schlauch.
1
int encoder0PinA = 2;
2
int encoder0PinB = 3;
3
int encoder0Pos = 0; 
4

5
void setup()
6
{
7
  Serial.begin(9600);
8
  Serial.println("Ready\n0");
9
}
10

11
void loop()
12
{
13
  Serial.println(drehencodertask(digitalRead(encoder0PinA),digitalRead(encoder0PinB)));
14
  Serial.println(encoder0Pos);
15
}
16

17
int drehencodertask(int A,int B)
18
{
19
  static int enc_last=0,enc_delta=2; //vorher enc_delta=0
20
  char i = 0;
21
  encoder0Pos = enc_delta >> 2; 
22

23
    if (A) i = 1;
24
    if (B) i ^= 3;
25
    i -= enc_last;
26
    if (i & 1)
27
    {
28
        enc_last += i;
29
        enc_delta += (i & 2) - 1;
30
    }
31
    return enc_delta;  
32
}

Wo ist "ganz am Anfang", außerhalb von int drehencodertask(int A,int B) 
geht es ja nicht oder doch?

"Ich initialisiere Enc_deta mit 2", also static int 
enc_last=0,enc_delta=2;?
Gast #5307834
Lesenswert?

So, neue Erkenntnis, ich habe den folgenden Code und die Libary dazu 
verwendet.
1
/* Encoder Library - TwoKnobs Example
2
 * http://www.pjrc.com/teensy/td_libs_Encoder.html
3
 *
4
 * This example code is in the public domain.
5
 */
6

7
#include <Encoder.h>
8

9
// Change these pin numbers to the pins connected to your encoder.
10
//   Best Performance: both pins have interrupt capability
11
//   Good Performance: only the first pin has interrupt capability
12
//   Low Performance:  neither pin has interrupt capability
13
Encoder knobLeft(2,3);
14

15
void setup()
16
{
17
  Serial.begin(9600);
18
  Serial.println("Encoder Test:");
19
}
20

21
long positionLeft  = -999;
22

23
void loop() {
24
  long newLeft;
25
  newLeft = knobLeft.read();
26
  if (newLeft != positionLeft)
27
  {
28
    Serial.print("Left = ");
29
    Serial.print(newLeft);
30
    Serial.println();
31
    positionLeft = newLeft;
32
  }
33
  // if a character is sent from the serial monitor,
34
  // reset both back to zero.
35
  if (Serial.available())
36
  {
37
    Serial.read();
38
    Serial.println("Reset knobs to zero");
39
    knobLeft.write(0);
40
  }
41
}

Wenn ich mal schneller und mal langsamer drehe, habe ich wieder eine 
Differenz von 4, mal von 20, mal von 60. Je nachdem wie oft ich drehe.

Verwende ich nun aber die neg. Kontakte also A Strich und B Strich, kann 
ich 3x, 10x oder auch 20x in unterschiedlichen Geschwindigkeiten drehen, 
stelle ich den Encoder dann wieder auf Null (Skala), steht im 
SerialMonitor auch wirklich 0...

Ist also ein Hardwaredefekt/-problem.

Dennoch würde mich das mit dem Shiftoperator interessieren.
#5307913
Lesenswert?

Peter schrieb:
> Wenn ich mal schneller und mal langsamer drehe, habe ich wieder eine
> Differenz von 4, mal von 20, mal von 60. Je nachdem wie oft ich drehe.
>
> Verwende ich nun aber die neg. Kontakte also A Strich und B Strich, kann
> ich 3x, 10x oder auch 20x in unterschiedlichen Geschwindigkeiten drehen,
> stelle ich den Encoder dann wieder auf Null (Skala), steht im
> SerialMonitor auch wirklich 0...
>
> Ist also ein Hardwaredefekt/-problem.
>
> Dennoch würde mich das mit dem Shiftoperator interessieren.

Irgendwie hast Du doch jetzt eine Lösung. Verwende A' und B'

Die Ausgänge des Encoders müssen halt zum Decoderalgorithmus passen. Da 
muss man manchmal einfach spielen oder probieren.

Du bekommst jetzt immer Vielfache von 4, weil der Encoder das halt so 
macht. Von Rast zu Raststellung ändern A,B halt viermal ihren Zustand. 
Damit Du 1,2,3,4.... rausbekommst, musst Du halt einfach durch 4 teilen 
oder eben um 2 (nach rechts) shiften.
Um 2 (nach rechts) shiften teilt für positive Zahlen durch 4. Das musst 
Du Dir mal in einem Grundlagenbuch "C lernen" mal angucken. Es gibt 
einen kleinen Unterschied zwischen shiften und Teilen für negative 
Zahlen.
Dreh mal den Encoder von der Nullstellung nach links. Dann müsstest Du 
negative Zahlen bekommen. (-4,-8,-12 . . .)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren