INFO: Dieses Forum nutzt Cookies...
Cookies sind für den Betrieb des Forums unverzichtbar. Mit der Nutzung des Forums erklärst Du dich damit einverstanden, dass wir Cookies verwenden.

Es wird in jedem Fall ein Cookie gesetzt um diesen Hinweis nicht mehr zu erhalten. Desweiteren setzen wir Google Adsense und Google Analytics ein.

Antwort schreiben 
 
Themabewertung:
  • 0 Bewertungen - 0 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
Rotary Encoder - gedrückt und gleichzeitig drehen
28.10.2019, 20:23 (Dieser Beitrag wurde zuletzt bearbeitet: 28.10.2019 20:24 von Gerdchen03.)
Beitrag #1
Rotary Encoder - gedrückt und gleichzeitig drehen
Ich habe an einem Sparkfun Pro Micro einen Drehender angeschlossen. Der Sparkfun soll an einen PC Befehle senden. Ich habe gelesen, dass man den Drehencoder mit Pushbutton auf mehrere Weise nutzen kann:
- kurz gedrückt
- lang gedrückt
- drehen
- drücken und drehen

Die ersten drei Varianten habe ich umsetzen können. Unten ein Beispielcode von mir, der soweit funktioniert. Ich finde aber nichts, wie ich drücken und drehen gleichzeitig abfrage. Wie kann ich den Code um den entsprechenden Teil erweitern?

Code:
#include <Encoder.h>
#include <Keyboard.h>


int accel = 2;
int RE_PB = 7;

long longpresstime = 500;
long RE_PBtimer = 0;

bool oldStatus = true;
bool RE_PBactive = false;
bool RE_PBLongpressactive = false;

Encoder R_Enc(1, 0);
long oldPosition  = -999;
int buttonState;
int lastButtonState = LOW;
long lastDebounceTime = 0;
long debounceDelay = 80;  

void setup() {
  pinMode(RE_PB, INPUT_PULLUP);
  Serial.begin(9600);
  Serial.println("Debug Output:");
    
}

void loop() {
  long newPosition = R_Enc.read() / accel;
  if (newPosition != oldPosition) {
    
    if(newPosition > oldPosition) {
      Keyboard.write(KEY_DOWN_ARROW);
    }
    
    if(oldPosition > newPosition) {
     Keyboard.write(KEY_UP_ARROW);  
    }
    
    oldPosition = newPosition;
    Serial.println(newPosition);
    
  }

//RE_PB
  if (digitalRead(RE_PB) == LOW) {
    if (RE_PBactive == false) {
      RE_PBactive = true;
      RE_PBtimer = millis();
    }
    if ((millis() - RE_PBtimer > longpresstime) && (RE_PBLongpressactive == false)) {
      RE_PBLongpressactive = true;
      Keyboard.write(KEY_F1);
      delay(debounce_delay);
    }
  }
  else {
    if (RE_PBactive == true) {
      if (RE_PBLongpressactive == true) {
        RE_PBLongpressactive = false;
      }
      else {
        Keyboard.write(KEY_RETURN);
        delay(debounce_delay);
      }
      RE_PBactive = false;
    }
  }
}
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
28.10.2019, 20:36
Beitrag #2
RE: Rotary Encoder - gedrückt und gleichzeitig drehen
Von Drücken und Drehen habe ich noch nichts gehört. Wo hast Du das her?
Ich stelle es mir schon von der Bedienung her grauselig vor.

So, wie ich es kenne, wird Drehen und Drücken getrennt ausgewertet.

Gruß Tommy

"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
28.10.2019, 20:40
Beitrag #3
RE: Rotary Encoder - gedrückt und gleichzeitig drehen
Ich hab das aus einem Forum, da muss man sich allerdings anmelden. Der User hat einen Code veröffentlicht, den ich aber so nicht in meinen implementieren kann. Einen Großteil davon verstehe ich auch nicht, weil er für mich zu undurchsichtig ist. Hier mal der Code.

Code:
// A simple Arduino Leonardo based program to use two rotary encoders with push buttons and three additional buttons to operate XCSoar.
// This tutorial was very helpful: http://www.loiph.in/2014/09/arduino-leonardo-atmega32u4-based-usb.html
// Modified by Thomas Hanika;

#include <Encoder.h>
// The rotary encoder library http://www.pjrc.com/teensy/td_libs_Encoder.html

#include <Keyboard.h>

const int ACCELERATION = 2;
// This is an acceleration factor. Use between 1 and 8 to suit how quickly the volume goes up or down.

const int DEPRELLING_DELAY = 50;
// this delay is for deprelling the buttons and

// The digital pin to which the rotary encoder push button is connected too. Assumes that the pin has a pull-down resistor.
// Button definition
const int BTN_KNOB_LEFT = 9;
const int BTN_FN = 14;
const int BTN_M = 16;
const int BTN_ESC = 15;
const int BTN_KNOB_RIGHT = 8;
const int BTN_STF = 4; // Speed2Fly (optional)

struct BtnProperties {
  const int pin;  // defines arduino pin
  const int key;  // default key to send
  const int key_longpress; // key if a long pressing of the button is detected or in switchmode: the key to send after releasing button
  const bool isSwitch; // behavior of button logic lika a switch or like a button. if true, then key is send imidiately
  const int msLongPress; // the timeout to signal longpressed
};

// list of buttons
#define MAX_BUTTONSDECLARED 6

enum ueButton {KnobLeft = 0, Fn, Menu, Esc, KnobRight = 4,STF};

const BtnProperties buttonProps[MAX_BUTTONSDECLARED] = {
//{int pin,       int key,    int key_longpress,bool isSwitch,int msLongPress}
  {BTN_KNOB_LEFT, KEY_RETURN, 'm',              false,        1500}, // 'm' vor free use (mute sound?)
  {BTN_FN,        KEY_F5,     KEY_F6,           false,        1500}, // default.xci: F5=> GotoLookUp, F6 => Setup Alternates
  {BTN_M,         KEY_F1,     KEY_F8,           false,        1500}, // default.xci: F1=> QuickMenu, F8=> Setup Basics
  {BTN_ESC,       KEY_ESC,    KEY_F7,           false,        1500}, // default.xci: ESC=> ESC, F7=> Setup Task
  {BTN_KNOB_RIGHT, KEY_RETURN,'a',              false,        1500}, // 'a' vor free use (MC auto mode?)
  {BTN_STF,       's',        'v',              true,         500 }, // 500ms for autodetection switch or button, S on activ LOW
};

struct Button {
  bool isActivated; // actual buttonstate
  bool done; // button is done (key was send)
  bool isButton; // used in switchmode, if button is detected (flip-flop-mode)

  long msDownAt;
  BtnProperties * prop ;
};
Button myButtons[MAX_BUTTONSDECLARED];

struct RotaryKnob {
  const int myEncKnob; // koresponding knob button
  Encoder myEnc; // rotary Encoder
  const int incKey ;
  const int decKey ;
  const int shiftIncKey;
  const int shiftDecKey;
  long myEncPosOld;
};

// These are the pins to which the rotary encoder is connected.
// Pins 2,3 are the interrupt pins on a Leonardo/Uno, which give best performance with a rotary encoder.
// Use other pins if you wish, but performance may suffer.
// Avoid using pins that have LED's attached.
// enum ueEncoder(Left, Right)


RotaryKnob myRotaryKnobs[]{
  {KnobLeft,Encoder(1,0),KEY_UP_ARROW,KEY_DOWN_ARROW,'2','8',-999},
  {KnobRight,Encoder(3, 2),KEY_RIGHT_ARROW,KEY_LEFT_ARROW,'6','4',-999}  
};

void setup() {
  for (unsigned int i = 0; i < MAX_BUTTONSDECLARED; i++) {
    myButtons[i].prop = &buttonProps[i];
    pinMode(myButtons[i].prop->pin, INPUT_PULLUP);
    myButtons[i].isActivated = false;
    myButtons[i].done = false;
    myButtons[i].msDownAt = 0;
  }

  Serial.begin(9600);
  Serial.println("Debug Output:");

}

void doRotary(RotaryKnob & curRot){
    long newPosition = curRot.myEnc.read() / ACCELERATION;
    if (newPosition != curRot.myEncPosOld) {

      // check rotaryknob is pressed an save using in knobPressedWithRotary
      bool bShift = false;
      if (digitalRead(myButtons[curRot.myEncKnob].prop->pin) == LOW) {
        bShift = true;
        myButtons[curRot.myEncKnob].done = true ; // avoid setting any other keys, button key
        myButtons[curRot.myEncKnob].isActivated = true ; // avoid setting any other keys, button key
      }

      if (newPosition > curRot.myEncPosOld) Keyboard.write( bShift ? curRot.shiftIncKey : curRot.incKey);
      if (newPosition < curRot.myEncPosOld) Keyboard.write( bShift ? curRot.shiftDecKey : curRot.decKey);
      curRot.myEncPosOld = newPosition;
      Serial.println(newPosition);
    }
}

void doSwitch(Button & curButn) {
  if (digitalRead(curButn.prop->pin) == LOW) {
    if (!curButn.isActivated) {
      Keyboard.write(curButn.prop->key);
      curButn.done = false;
      curButn.isActivated = true;
      curButn.msDownAt = millis();
      curButn.isButton = false;
    } else {
      if (curButn.isButton) curButn.done = false;
    }
  }
  else {
    if (!curButn.isButton) {
      if ((millis() - curButn.msDownAt) < curButn.prop->msLongPress) { // switch period to short -> button-mode
        curButn.isButton = true;
        curButn.done = true;
      }
    }
    if (!curButn.isButton) {
      if (curButn.isActivated) {
        if (!curButn.done) Keyboard.write(curButn.prop->key_longpress);
        curButn.done = true;
        curButn.isActivated = false;
      }
    } else {
      if (!curButn.done) {
        Keyboard.write(curButn.prop->key_longpress);
        curButn.done = true;
        curButn.isActivated = false;
        curButn.isButton = false;
      }
    }
  }
}

void doButton(Button & curButn) {
  if (digitalRead(curButn.prop->pin) == LOW) {
    if (!curButn.isActivated) { // first time, that signals pressed?
      curButn.isActivated = true;
      curButn.done = false;
      curButn.msDownAt = millis();
    } else {
      if (!curButn.done) {
        if ((millis() - curButn.msDownAt) > curButn.prop->msLongPress) { // if long pressed, send long pressed button key
          Keyboard.write(curButn.prop->key_longpress);
          curButn.done = true;
        }
      }
    }
  } else { //
    curButn.isActivated = false;
    if (!curButn.done) {
      Keyboard.write(curButn.prop->key);
      curButn.done = true;
    }
  }
}

void loop() {

  // Encoder
  for (unsigned int i = 0; i < 2; i++ ) // 2 Encoders
  {
    doRotary(myRotaryKnobs[i]);
  }

  // Buttons
  for (unsigned int i = 0; i < MAX_BUTTONSDECLARED; i++) {
    if (myButtons[i].prop->isSwitch) {
      doSwitch(myButtons[i]);
    } else {
      doButton(myButtons[i]);
    }
  }
  delay(DEPRELLING_DELAY); // deprelling
}
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
28.10.2019, 20:52
Beitrag #4
RE: Rotary Encoder - gedrückt und gleichzeitig drehen
Er wertet beides auch getrennt aus, hällt es aber in einer gemeinsamen Struktur.
Du könntest in Deinem Code auch checken, wenn der Encoder gedrückt ist, ob sich dabei die Position geändert hat.
Pseudocode:
Code:
if (positionAlt != positionNeu && gedrückt)
Ich halte das aber nicht für praktisch in der Bedienung.

Gruß Tommy

"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
28.10.2019, 21:16
Beitrag #5
RE: Rotary Encoder - gedrückt und gleichzeitig drehen
(28.10.2019 20:52)Tommy56 schrieb:  ....
Pseudocode:
Code:
if (positionAlt != positionNeu && gedrückt)
Ich halte das aber nicht für praktisch in der Bedienung.

Gruß Tommy

...gedrückt drehen, ähmm also das kommt mir auch ziemlich schräg vor. Habe auch schon Encoder verbaut und programmiert aber das habe ich nicht benötigt.
lgbk

1+1 = 10 Angel ...und ich bin hier nicht der Suchmaschinen-Ersatz Dodgy...nur mal so als genereller Tipp..
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
28.10.2019, 23:46 (Dieser Beitrag wurde zuletzt bearbeitet: 28.10.2019 23:47 von Gerdchen03.)
Beitrag #6
RE: Rotary Encoder - gedrückt und gleichzeitig drehen
Funktioniert sehr gut. So unpraktisch ist das gar nicht, da ich den Encoder nur ein paar Raster verstellen muss, um die gewünschten Einstellungen zu haben. Einziges Problem ist die Überlagerung zwischen longpress und push+rotate. Ich dachte, dazu setze ich einfach den Timer zurück ( long RE_PBtimer = 0; ) wenn push+rotate aktiv ist, so einfach ist es aber nicht. Wie könnte man diese Überlagerung noch vermeiden?

Code:
if (newPosition != oldPosition && RE_PBactive == true) {

    if (newPosition > oldPosition) {
      Keyboard.write(KEY_F11);            
    }

    if (oldPosition > newPosition) {
      Keyboard.write(KEY_F12);            
    }

    oldPosition = newPosition;
    Serial.println(newPosition);
    long RE_PBtimer = 0;

  }

Code:
if (digitalRead(RE_PB) == LOW) {
    if (RE_PBactive == false) {
      RE_PBactive = true;
      RE_PBtimer = millis();
    }
    if ((millis() - RE_PBtimer > longpresstime) && (RE_PBLongpressactive == false)) {
      RE_PBLongpressactive = true;
      //Serial.println("Quick Menue");
      Keyboard.write(KEY_F1);  // F1
      delay(debounce_delay);
    }
  }
  else {
    if (RE_PBactive == true) {
      if (RE_PBLongpressactive == true) {
        RE_PBLongpressactive = false;
      }
      else {
        //Serial.println("Return");
        Keyboard.write(KEY_RETURN);  // return
        delay(debounce_delay);
      }
      RE_PBactive = false;
    }
  }
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
29.10.2019, 10:49
Beitrag #7
RE: Rotary Encoder - gedrückt und gleichzeitig drehen
Evtl. bei der Longpress prüfen, dass sich die Position nicht geändert hat.

Gruß Tommy

"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
Antwort schreiben 


Möglicherweise verwandte Themen...
Thema: Verfasser Antworten: Ansichten: Letzter Beitrag
  Probleme mit SD-Karten und Displayansteuerung gleichzeitig reichs 7 179 Gestern 18:55
Letzter Beitrag: reichs
  Zeitmessung - Taster gedrückt DEL 14 844 08.08.2019 21:25
Letzter Beitrag: Bitklopfer
  mBlock und Arduino IDE gleichzeitig auf einem PC? mgbig 4 598 14.01.2019 08:39
Letzter Beitrag: mgbig
  2 taster gleichzeitig drücken Rasa 6 1.100 02.01.2019 16:55
Letzter Beitrag: Rasa
  Led bei gedrückt gehaltenen Button nur 2 Sekunden leuchten lassen kiefer_dev 5 724 29.12.2018 14:36
Letzter Beitrag: Tommy56
  Menue und klick-Encoder bojojo 2 691 23.11.2018 13:46
Letzter Beitrag: bojojo
  Probleme mit Umstellung von Tastern auf Encoder MasterOfPuppets 5 837 09.11.2018 22:29
Letzter Beitrag: hotsystems
  Servo langsamer drehen und auf position lassen Thor Wallhall 13 7.012 12.04.2018 11:42
Letzter Beitrag: BanditBandeh
  Ampelschaltung mehrere Befehle möglichst gleichzeitig Jan5663 15 2.681 15.12.2017 15:46
Letzter Beitrag: Chopp
  2 Befehle gleichzeitig, Millis()-Befehl rakadami 24 6.803 13.05.2017 20:47
Letzter Beitrag: MicroBahner

Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 1 Gast/Gäste