Rotary Encoder und Pushbutton funktioniert nicht richtig

Hallo Zusammen,

Ich versuche gerade ein LCD-Menü mit diesem Rotary Encoder zu bauen und komme jetzt leider
nicht mehr weiter.

Vielleicht hat ja jemand eine Idee oder Tipp für mich.

Encoder:
http://www.ebay.de/itm/Digital-Drehgeber-Rotary-Encoder-Modul-fur-Arduino-Raspberry-Pi-Mikrocontroller-/171973067611?hash=item280a64c35b:g:vcwAAOSwsB9V~Wiu

Ich habe schon eine Auswahl von 1-5 auf dem Display und kann diese auch mit dem Encoder
auswählen.

Menue
https://pl.vc/10m6wu

Leider funktioniert der Encoder-Push-Button nicht so, wie ich gerne möchte.

Also (erst einmal ganz einfach):

1x Push-Button drücken LED an PIN13 ein
1x wiederholtes drücken LED an PIN13 aus

Das funktioniert zwar, aber wenn der Encoder links oder rechts gedreht wird, beeinflusst das
ebenfalls die LED oder der Arduino muss neu gestartet werden, dass er sich auf gehangen hat.

Ich verwende einen Arduino Mega.

Hier der Code:

#include <LiquidCrystal.h>
#include <RotaryEncoder.h>

// ----------------- LCD 16x2

LiquidCrystal lcd(25, 24, 29, 28, 27, 26);

// ----------------- Encoder PINA + PINB

RotaryEncoder encoder(42, 41);

byte full[8]  = {0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111};
byte one[8] = {0b11011, 0b10011, 0b11011, 0b11011, 0b11011, 0b11011, 0b10001, 0b11111};
byte two[8] = {0b10001, 0b01110, 0b11110, 0b11101, 0b11011, 0b10111, 0b00000, 0b11111};
byte three[8] =  {0b00000, 0b11101, 0b11011, 0b11101, 0b11110, 0b01110, 0b10001, 0b11111};
byte four[8] = {0b11101, 0b11001, 0b10101, 0b01101, 0b00000, 0b11101, 0b11101, 0b11111};
byte five[8] = {0b00000, 0b01111, 0b00001, 0b11110, 0b11110, 0b01110, 0b10001, 0b11111};
byte six[8] = {0b11001, 0b10111, 0b01111, 0b00001, 0b01110, 0b01110, 0b10001, 0b11111};

static int pos = 1;
int newPos = 0;
int selected = 0;

// ----------------- Encoder Button

int inPin = 43;        // the number of the input pin
int outPin = 13;       // the number of the output pin

int state = HIGH;      // the current state of the output pin
int reading;           // the current reading from the input pin
int previous = LOW;    // the previous reading from the input pin

// the follow variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long time = 0;         // the last time the output pin was toggled
long debounce = 200;   // the debounce time, increase if the output flickers


void setup()
{

  // Encoder Button
  pinMode(inPin, INPUT);
  pinMode(outPin, OUTPUT);

  // LCD Menue Zahlen
  lcd.begin(16, 2);
  lcd.createChar(0, full);
  lcd.createChar(1, one);
  lcd.createChar(2, two);
  lcd.createChar(3, three);
  lcd.createChar(4, four);
  lcd.createChar(5, five);

  lcd.setCursor(0, 0);
  lcd.print("> 1  2  3  4  5 ");
}

void loop()
{

// ----------------- Encoder Button

  reading = digitalRead(inPin);

  // if the input just went from LOW and HIGH and we've waited long enough
  // to ignore any noise on the circuit, toggle the output pin and remember
  // the time
  if (reading == HIGH && previous == LOW && millis() - time > debounce) {
    if (state == HIGH)
      state = LOW;
    else
      state = HIGH;

    time = millis();
  }

  digitalWrite(outPin, state);
  previous = reading;

// ----------------- LCD Menue

  lcd.setCursor(0, 1);
  selected = newPos;
  lcd.print(selected);
  lcd.print(".");

  encoder.tick();
  newPos = encoder.getPosition();
  if (pos != newPos)
  {
    if (newPos > 5)
    {
      encoder.setPosition(5);
      newPos = 5;
    }

    if (newPos < 1)
    {
      encoder.setPosition(1);
      newPos = 1;
    }

    highlightedSelection(newPos);
    pos = newPos;
  }
}

// ----------------- Cursor Auswahl

void highlightedSelection(int count)
{
  int present = (count * 3) - 1;
  if (count > pos)
  {
    lcd.setCursor(present - 4, 0);
    lcd.print(" ");
    lcd.print(count - 1);
    lcd.print(" ");
  }
  if (count < pos)
  {
    lcd.setCursor(present + 2, 0);
    lcd.print(" ");
    lcd.print(count + 1);
    lcd.print(" ");
  }

  lcd.setCursor(present - 1, 0);
  lcd.write((uint8_t)0);
  lcd.write((uint8_t)0);
  lcd.write((uint8_t)0);
  lcd.setCursor(present, 0);
  lcd.write((uint8_t)count);
}

Ich glaube, du solltest erst mal die grundlegende Funktion des Encoders zum Laufen bekommen. Wo ist der denn her?

Leider steige ich durch deinen Sketch nicht so richtig (fehlende Dokumentation und falsch gepostet) durch.

Dadurch, dass du den Sketch in Quote-Tags gesetzt hast, ist dieser ganz schlecht lesbar. Setze den bitte in Code-Tags, das kannst du auch noch nachträglich ändern.

Hi, ich doktere derzeit auch mit einem Encoder rum.
Evtl. hilft dir der Sketch weiter. Läuft auf einem UNO Clone ohne Probleme.
Pins müssen noch angepasst werden und evtl. ein debouncing für CLK und DT.

int pinA = 4;  // Connected to CLK on KY-040
int pinB = 3;  // Connected to DT on KY-040
const int button = 2;

int select_b_state;
int last_select_b_state = HIGH;
long lastDebounceTime_select_b = 0;
long debounceDelay_select_b = 50;

int zaehler = 0;

int encoderPosCount = 0; 
int pinALast;  
int aVal;
boolean bCW;

 void setup() { 
   pinMode (pinA,INPUT);
   pinMode (pinB,INPUT);
   pinMode (button,INPUT_PULLUP);
   /* Read Pin A
   Whatever state it's in will reflect the last position   
   */
   pinALast = digitalRead(pinA);   
   Serial.begin (9600);
 } 

 void loop() { 

int reading_select_b = digitalRead(button);   
if (reading_select_b != last_select_b_state) {
    // reset the debouncing timer
    lastDebounceTime_select_b = millis();
  }
 
if ((millis() - lastDebounceTime_select_b) > debounceDelay_select_b) {
    // if the button state has changed:
    if (reading_select_b != select_b_state) {
      select_b_state = reading_select_b;
      
         if (select_b_state == LOW && zaehler == 0) {
                 
               zaehler = 1;
               
     Serial.print ("Zaehler = ");
     Serial.println (zaehler);
         } else if (select_b_state == LOW && zaehler == 1) {
   
                          zaehler = 0;
                           
                           Serial.print ("Zaehler = ");
                           Serial.println (zaehler);
                   }                    
        
     }
}

last_select_b_state = reading_select_b;

 
   aVal = digitalRead(pinA);
   if (aVal != pinALast){ // Means the knob is rotating
     // if the knob is rotating, we need to determine direction
     // We do that by reading pin B.
     if (digitalRead(pinB) != aVal) {  // Means pin A Changed first - We're Rotating Clockwise

       encoderPosCount ++;
       bCW = true;

        if (encoderPosCount >3){
        encoderPosCount = 3;
       }

     } else {// Otherwise B changed first and we're moving CCW
            
       bCW = false;
       encoderPosCount--;

       if (encoderPosCount <1){
        encoderPosCount = 1;
       }
  
     }

                 if (encoderPosCount == 1) {
            
                      Serial.println ("X-AXIS");
                      Serial.println ("");                      
                      
                      } else if (encoderPosCount == 2) {
                    
                    Serial.println ("Y-AXIS");
                    Serial.println ("");
                      
                      
                      } else if (encoderPosCount == 3) {
                    
                      Serial.println ("Z-AXIS");
                      Serial.println ("");
                      
                 }
                     
 //  Serial.println (encoderPosCount);
   } 
   pinALast = aVal;

   
 }

Habe genau das gleich vor und auch erst vor zwei Tagen den Encoder in Betrieb genommen :slight_smile:

Hat dein Encoder einen Pull-Up Widerstand für den Button? Bei meinem war keiner vorhanden, auf der Rückseite waren nur zwei von drei Widerständen bestückt. Mit einem 10k-Widerstand hat es dann geklappt, möglicherweise kannst du auch den internen Pull-Up vom Arduino aktivieren.

@ HotSystems

Die Grundfunktionen laufen ja. Ich zähle ja alle 2 Clicks einmal forwärts bis 5. bzw. zurück bis 1.
Höher als 5 wird nicht gezählt. (es sollen später 5 Menüpunkte werden) Der Push-Button funktioniert
ja auch mit der LED.

Nur wenn der Encoder gedreht wird, beeinflust das irgendwie die LED mit.

@ Tchefter

Ich werde den Code mal auf einen UNO spielen und den Encoder dort anschließen.
Vielleicht liegt es ja an dem Low-Budget-Encoder.

@ Spexx

Ich schaue heute Abend einmal nach, habe bei Google auch gerade ein paar Bilder gefunden, wo bei
vielen Encodern der SMD-Widerstand R1 fehlt. Erlich gesagt, habe ich da gar nicht drauf geachtet.

Vielleicht hat ja jemand eine Idee oder Tipp für mich.

Encoder: http://www.ebay.de/itm/Digital-Drehgeber-Rotary-Encoder-Modul-fur-Arduino-Raspberry-Pi-Mikrocontroller-/171973067611?hash=item280a64c35b:g:vcwAAOSwsB9V~Wiu [/quote]

Der Drehgeber auf dem Modul bei Deinem eBay-Anbieter sieht vollkommen normal aus, aber die Beschriftung der Anschlüsse auf der Modulplatine finde ich äußerst verwirrend.

Ein mechanischer Drehgeber mit Pushbutton-Schalter hat normalerweise fünf Anschluss-Pins, drei auf der einen Seite und zwei auf der anderen Seite des Drehgebers, und keiner davon darf mit einer Betriebsspannung (+) verbunden sein, es sein denn Du möchtest beim Betreiben des Drehgebers ( entwede3r beim Drücken des Schalters oder beim Drehen der Achse) einen Kurzschluss erzeugen, der an angeschlossenen Arduino-Pins zu unzulässig hohem Strrom und ggf. Fehlfunktion/Zerstörung des Controllers führen kann.

Solche Encoder mit Pushbutton werden nur an GND angeschlossen und an drei Arduino-Datenleitungen (Drehgeber A und B und Schalter) , an denen entweder externe Pullup-Widerstände angeschlossen sein müssen oder zur Initialisierung der pinMode auf INPUT_PULLUP gesetzt wird, um die eingebauten Pullup-Widerstände des Controllers auf dem Arduino-Board an den Pins zu aktivieren.

Hast Du ein Multimeter mit Ohm-Messbereich und kannst ggf. an Deinem Modul mal eine Durchgangsprüfung machen und feststellen, welcher Anschlusspin des Drehgebers mit welchem Anschluss der Modulplatine Durchgang hat (Widerstand 0)?

BTW: Die meisten Libraries für Drehgeber, die es zum freien Download für Arduino gibt, taugen nicht viel und funktionieren zusammen mit mechanischen Drehgebern nur bedingt fehlerfrei.

Hallo!

Dieser Typ von Dreh-Encoder hat die gesamte Elektronik (also Pullups bzw. Pulldowns)
bereits auf seiner kleinen Platine drauf.
Er wird wie die großen Dreh-Encoder mit 100er Auflösung (schwerer großer
Metalldrehknopf, Durchmesser 4,5 cm) sehr einfach direkt angeschlossen:
GND und 5V, SW ist der Schalterkontakt, die beiden anderen sind A und B
des Drehencoders - dort ausprobieren, welcher was ist.

Die anderen, einfachen Drehencoder, die einmal 3 und einmal 2 Anschlüsse haben,
wie hier vorher angesprochen, müssen komplett elektronisch eingebunden werden.

HG

Du willst bestimmt sagen, dass der + für die Pullups ist, und dass ein Pin vom Taster und vom Encoder bereits auf Masse liegen. Und dass somit die eingebauten Pullups nicht gebraucht werden?

hgpa: Hallo!

Dieser Typ von Dreh-Encoder hat die gesamte Elektronik (also Pullups bzw. Pulldowns) bereits auf seiner kleinen Platine drauf. Er wird wie die großen Dreh-Encoder mit 100er Auflösung (schwerer großer Metalldrehknopf, Durchmesser 4,5 cm) sehr einfach direkt angeschlossen: GND und 5V, SW ist der Schalterkontakt, die beiden anderen sind A und B des Drehencoders - dort ausprobieren, welcher was ist.

Die anderen, einfachen Drehencoder, die einmal 3 und einmal 2 Anschlüsse haben, wie hier vorher angesprochen, müssen komplett elektronisch eingebunden werden.

Laut diesem gegoogelten Schaltbild sind neben dem eigentlicheen rotary ecoder nur 2 Stk. 10K Widerstände auf der Platine drauf, die als Pullups für CLK (Encoder_A) und DT (Encoder_B) dienen, sobald GND und + angeschlossen sind. Der Schaltkontakt schließt beim Herunterdrücken der Encoderachse zwischen SW und GND.

|500x304

Genau so ist es.

Das Schaltbild habe ich so schnell nicht mehr gefunden... Meine Wortwahl mit "Elektronik" war natürlich ein bisschen hoch gegriffen, aber immerhin sind ja auch Widerstände elektronische Bauelemente.... :-) und man vereinfacht sich mit diesen hier gezeigten Dreh-Encodern ein bisschen das Löten, zumindest, wenn man - wie ich gerade in einem Projekt - davon über 20 Stück braucht.... :o

Allerdings ist der in der Anzeige genannte Preis recht happig, die gibts auch bereits für unter 2,- €

HG

Der Encoder funktioniert nun endlich.

Es lag weder an dem fehlenden R1 = 10kOhm-Wiederstand am Encoder, noch an dem Sketch.

Ich habe den Code von Tchefter mit dem Encoder sowie einem UNO getestet und es gab keine Fehlfunktionen. Danach habe ich die PIN´s an den Mega angepasst und hatte auf einmal dieselben Probleme mit dem Sektch von Tchefter.

Habe jetzt die PIN´s gewechselt und es läuft:

CLK -> von PIN41 auf PIN51 DT -> von PIN42 auf PIN52 SW -> von PIN43 auf PIN50

… nur der Grund erschließt sich mir nicht so ganz. :confused:

@aLSTRIx:

Ich habe vor einiger Zeit mal ein kleines Beispiel gepostet, wo ich ein "flaches = einstufiges" Menü erstellt habe mit Drehencoder/Switch und LCD: https://forum.arduino.cc/index.php?topic=403948.0 Siehe meinen Code in Antwort #6.

Die benutzten Bibliotheken (die rotary ist im post angehängt) benutze ich seit über einem Jahr ohne Probleme und mit teils 2 Euro-Dreh-Encodern. Vielleicht hilft es auch bei deinem Projekt.

Nachtrag: du warst schneller und jetzt scheint es ja mit deinem Ansatz zu klappen, warum auch immer (kenne mich mit Megas nicht aus, evtl. hat es mit den diversen Interrupt-Pins des Megas zu tun?).