Drehimpulsgeber KY-040

Guten tag,

ich möchte gerne ein Projekt mit einen Drehimpulsgeber aufbauen. Dafür verwende ich den KY-040.

Ich habe mir ein Beispielprogramm rausgesucht, womit ich mir die eingestellten Werte anzeigen lasse. Gerne würde ich das ganze begrenzen, sodass er nur zwischen 0 und 255 zählt. Wenn ich bei diesen Werten angekommen bin, soll sich durch Drehrichtung nichts weiter ändern. Momentan hatte ich es so geändert, das ich zwar in diesen Werten bleibe, jedoch durch drehen ewig weiter gezählt wird, mir jedoch kein neuer Wert angezeigt wird. Ist es möglich, dies zu begrenzen, sodass ich bei den Endwerten mit der nächsten Drehung in die entgegengesetzte Richtung wieder einen neuen Wert angezeigt bekomme?

Zusätzlich würde ich gern über den Button des Impulsgebers meinen aktuellen Wert resetten, bzw. durch drücken die Schritte ändern können. (1x drücken er zählt mit jeder Bewegung 10 Schritte)
Ist das mit dem dem drücken und zwei verschiedenen Funktionen möglich?

Mir ist auch aufgefallen, das mit jeder Bewegung teilweise 4 Schritte gezählt werden. Müsste ich da irgendwo noch eine Pause einbauen?

Hier der Code:

#include <Encoder.h>    // Verwendung der <Encoder.h> Bibliothek 

const int CLK = 39;      // Definition der Pins. CLK an 39, DT an 36.
const int DT = 36;
const int SW = 27;       // Der Switch wird mit Pin 27 Verbunden. 
long altePosition = -999;  // Definition der "alten" Position (Diese fiktive alte Position wird benötigt, damit die aktuelle Position später im seriellen Monitor nur dann angezeigt wird, wenn wir den Rotary Head bewegen)

Encoder meinEncoder(DT, CLK); // An dieser Stelle wird ein neues Encoder Projekt erstellt. Dabei wird die Verbindung über die zuvor definierten Varibalen (DT und CLK) hergestellt.


void setup() {
  Serial.begin(19200); // Festlegung der Baudrate für den seriellen Monitor
  pinMode(SW, INPUT);   // Hier wird der Interrupt installiert.
}

void loop() {
  long neuePosition = meinEncoder.read();  // Die "neue" Position des Encoders wird definiert. Dabei wird die aktuelle Position des Encoders über die Variable.Befehl() ausgelesen.

  if (neuePosition != altePosition)  // Sollte die neue Position ungleich der alten (-999) sein (und nur dann!!)...
  {
    if ((neuePosition >= 0) && (neuePosition <= 255))
      altePosition = neuePosition;

    Serial.println(altePosition);      // ...soll die aktuelle Position im seriellen Monitor ausgegeben werden.

  }

Die library NewEncoder hat das schon eingebaut
Diese Library benötigt jedoch interruptfähige IO-pins
Auf dem Arduino Uno sind das IO-pin 2 und IO-pin 3

#include "Arduino.h"
#include "NewEncoder.h"

const byte EncChA_Pin = 2;
const byte EncChB_Pin = 3;
const int minVal = -10;
const int maxVal =  10;
const int startVal = 2;

// Pins 2 and 3 should work for many processors, including Uno. See README for meaning of constructor arguments.
// Use FULL_PULSE for encoders that produce one complete quadrature pulse per detnet, such as: https://www.adafruit.com/product/377
// Use HALF_PULSE for endoders that produce one complete quadrature pulse for every two detents, such as: https://www.mouser.com/ProductDetail/alps/ec11e15244g1/?qs=YMSFtX0bdJDiV4LBO61anw==&countrycode=US&currencycode=USD

NewEncoder myEncoderObject(EncChA_Pin, EncChB_Pin, minVal, maxVal, startVal, FULL_PULSE);

int16_t currentValue;
int16_t prevEncoderValue;

void setup() {
  // myEncState is a variable of type EncoderState
  // EncoderState is a structured variable that has two "simple" variables
  // .currentValue which is type int16_t
  // (16 bit signed integer valuerange -36767 to 36767)
  // currentValue counts up / down with each pulse created through rotating the encoder
  // and
  // .currentClick which is of type "EncoderClick"
  // the variable type "EncoderClick" can have just 3 values
  // NoClick, DownClick, UpClick where "click" means a "pulse" created through rotating the encoder
  NewEncoder::EncoderState myEncState;

  Serial.begin(115200);
  delay(2000);
  Serial.println("Starting");

  if (!myEncoderObject.begin()) {
    Serial.println("Encoder Failed to Start. Check pin assignments and available interrupts. Aborting.");
    while (1) {
      yield();
    }
  } else {
    // store values of currentValue and EncoderClick into variable myEncState
    myEncoderObject.getState(myEncState);
    Serial.print("Encoder Successfully Started at value = ");
    prevEncoderValue = myEncState.currentValue;
    Serial.println(prevEncoderValue);
  }
}

void loop() {
  NewEncoder::EncoderState myCurrentEncoderState;

  // store actual values into variable myCurrentEncoderState
  if (myEncoderObject.getState(myCurrentEncoderState)) {
    Serial.print("Encoder: ");
    currentValue = myCurrentEncoderState.currentValue;

    // if currentValue has REALLY changed print new currentValue
    if (currentValue != prevEncoderValue) {
      Serial.println(currentValue);
      prevEncoderValue = currentValue;


      // if currentValue stayed the same because the number is at upper/lower limit
      // check if encoder was rotated by using the UpClick / DownClick-values
    } else
      switch (myCurrentEncoderState.currentClick) {
        case NewEncoder::UpClick:
          Serial.println("at upper limit.");
          break;

        case NewEncoder::DownClick:
          Serial.println("at lower limit.");
          break;

        default:
          break;
      }
  }
}

vgs

1 Like

Ok vielen Dank. Müsste ich mal probieren. Ich benutze einen esp32 , ganz vergessen zu erwähnen.

Bekomme ich die newencoder Bibliothek normal über Google ?

Ich benutze eine ander lib.
Darum ist der Aufruf auch etwas anders, aber vielleicht kannst Du Dir ja ablesen, wie das funktionieren kann.

Kurze Beschreibung:
Ich habe eine Funktion, die alles abhandelt. Übergeben wird ihr:

  • die Zahl, die geändert werden soll
  • der kleinste Wert für die Zahl
  • der größte Wert für die Zahl
  • ob am Ende Schluss sein soll oder ein überrollen erfolgt
    Das Ganze geht mit dieser Funktion mit allen positiven Zahlen (unsigned int).
// Forensketch Drehencoder Wertebereich begrenzen
// https://forum.arduino.cc/t/drehimpulsgeber-ky-040/992947/4

#include <rotary.h> //https://github.com/CarlosSiles67/Rotary
Rotary r = Rotary(45, 43);

uint32_t zahl, alteZahl;


void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start..."));
  Serial.println(zahl);
}

void loop()
{
  setupZahl(zahl, 0, 12, false); // zu ändernde Zahl, minimal, maximal, umlauf oder Ende
  ausgabe();
}
//
void ausgabe()
{
  if (zahl != alteZahl)
  {
    Serial.println(zahl);
    alteZahl = zahl;
  }
}
//
void setupZahl(uint32_t &aenderZahl, const uint32_t &minZahl, const uint32_t &maxZahl, const bool umlauf)
{
  if (aenderZahl < minZahl) aenderZahl = minZahl;
  if (aenderZahl > maxZahl) aenderZahl = maxZahl;
  uint32_t myZahl = aenderZahl;     // lokale Berechnung
  unsigned char val = r.process();  // encoder auslesen
  if (val == r.clockwise())         // auf zaehlen
  {
    myZahl++;
    if (umlauf)                     // Wenn Überlauf
    {if (myZahl > maxZahl) myZahl = minZahl;}
    else                            // Wenn Begrenzung
    {if (myZahl > maxZahl) myZahl = maxZahl;}
  }
  if (val == r.counterClockwise())  // ab zaehlen
  {
    if (myZahl == minZahl)          // Wenn kleinstmögliche Zahl schon erreicht
    {if (umlauf) myZahl = maxZahl;} // Nur wenn Überlauf
    else myZahl--;
  }
  aenderZahl = myZahl;
}

Das kann alle möglichen Gründe haben, mit der roraylib habe ich das Phänomen noch nie gehabt.

Ja, haben wir in diesem Thread gebaut - kurzes drücken, langes drücken.
Ansonsten geht auch eine lib dafür.

Die Pin-Nimmern von @my_xy_projekt für den Mega2560 mußt Du an den ESP32 anpassen.

danke Stefan, das Programm funktioniert so wie jetzt von mir gewünscht. Der nächste Schritt wäre jetzt durch klicken eine Veränderung des Wertes in größeren Schritten. Und beim zweiten klicken wieder auf Ursprungszählung zurück

Das Prinzip der geringsten Verwunderung:
Eigentlich benutzt man das klicken, als OK, als positive Bestätigung, wie ein Enter.
Und die großen/kleine Schritte erzeugt man über eine Beschleunigungsfunktion. Langsam drehen, kleine Schritte, schnell drehen große Schritte, noch schneller, noch größer.

schreibe bitte explizit welchen Code du benutzt- user @my_xy_projekt hat auch eine Version gepostet.

Am besten ist jeweils den aktuellen kompletten Sketch als Code-Section in einem neuen Posting zu posten.

Wie groß ist denn der Zahlenbereich den du da insgesamt einstellen willst?
Wie möchtest du den Einstellmodus beenden ?

  • soll das durch eine andere Taste erfolgen
  • durch es wird 10 Sekunden lang nicht gedreht ?
  • langer Encoder-Tasterdruck?
    oder noch irgendwie anders?

vgs

Habe den Code von @StefanL38 benutzt. Ich wusste nicht wie ich den Code zitieren konnte.

hier mal der aktuelle Code:

#include "Arduino.h"
#include "NewEncoder.h"

#define VSPI_MOSI 23
#define VSPI_SCK 18
#define VSPI_SS 5
#define ADR_BITS 0x00  // Adressbits A0 und A1 auf 0 setzen

const byte CLK = 39;
const byte DT = 36;
const int Taster = 27;
const int minVal = 0;
const int maxVal =  255;
const int startVal = 0;


// Pins 2 and 3 should work for many processors, including Uno. See README for meaning of constructor arguments.
// Use FULL_PULSE for encoders that produce one complete quadrature pulse per detnet, such as: https://www.adafruit.com/product/377
// Use HALF_PULSE for endoders that produce one complete quadrature pulse for every two detents, such as: https://www.mouser.com/ProductDetail/alps/ec11e15244g1/?qs=YMSFtX0bdJDiV4LBO61anw==&countrycode=US&currencycode=USD

NewEncoder myEncoderObject(CLK, DT, minVal, maxVal, startVal, FULL_PULSE);

int16_t currentValue;
int16_t prevEncoderValue;
uint8_t poti_value;

void setup() {
  // myEncState is a variable of type EncoderState
  // EncoderState is a structured variable that has two "simple" variables
  // .currentValue which is type int16_t
  // (16 bit signed integer valuerange -36767 to 36767)
  // currentValue counts up / down with each pulse created through rotating the encoder
  // and
  // .currentClick which is of type "EncoderClick"
  // the variable type "EncoderClick" can have just 3 values
  // NoClick, DownClick, UpClick where "click" means a "pulse" created through rotating the encoder
  NewEncoder::EncoderState myEncState;



  attachInterrupt(digitalPinToInterrupt(Taster), Interrupt, CHANGE);

  pinMode(VSPI_MOSI, OUTPUT); // Master Out - Slave In
  pinMode(VSPI_SCK, OUTPUT); // Clock
  digitalWrite(VSPI_SCK, LOW); // Clock-Ruhezustand: LOW
  pinMode(VSPI_SS, OUTPUT); // SPI-Select (Chip Select)
  digitalWrite(VSPI_SS, HIGH); // Slave gesperrt

  Serial.begin(115200);
  delay(2000);
  Serial.println("Starting");

  if (!myEncoderObject.begin()) {
    Serial.println("Encoder Failed to Start. Check pin assignments and available interrupts. Aborting.");
    while (1) {
      yield();
    }
  } else {
    // store values of currentValue and EncoderClick into variable myEncState
    myEncoderObject.getState(myEncState);
    Serial.print("Encoder Successfully Started at value = ");
    prevEncoderValue = myEncState.currentValue;
    Serial.println(prevEncoderValue);
  }
}

void loop() {
  NewEncoder::EncoderState myCurrentEncoderState;

  // store actual values into variable myCurrentEncoderState
  if (myEncoderObject.getState(myCurrentEncoderState)) {
    Serial.print("Encoder: ");
    currentValue = myCurrentEncoderState.currentValue;

    // if currentValue has REALLY changed print new currentValue
    if (currentValue != prevEncoderValue) {
      Serial.println(currentValue);
      prevEncoderValue = currentValue;

      poti_value = prevEncoderValue;
      WRITE_POTI(ADR_BITS, poti_value, 10); // 10-Bit-Datenwort für die Wiper-Einstellung an Digitalpoti senden



      // if currentValue stayed the same because the number is at upper/lower limit
      // check if encoder was rotated by using the UpClick / DownClick-values
    } else
      switch (myCurrentEncoderState.currentClick) {
        case NewEncoder::UpClick:
          Serial.println("Obere Einstellgrenze erreicht");
          break;

        case NewEncoder::DownClick:
          Serial.println("Untere Einstellgrenze erreicht.");
          break;

        default:
          break;
      }
  }
}
void Interrupt() // Beginn des Interrupts. Wenn der Rotary Knopf betätigt wird, springt das Programm automatisch an diese Stelle. Nachdem...
{
  static unsigned long last_interrupt_time = 0;
  unsigned long interrupt_time = millis();
  // If interrupts come faster than 200ms, assume it's a bounce and ignore
  if (interrupt_time - last_interrupt_time > 200)
  {
    Serial.println("Button gedrückt.");
  }
  last_interrupt_time = interrupt_time;
}

Insgesamt ist der Zahlenbereich von 0-255.

Geplant war die Umsetzung der Veränderung durch einmaliges klicken. um je Drehrichtung um 10 Schritte, wenn ich nochmal klicke um 20 Schritte.

Beendet werden sollte das eigentlich durch ein drittes klicken.

Falls das so möglich ist. Wenn man das über einen längeren Tastendruck ändern kann, wäre auch ok

abhängig davon was du insgesamt in deinem Programm machen willstbrauchst du höchstwahrscheinlich keinen Interrupt zu benutzen.

Es gibt eine Menge Demo-Programme zu interrupt die in der Interrupt-function etwas auf die serielle Schnittstelle ausgeben.

Das ist eine - ich bezeichne es mal als - extrem unprofessionelle Art und Weise.
Ein Profi macht in einer Interruptroutine NIEMALS eine Ausgabe auf die serielle Schnittstelle.

Einzige Ausnahme: der Arduino-Core-Code der INTERN aufgerufen wird wenn man "print" aufruft.

Um es mal auf die Realwelt zu übertragen: Mit einem Rennwagen B fährt man nicht im inneren des Rennwagens A herum. Nocht mal mit einem ferngesteuerten Modellauto.

Einem Newcomer kann man das nicht vorwerfen wenn er es dann auch so macht.
Bitte vorsichtig zu Ende lesen das folgende ist neutral gemeint keinesfalls als Vorwurf
Ich habe den Eindruck im Moment schreibst du Code um so eine Art Basisfunktionen zu haben die später für veschiedene Sachen verwendet werden sollen. Das ist vollkommen OK.

In der Interruptroutine wird nur eine flag-variable gesetzt und dann wird diese Flag-Variable in loop() abgefragt

Probiere mal diese Version aus die macht das so.

#include "Arduino.h"
#include "NewEncoder.h"

#define VSPI_MOSI 23
#define VSPI_SCK 18
#define VSPI_SS 5
#define ADR_BITS 0x00  // Adressbits A0 und A1 auf 0 setzen

const byte CLK = 39;
const byte DT = 36;
const int Taster = 27;
const int minVal = 0;
const int maxVal =  255;
const int startVal = 0;

volatile boolean TasterGedrueckt = false;

// Pins 2 and 3 should work for many processors, including Uno. See README for meaning of constructor arguments.
// Use FULL_PULSE for encoders that produce one complete quadrature pulse per detnet, such as: https://www.adafruit.com/product/377
// Use HALF_PULSE for endoders that produce one complete quadrature pulse for every two detents, such as: https://www.mouser.com/ProductDetail/alps/ec11e15244g1/?qs=YMSFtX0bdJDiV4LBO61anw==&countrycode=US&currencycode=USD

NewEncoder myEncoderObject(CLK, DT, minVal, maxVal, startVal, FULL_PULSE);

int16_t currentValue;
int16_t prevEncoderValue;
uint8_t poti_value;

void setup() {
  // myEncState is a variable of type EncoderState
  // EncoderState is a structured variable that has two "simple" variables
  // .currentValue which is type int16_t
  // (16 bit signed integer valuerange -36767 to 36767)
  // currentValue counts up / down with each pulse created through rotating the encoder
  // and
  // .currentClick which is of type "EncoderClick"
  // the variable type "EncoderClick" can have just 3 values
  // NoClick, DownClick, UpClick where "click" means a "pulse" created through rotating the encoder
  NewEncoder::EncoderState myEncState;



  attachInterrupt(digitalPinToInterrupt(Taster), Interrupt, CHANGE);

  pinMode(VSPI_MOSI, OUTPUT); // Master Out - Slave In
  pinMode(VSPI_SCK, OUTPUT); // Clock
  digitalWrite(VSPI_SCK, LOW); // Clock-Ruhezustand: LOW
  pinMode(VSPI_SS, OUTPUT); // SPI-Select (Chip Select)
  digitalWrite(VSPI_SS, HIGH); // Slave gesperrt

  Serial.begin(115200);
  delay(2000);
  Serial.println("Starting");

  if (!myEncoderObject.begin()) {
    Serial.println("Encoder Failed to Start. Check pin assignments and available interrupts. Aborting.");
    while (1) {
      yield();
    }
  } else {
    // store values of currentValue and EncoderClick into variable myEncState
    myEncoderObject.getState(myEncState);
    Serial.print("Encoder Successfully Started at value = ");
    prevEncoderValue = myEncState.currentValue;
    Serial.println(prevEncoderValue);
  }
}

void loop() {
  if (TasterGedrueckt) {
    TasterGedrueckt = false; // auf false setzen damit die Ausgabe nur einmal pro Tastendruck erfolgt
    Serial.println("Button gedrückt.");
  }

  NewEncoder::EncoderState myCurrentEncoderState;

  // store actual values into variable myCurrentEncoderState
  if (myEncoderObject.getState(myCurrentEncoderState)) {
    Serial.print("Encoder: ");
    currentValue = myCurrentEncoderState.currentValue;

    // if currentValue has REALLY changed print new currentValue
    if (currentValue != prevEncoderValue) {
      Serial.println(currentValue);
      prevEncoderValue = currentValue;

      poti_value = prevEncoderValue;
      WRITE_POTI(ADR_BITS, poti_value, 10); // 10-Bit-Datenwort für die Wiper-Einstellung an Digitalpoti senden



      // if currentValue stayed the same because the number is at upper/lower limit
      // check if encoder was rotated by using the UpClick / DownClick-values
    } else
      switch (myCurrentEncoderState.currentClick) {
        case NewEncoder::UpClick:
          Serial.println("Obere Einstellgrenze erreicht");
          break;

        case NewEncoder::DownClick:
          Serial.println("Untere Einstellgrenze erreicht.");
          break;

        default:
          break;
      }
  }
}
void Interrupt() // Beginn des Interrupts. Wenn der Rotary Knopf betätigt wird, springt das Programm automatisch an diese Stelle. Nachdem...
{
  static unsigned long last_interrupt_time = 0;
  unsigned long interrupt_time = millis();
  // If interrupts come faster than 200ms, assume it's a bounce and ignore
  if (interrupt_time - last_interrupt_time > 200)
  {
    //Serial.println("Button gedrückt.");
    TasterGedrueckt = true;
  }
  last_interrupt_time = interrupt_time;
}

vgs

Der Tastendruck kann auch innerhalb von loop() durch "pollen" abgefragt werden. Ob es mit pollen gut funktioniert hängt vom Gesamtprogramm ab.

Meine Meinung: Wenn der Zahlenbereich nur bis 255 geht dann lohnt sich umstellen auf 20er-Schritte nicht.
Da bist du länger mit Umschalten beschäftigt als mit schnell am Encoder drehen.
Umschalten auf 10er reicht da.

1 Like

Danke für diese Info. Der serial Print ist erstmal nur ein Platzhalter.

Im Endeffekt soll das Programm einen digitalen Widerstand ändern. Durch drücken sollen die Widerstandswerte in einem anderen verstellbereich geändert werden.

Eingestellt werden soll eine Spannung von 1,25-5v. Geplant war eine Verstellung im
0.01v schritten (standart) , 0,1v schritten und 0,5 schritten. Über den vierten Tastendruck sollte wieder auf die Standart Einstellung von 0,01v zurück gesetzt werden

Über einen weiteren Taster sollen 5 voll direkt eingestellt werden können.

Da weis ich jetzt nicht ob der interrupt Sinn macht oder für diese Zwecke nicht notwendig ist

Wenn du meinst in 10er Schritten würde reichen ist ja auch ok.

Interessant. Unter bestimmten Vorraussetzungen kann man das auch einfacher haben als mit
digitalem Widerstand.

Wenn die Masseleitung vom Arduino mit der Masseleitung wo die 1,25V-5V "eingespeist" werden sollen verbunden sein darf, dann geht das entweder direkt per PWM und RC-Glied als DAC oder du nimmst gleich einen 12-16bit DAC-chip dafür.

Wenn du eine galvanische Trennung brauchst (= elektrisch voneinander getrennt) dann macht das mit dem digitalen Widerstand Sinn. Solche digitalen Widerstände können meistens nur ganz kleine Ströme ab 5-20 mA. Kommst du damit hin?

Am besten wäre ja du würdest mal das Gesamtprojekt beschreiben.

vgs

Naja, 10/ 20 sind vielleicht ein wenig viel, wenn 255 als Grenze dient.
Leider hab ich das zu spät gesehen - aber ich werf meinen mal trotzdem in den Ring.

Die Zeile 5 sind Deine 3 Pins - Die musste ändern / der letzte ist der Button - Der Rest wird komplett auf dem SerMon ausgegeben.

// Forensketch Drehencoder Wertebereich begrenzen
// Zusatzfunktion Stellwert ändern
// https://forum.arduino.cc/t/drehimpulsgeber-ky-040/992947/13

#include <rotary.h> //https://github.com/CarlosSiles67/Rotary
Rotary r = Rotary(45, 43, 41);

uint16_t zahl, alteZahl;
const uint8_t stepVal = 5;
uint8_t switchStep = 0;

void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start..."));
  Serial.println(zahl);
}

void loop()
{
  if (r.buttonPressedReleased(20))
  {
    switchStep++;
    if (switchStep > 4) switchStep = 0;
    Serial.print(F("Multiplikator: "));
    Serial.println(switchStep);
  }
  setupZahl(zahl, 0, 255, true); // zu ändernde Zahl, minimal, maximal, umlauf oder Ende
  ausgabe();
}
//
void ausgabe()
{
  if (zahl != alteZahl)
  {
    Serial.println(zahl);
    alteZahl = zahl;
  }
}
//
void setupZahl(uint16_t &aenderZahl, const uint32_t &minZahl, const uint32_t &maxZahl, const bool umlauf)
{
  if (aenderZahl < minZahl) aenderZahl = minZahl;
  if (aenderZahl > maxZahl) aenderZahl = maxZahl;
  int16_t myZahl = aenderZahl;             // lokale Berechnung
  unsigned char val = r.process();         // encoder auslesen
  if (val == r.clockwise())                // auf zaehlen
  {
    if (switchStep)                        // Wenn step != 0
      myZahl += switchStep * stepVal;
    else myZahl++;                         // sonst +1
    if (umlauf)                            // Wenn Überlauf
    {if (myZahl > maxZahl) myZahl = minZahl;}
    else                                   // Wenn Begrenzung
    {if (myZahl > maxZahl) myZahl = maxZahl;}
  }
  if (val == r.counterClockwise())         // ab zaehlen
  {
    switchStep ?                           // Multiplikator aktiv?
    myZahl -= switchStep * stepVal :       // dann damit rechnen
    myZahl--;                              // sonst nicht
    if (myZahl < minZahl ||
        myZahl < 0)                        // Wenn kleinstmögliche Zahl schon erreicht
      if (umlauf) myZahl = maxZahl;
      else myZahl = minZahl;
  }
  aenderZahl = myZahl;
}

Ausgabe

19:41:45.194 -> Start...
19:41:45.194 -> 0
19:41:47.745 -> 1
19:41:48.043 -> 2
19:41:48.242 -> 3
19:41:48.441 -> 4
19:41:48.805 -> 5
19:41:50.130 -> 6
19:41:50.727 -> 7
19:41:51.621 -> Multiplikator: 1
19:41:52.583 -> 2
19:41:53.311 -> 255
19:41:54.471 -> 250
19:41:55.232 -> 245
19:41:55.928 -> 240
19:41:56.823 -> 235
19:41:58.611 -> Multiplikator: 2
19:41:59.738 -> 245
19:42:00.334 -> 255
19:42:01.559 -> 0
19:42:02.487 -> 10
19:42:03.348 -> 20
19:42:04.607 -> Multiplikator: 3
19:42:05.468 -> 5
19:42:06.363 -> 255
19:42:07.390 -> 240
19:42:08.152 -> 225
19:42:08.948 -> Multiplikator: 4
19:42:10.406 -> 245
19:42:11.565 -> 0
19:42:12.625 -> Multiplikator: 0
19:42:13.354 -> 1
19:42:13.851 -> 2
19:42:14.349 -> 3
19:42:14.978 -> Multiplikator: 1
19:42:15.744 -> 255
19:42:16.241 -> 250
19:42:16.838 -> 245
1 Like

Wir wollen in einem Schulprojekt ein vorhandenes Netzteil umändern. Ursprünglich soll die Spannung über eine Spannungsteilerschaltung mit Festwiderständen eingestellt werden.

Diese sollen durch das digitale Potentiometer ersetzt werden. Am Ende soll eine maximale Spannung von 5V mit einem maximalen Strom von 2A ausgeben werden können.

das Programm von dir sieht auch ganz gut aus @my_xy_projekt . Jedoch habe ich da das Problem, das ich beim klicken immer einen Multiplikator überspringe. Zudem muss ich da sehr fein an der Einstellung drehen. Bei dem Programm von Stefan kann ich die Werte einzeln über jede Rasteinstellung ändern.

Die Werte sollen auch nach Möglichkeit nicht überlaufen, also müssten wie im Programm von Stefan an den Endwerten begrenzt werden und durch Drehung in entgegengesetzte Richtung soll der Wert sich sofort wieder ändern.

Steht in meinem Code drin, wie Du das verhinderst.

Wenn Du da ein false drin schreibst....

Dann kannst Du die DeBouncetime höher setzen.

Mach da mal eine 50 rein.

Was heisst das? Mit jeder Rastung bekommst Du einen Wert höher gestellt.

1 Like

wenn ich einmal drehe und die nächste Rastung merke habe ich schon einen Schritt übersprungen.

In dem Programm von Stefan ist das nicht der Fall. ich wüsste jetzt aber nicht woran es liegt

Dann...
im Lib-Verzeichnis Rotary suche nach der rotary.h
Dort ist eine Zeile drin, die lautet:

// Enable this to emit codes twice per step.
#define HALF_STEP

Diese auskommentieren.

Und wenn Du für den Button keinen aufgelöteten Pullup hast (Also nur 2 auf der Platine), dann darunter

// Enable weak pullups
// #define ENABLE_PULLUPS

die define-Zeile einkommentieren.

1 Like

Super, danke das funktioniert jetzt soweit :slight_smile:

@StefanL38
Dein Vorschlag passt soweit auch. Wenn ich den Taster drücke, springt er in die Interrupt Funktion. Da müsste ich nur notfalls anpassen, das dort mit anderen Werten gerechnet wird. Ähnlich dem Beispiel von @my_xy_projekt

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.