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