Drehimpulsregler einsetzen, auch mit Display

Hier ein kleiner Versuchsaufbau mit einem Drehimpulsregler KY-040 auch als Rotary Encoder bekannt.
Dieser Drehregler hat spürbar beim drehen kurze Wege bis zur nächsten Einrastung. Durch Zählen dieser Impulse kann der Grad der Rotation ermittelt werden. Der Encoder gibt das Signal für die Drehung an Pin „CLK“ und „DT“ wieder. Dabei ist entscheidend, welcher Pin zuerst den Zustand wechselt. Bei Rotation im Uhrzeigersinn wechselt zuerst „CLK“ den Zustand. Bei Rotation gegen den Uhrzeigersinn wechselt „DT“ zuerst den Zustand.
Er kann auch gedrückt werden, so das eine Art Multifunktionsauswahl stattfinden kann.
Er benötigt zwischen 3,3 Volt bis 5 Volt und hat den Pin DT und CLK für digitalen A und B -Kanal, sowie SW als Auswahlbutton

KY-040 Drehgeber-Datenblatt: https://www.rcscomponents.kiev.ua/datasheets/ky-040-datasheet.pdf


Encoder steuert LEDs

Im ersten Teil wird die Ansteuerung einzelner LEDs gezeigt.
Weiter unten im zweiten Teil, ein Wert, zum Beispiel für Lautstärke, auf einem OLED Display angezeigt.

Verdrahtung:

Verdrahtung des Drehreglers an einen Arduino Uno:

Pin 2 mit CLK
Pin 3 mit DT
Pin 4 mit SW,
5V mit + oder VCC
GND an GND.

Die 5 LED Anode an Vorwiderstand 220 Ohm, sowie die jeweilige Katode an den Arduino Pin 5, 6, 7, 8, 9.

Bibliothek:

Arduino Drehgeber-Bibliothek: https://www.arduino.cc/reference/en/libraries/encoder/

Quellcode:
Mit dieser Lösung kann jede LED einzeln ausgewählt und zusätzlich geschaltet werden und zur Kontrolle ist eine Ausgabe im Seriellen Monitor mit dabei.

#include <Encoder.h>

// Encoder Pins
#define ENCODER_PIN_A 2 //CLK
#define ENCODER_PIN_B 3 //DT

// Button Pin
#define BUTTON_PIN 4 // SW

// LED Pins
const int ledPins[] = {5, 6, 7, 8, 9};
int ledCount = sizeof(ledPins) / sizeof(ledPins[0]);

// Create Encoder object
Encoder myEnc(ENCODER_PIN_A, ENCODER_PIN_B);

long oldPosition  = -999;
int selectedLed = 0;
bool ledStates[5] = {false, false, false, false, false}; // LED-Zustände speichern

void setup() {
  Serial.begin(9600);

  // Setup LED pins
  for (int i = 0; i < ledCount; i++) {
    pinMode(ledPins[i], OUTPUT);
    digitalWrite(ledPins[i], LOW);
  }

  // Setup button pin
  pinMode(BUTTON_PIN, INPUT_PULLUP); // Taster mit Pullup-Widerstand
}

void loop() {
  long newPosition = myEnc.read() / 4; //Einstellung für 4 Stufen pro Rastung

  if (newPosition != oldPosition) {
    oldPosition = newPosition;

    // Wrap the encoder value
    selectedLed = newPosition % ledCount;
    if (selectedLed < 0) {
      selectedLed += ledCount;
    }

    // Turn off all LEDs
    for (int i = 0; i < ledCount; i++) {
      digitalWrite(ledPins[i], LOW);
    }

    // Turn on the selected LED
    digitalWrite(ledPins[selectedLed], ledStates[selectedLed] ? HIGH : LOW);

    Serial.print("Selected LED: ");
    Serial.println(selectedLed + 1);
  }

  // Check if the button is pressed
  if (digitalRead(BUTTON_PIN) == LOW) {
    delay(50); // Debounce delay
    if (digitalRead(BUTTON_PIN) == LOW) { // Confirm button press
      ledStates[selectedLed] = !ledStates[selectedLed]; // Toggle LED state
      digitalWrite(ledPins[selectedLed], ledStates[selectedLed] ? HIGH : LOW);
      Serial.print("Toggled LED: ");
      Serial.println(selectedLed + 1);

      // Wait for button release
      while (digitalRead(BUTTON_PIN) == LOW) {
        delay(10);
      }
    }
  }
}

3D-Druck:
Habe mir diesen Drehknopf ausgedruckt. Er passt perfekt und macht die Bedienung deutlich einfacher.
Rotary Encoder Knob by Nitorix – Thingiverse


Encoder mit Display
Jetzt mal mit Display der den Stellwert anzeigt, sowie auch als Balkengrafik.

Verdrahtung:
Dazu werden die OLED Display Pins:
VCC –> 3,3 Volt
GND –> GND
SDA –> A4
SCL –> A5
angeschlossen.

Quellcode:

#include <Wire.h>  //für I2C-Kommunikation
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128  // OLED display Breite
#define SCREEN_HEIGHT 32  // OLED display Hoehe 

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

const int encoderPin1 = 2;  // Encoder Pin CLK
const int encoderPin2 = 3;  // Encoder Pin DT
const int buttonPin = 4;    // Button Pin SW

int encoderValue = 0;
int lastEncoded = 0;

void setup() {
  pinMode(encoderPin1, INPUT);
  pinMode(encoderPin2, INPUT);
  pinMode(buttonPin, INPUT_PULLUP);

  attachInterrupt(digitalPinToInterrupt(encoderPin1), updateEncoder, CHANGE);
  attachInterrupt(digitalPinToInterrupt(encoderPin2), updateEncoder, CHANGE);

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // Initialisiere I2C mit Addr 0x3C
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
}

void loop() {
  if (digitalRead(buttonPin) == LOW) {
    encoderValue = 50;
  }

  encoderValue = constrain(encoderValue, 0, 100);

  display.clearDisplay();
  display.setCursor(0, 0);
  display.print("Stellwert: ");
  display.println(encoderValue);
  display.drawRect(10, 20, encoderValue, 10, WHITE);
  display.display();

  delay(100);
}

void updateEncoder() {
  int MSB = digitalRead(encoderPin1);  //MSB = Bit mit dem höchsten Stellenwert
  int LSB = digitalRead(encoderPin2);  //LSB = Bit mit dem niedrigsten Stellenwert

  int encoded = (MSB << 1) | LSB;          //Umwandlung des 2-Pin-Wertes in eine einzelne Zahl
  int sum = (lastEncoded << 2) | encoded;  //Hinzufügung zum vorherigen kodierten Wert

  if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++;
  if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue --;

  lastEncoded = encoded;  //diesen Wert für das nächste Mal speichern
}

Rechts drehen – Wert wird erhöht, Links drehen – Wert wird kleiner, drücken setzt Standardwert auf 50

, ,