Drehimpulsgeber Entprellen mit Bounce2.h und Chattering

Guten Tag,
für ein Projekt möchte ich einen Drehimpulsgeber zum Steuern verwenden, dies habe ich auch beinahe geschafft, nur das er mir immer um 2 hoch- bzw. runterzählt, jetzt wollte ich das ganze mit der Bounce2 Bibliothek entprellen, aber jetzt Zählt er nur noch runter Automatisch, auch würde es mich interessieren ob man das Chattering auch Softwareseitig verhindern kann.
Bei dem Drehimpulsgeber handelt es sich um den STEC11B09 auf Reichelt.
Einmal der Code ohne Bounce2:

volatile int Zaehler = 0;
void setup (){
  Serial.begin(9600);
  pinMode(2, INPUT);
  pinMode(3, INPUT);
  attachInterrupt(digitalPinToInterrupt(2), Encoder_Interrupt, CHANGE);
}
void loop(){
  Serial.println(Zaehler,DEC);
  delay(250);
}
void Encoder_Interrupt(){
  if(digitalRead(2) != digitalRead(3))
  Zaehler++;
  else
  
  Zaehler--;
}

und einmal mit:

#include <Bounce2.h>

volatile int Zaehler = 0;
const int Minus = 2;
const int Plus = 3;
Bounce myButton1 = Bounce();
Bounce myButton2 = Bounce();
void setup (){
  Serial.begin(115200);
  pinMode(2, INPUT);
  pinMode(3, INPUT);
  
 myButton1.attach(Minus);
 myButton2.attach (Plus);
 myButton1.interval(2);
 myButton2.interval(2);
 
}
void loop(){
  myButton1.update();
  myButton2.update();
  if (myButton1.read() != myButton2.read()){
  Zaehler++;}
  else {Zaehler--;}
  Serial.println(Zaehler,DEC);

}

Es fehlt die Abfrage, ob sich myButton1 geändert hat.

Wie würde ich das hinbekommen, habe myButton.pressed und myButton.read == HIGH/LOW bereits ausprobiert?

Versuch mal
nicht getestet

if (myButton1.read() && !myButton2.read()){
  Zaehler++;}

if (myButton1.read() && myButton2.read()){
  Zaehler--;} 

Heinz

Leider nein, er zählt immer noch Automatisch nach Unten in den Minusbereich.

Vielleicht einfach nach dem StateChangeDetection Beispiel in der IDE, ohne Bibliotheken?

Oder den vorherigen Zustand merken?

Ich möchte mal was anderes in den Raum werfen. Warum quälst Du Dich das selbst machen zu wollen? Ich habe hier mal mit einem Zähler gespielt.
Die lib selbst bringt ein minimalbeispiel mit, bei dem die Drehrichtung ausgegeben wird.
Wenn Du da einfach nur auf und ab zählst....

Hallo,
jetzt hab ich das doch mal getestet und muss mich korregieren, hab mir noch mal die lib angesehen.
Man muss natürlich eine andere Methode der Bounce2 lib nutzen. Man sollte nur dann den Zähler ändern wenn sich der Zustand einer Spur geändert hat (Flanke). Dazu bietet sich die Methode fell an . Wenn eine Spur den Zustand wechselt wird das mit dem aktuellen Zustand der zweiten Spur genutzt um auf oder ab zu zählen.
Zudem kommt jetzt noch hinzu wie Du den Geber angeschlossen hast. Wird gegen plus oder minus geschaltet. Entsprechend muss halt wie immer ein externer Pulldown oder der interne Pullup vorhanden sein.
ich habe da so einen Geber darauf sind zusätzliche Pulldown vorhanden.
Basierend auf Deinem Sketch. Das läuft bei mir so.

#include <Bounce2.h>

int Zaehler = 0;
const int A = 2;// Spur A
const int B = 3;// Spur B 
Bounce myButton1 = Bounce();
Bounce myButton2 = Bounce();
void setup (){
  Serial.begin(115200);
  pinMode(A, INPUT);
  pinMode(B, INPUT);
  
 myButton1.attach(A);
 myButton2.attach (B);
 myButton1.interval(2);
 myButton2.interval(2);
 
}
void loop(){
  myButton1.update();
  myButton2.update();
  
  if (myButton1.fell()&& !myButton2.read()){
  Zaehler++;
  }
if (myButton1.fell() && myButton2.read()){
  Zaehler--;
  }
  
  Serial.println(Zaehler);

}

Heinz

Manchmal frage ich mich: "Was mache ich falsch?"

Denn, mein Decoder braucht weder Interrupts, noch Entprellungen oder gar Flankenerkennungen.

#include <CombiePin.h>
/*

   Vorbereitet um einen Drehencoder HW-040 direkt 
   in die Pins 3 bis 7 eines UNO stecken zu können
  
 */


using DekoderTabelle = const int8_t[16];
DekoderTabelle  einPhasenwechselProRastpunkt  = {0, 1,-1, 0,-1, 0, 0, 1, 1, 0, 0,-1, 0,-1, 1, 0}; 
DekoderTabelle zweiPhasenwechselProRastpunkt  = {0, 0,-1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,-1, 0, 0};
DekoderTabelle vierPhasenwechselProRastpunkt  = {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,-1, 0, 0};



template< typename PhaseA, typename PhaseB, typename T>
class DrehEncoder
{
  public:
  using CallBack = void(*)(T);
  
  private:
  const DekoderTabelle &tabelle;
  T count;        // Aktuelle Drehencoder Stellung
  int8_t index;    // Dekoder Tabellen Index Merker
  CallBack callback;

  public:
  DrehEncoder(const DekoderTabelle &tabelle):tabelle(tabelle),count(0),index(0),callback(nullptr){}

  void onChange(CallBack callback)
  {
    this->callback = callback;
  }
  
  void init()
  {
    PhaseA{}.initPullup();
    PhaseB{}.initPullup();
  }


  operator T() {return count;}

  void run()
  {
    index <<= 2;
    index |= PhaseA{};
    index |= PhaseB{} << 1;
    index &= 0x0F;
    count += tabelle[index];  
    if(callback && tabelle[index]) callback(count); 
  }
};



using DrehEncoderType = DrehEncoder<Combie::Pin::InputPin<7>,Combie::Pin::InputPin<6>,long>;
//using DrehEncoderType = DrehEncoder<Combie::Pin::InvInputPin<7>,Combie::Pin::InvInputPin<6>,long>;

//DrehEncoderType drehEncoder(vierPhasenwechselProRastpunkt);
DrehEncoderType drehEncoder(zweiPhasenwechselProRastpunkt);
//DrehEncoderType drehEncoder(einPhasenwechselProRastpunkt);


void setup() 
{
  Serial.begin(9600);
  Serial.println("Start");
  drehEncoder.init();
  drehEncoder.onChange([](long count) {Serial.println(count);});
  
  pinMode(3,OUTPUT); // GND für Encoder
  pinMode(4,OUTPUT); // Vcc für Encoder
  digitalWrite(4,1);
}

void loop() 
{
 drehEncoder.run();
}

CombiePin.zip (309,3 KB)

Nein Du machst nichts falsch. Mir ging es darum dem T0 zu zeigen was er an seinem Sketch falsch gemacht hat.
Gruß Heinz

Hallo,

Diesmal wohl etwas. Der Code prellt bzw. wertet unzuverlässig aus. Kann man mit jeden billigen Alps aus der Krabbelkiste provozieren. Ganz ehrlich.

3 verschiedene Sorten habe ich hier.
Keiner davon zappelt, zählt falsch, oder macht sonst komische Sachen.
Allerdings muss ich auch bei keinem von denen die einPhasenwechselProRastpunkt Tabelle nutzen.

Hallo,

mag ja alles sein, dein Code funktioniert nur nicht allgemein gültig für jeden Encoder. Also wundere dich nicht wenn man abseits davon mehr Aufwand betreiben muss.

Um das abzurunden. Bisher war der Code von Peter Dannegger die Referenz. Hatte aber auch sehr sehr sehr selten ein Zucker beim Flankenübergang auf der Rastung. Irgendwann hat Uwe Kolz sein Code vorgestellt und der ist das Beste was ich gesehen habe. Da zuckt und springt nichts mehr bei mir. Damit kann ich auch langsam auf der Rastnase ohne jedes Problem rumfummeln. neuer Algorithmus from Uwe Kolz

2 Likes

Hallo,

warum löscht du laufend deine Beiträge und schreibst neu? Editiere den einen Beitrag und fertig. Du musst nicht immer löschen und einen neuen absetzen.

1 Like

servus, das Drehen funktioniert nun.

#include <Bounce2.h>


Bounce2::Button MinusButton = Bounce2::Button();
Bounce2::Button PlusButton = Bounce2::Button();
int Minus = 2;
int Plus = 3;
int Zaehler = 0;
int MinusLast = LOW;
int MinusNow = LOW;

void setup() {
MinusButton.attach(Minus, INPUT_PULLUP);
PlusButton.attach (Plus, INPUT_PULLUP);
MinusButton.interval (0.5);
PlusButton.interval (0.5);
Serial.begin (115200);
}

void loop() {
  MinusButton.update();
  PlusButton.update();
  MinusNow = MinusButton.read();
  if ((MinusLast == HIGH) && (MinusNow == LOW)) {
    if (PlusButton.read() == HIGH) {
      Zaehler+=10;

    } else {
      Zaehler-=10;

    }
  }
    Serial.println(Zaehler);
  MinusLast = MinusNow;}

Jetzt wollte ich das ganze in mein Hauptprogramm einfügen, im Loop direkt funktioert es ohne Probleme, in den Voids EInHz bis HundertkHz in des eigentlich sein sollte Zählt er nur noch alle 3-4 Umdrehungen einmal Hoch (Der Code ist etwas umständlich, aber bis auf den Drehregler funktioniert alles).

 //Wichtig: Bei den Berechnungen wird alles mit Hertz gerechnet, 1kHz = 1000Hz, 1MHz = 1.000.000Hz!!!
//Die Umwandlung der Werte von Hertz in Kilohertz erfolgt im Void KHertz()

//Eingebundene Bibliotheken
#include <LiquidCrystal_I2C.h> 
#include <Wire.h>
#include <Bounce2.h>
#include <MD_AD9833.h>
#include <MD_AD9833_lib.h>
#include <math.h>

LiquidCrystal_I2C lcd(0x27, 20, 4); //Initialiesierung des Displays, Hex Adresse 0x27, 4 Zeilen mit je 20 Zeichen
Bounce2::Button VerlaufButton = Bounce2::Button();
Bounce2::Button WertMinusButton = Bounce2::Button();
Bounce2::Button WertPlusButton = Bounce2::Button();
Bounce2::Button MinusButton = Bounce2::Button();
Bounce2::Button PlusButton = Bounce2::Button();
//Definition der Einzelnen Knöpfe (selbstvergebener Name und zugehöriger Arduinopin)
const int VerlaufKnopf = 5;
const int WertMinusKnopf = 4;
const int WertPlusKnopf = 6;
const int Minus = 2;
const int Plus = 3;
const int Data = 11;
const int Clock = 13; 
const int FSync = 8;
//Definition des Intervals für die Bounce2 Bibliothek
const int Interval = 2;
//Merker 
int Tastercounter = 0;
int Textstatus = 0;
long Zaehler = 0;
int Kilo = 0;
int CaseMerker = 0; //Gibt den derzeitigen Case an
int Case = 0; //Speichert den derzeitigen Bildschirm
int CaseTasterMerker = 0;
int MinusMerker = 0;
int ClearMerker = 0;
int SchrittMerker = 0;
int AutoNullMerker = 0;
int AutoNullAD9833 = 0;
float Frequenzeinstellung = 100;
int Start = 0;
int Hauptfrequenz = 0;
int Welleneinstellung = 0;
int MinusDruckZeit = 5000; //Einstellung der Zeit solange der MinusButton mindestens gedrückt sein muss, für die AutoNull-Funktion, in dem Falle  mindestens 5 Sekunden
unsigned long ZeitstatusMerker;
unsigned long ModulFrequenz;
long Vorzeit;
int ZeitMinusMerker = 0;
int EncoderWert = 0; 
volatile byte MinusLast = LOW;
volatile byte MinusNow = LOW;
int InterMerker = 0;
MD_AD9833 AD (FSync);
//Erstellen der unterschiedlichen Zeichen
byte Sinuswelle[8] ={ //Benötigt zum Darstellen der Sinuswelle
B00010,
B00100,
B01000,
B00100,
B00010,
B000100,
B01000,
};
byte Dreiecksymbol[8] = { //Benötigt zum Darstellen des Dreiecks Links
B00010,
B00101,
B01001,
B10001,
B01001,
B00101,
B00010,
};
byte Dreiecksymbol2 [8] = { //Benötigt zum Darstellen des Dreiecks Rechts
B01000,
B10100,
B10010,
B10001,
B10010,
B10100,
B01000,
};
byte Rechteckwelle [8] = { //Benötigt zum Darstellen des Rechtecks Links
B10000,
B11111,
B00001,
B00001,
B00001,
B11111,
B10000,
};
byte Rechteckwelle2 [8] = { //Benötigt zum Darstellen des Rechtecks Rechts
B00001,
B11111,
B10000,
B10000,
B10000,
B11111,
B00001,
};
void setup() {
 Serial.begin(115200);
//Einstellung des AD9833
AD.begin();  
AD.setMode(MD_AD9833::MODE_OFF);
//Zuweisung der Taster und Entprellen und Zuweisen des Zustandes bei Drücken

VerlaufButton.attach (VerlaufKnopf, INPUT);
WertPlusButton.attach (WertPlusKnopf, INPUT);
WertMinusButton.attach (WertMinusKnopf, INPUT);
MinusButton.attach (Minus, INPUT_PULLUP);
PlusButton.attach (Plus, INPUT_PULLUP);
VerlaufButton.interval (Interval);
WertPlusButton.interval (Interval);
WertMinusButton.interval (Interval);
MinusButton.interval (1);
PlusButton.interval (1);

VerlaufButton.setPressedState(HIGH);
WertPlusButton.setPressedState(HIGH);
WertMinusButton.setPressedState(HIGH);
//Ansteuerung des Displays
lcd.init();
lcd.backlight();
lcd.noCursor();
lcd.clear();
//Einstellung des Starttext, wird solange angezeigt, bis via VerlaufButton in den Sinusbereich gewechselt wird.
lcd.setCursor(2,0); //Es wird immer erst das Zeichen, dann die Zeile genannt, hier werden 2 Zeichen freigehalten, geschrieben wird in das 3 Zeichen und 0 Zeilen, beginn des Schreibens in der 1ten Zeile
lcd.print("TEST");
lcd.setCursor(4,1); //Zeichen, Zeile
lcd.print("TEST");
lcd.setCursor(2,2);
lcd.print("TEST");
//Ende der Einstellung des Starttextes
//Kreieren der einzelnen Symbole um sie via lcd.write() Befehl einzufügen
lcd.createChar(1, Sinuswelle);
lcd.createChar(2, Dreiecksymbol); //Dreieck Links
lcd.createChar(3, Dreiecksymbol2); //Dreieck Rechts
lcd.createChar(4, Rechteckwelle); //Rechteck Links
lcd.createChar(5, Rechteckwelle2); //Rechteck Rechts
//Ende kreieren der Symbole

}

void loop() { //Alle hinterhinterlegten Voids sind im Loop
  MinusButton.update();
  PlusButton.update();
  MinusNow = MinusButton.read();
  if ((MinusLast == HIGH) && (MinusNow == LOW)) {
    if (PlusButton.read() == HIGH) {
      Zaehler+=10;
      Frequenzeinstellung = Frequenzeinstellung + 10;
    } else {
      Zaehler-=10;
      Frequenzeinstellung = Frequenzeinstellung - 10;
    }
  }
    Serial.println(Zaehler);
  MinusLast = MinusNow;
Sperrung();
Text();
Taster();
StoppZahl();
Casetaster();
Casewechsel();
Welle();
AutoNull();
}
void Sperrung(){ //Sperrt alles über bzw. unter bestimmten Frequenzen
 if (Zaehler <= 100){ //Sperrt im Hertzbereich alles unter 0Hz
Zaehler = 100; 
}
if (Frequenzeinstellung <= 100){ //Sperrt im Hertzbereich alles unter 0Hz
Frequenzeinstellung = 100; 
}

if (Zaehler >= 1000000){ //Sperrt im Hertzbereich alles über 1MHz
Zaehler = 1000000;}
if (Frequenzeinstellung >= 1000000){ //Sperrt im Hertzbereich alles über 1MHz
Frequenzeinstellung = 1000000;} 
}
void Taster(){ //Tastendruckbedingung und Entprellung für den Wechsel der einzelnen Wellenarten.

if (VerlaufButton.update()){
if (VerlaufButton.pressed()){
Tastercounter++;
}
}
if (Tastercounter > 3){
Tastercounter = 1;
}

if(VerlaufButton.pressed()&& Tastercounter == 1  || Tastercounter == 1){Sinus();} //Wechselt zum Sinusbereich des Progammes
else if (VerlaufButton.pressed()&& Tastercounter == 2 || Tastercounter == 2){Dreieck();} // Wechselt zum Dreieckbereich des Progammes
else if (VerlaufButton.pressed()&& Tastercounter == 3 || Tastercounter == 3){Rechteck();} // Wechselt zum Rechteckbereich des Progammes
}

void Text (){ //Regelt ob die Hertz oder Kilohertz oder Megahertz Anzeige verwendet wird

if (Textstatus < 1){
Textstatus = 1;
}
else if (Textstatus > 3){
Textstatus = 3;
}
if (Frequenzeinstellung == 100){
Textstatus = 1;
}
if (Frequenzeinstellung >= 1000 && Textstatus == 1){
Textstatus = 2;
}
if (Frequenzeinstellung < 1000){
Textstatus = 1;
}
if (Frequenzeinstellung >= 1000000 && Textstatus == 2){
Textstatus = 3;
}

if ((Tastercounter == 1 || Tastercounter == 2 || Tastercounter == 3) && Textstatus == 1) {Hertz();}
else if ((Tastercounter == 1 || Tastercounter == 2 || Tastercounter == 3) && Textstatus == 2) {KHertz();}
else if ((Tastercounter == 1 || Tastercounter == 2 || Tastercounter == 3) && Textstatus == 3) {MHertz();}}

void StoppZahl(){ //Regelt das nie ein Wert unter 1Hz und über 1 Mhz angezeigt wird

if (Zaehler >= 1000){ // Springt ab 1kHz in den kHz Bereich
Textstatus = 2;
}

if (Zaehler < 1000){ //Wechsel von kHz in Hz sobald Wert unter 1000
Textstatus = 1;
}
if (Zaehler >= 1000000){ // Springt ab 1MHz in den MHz Bereich
Textstatus = 3;
}
}

void Casetaster(){ //Regelt den derzeitigen CaseMerker, dass dieser nicht unter 0 und nicht über 3 geht
if (WertMinusButton.update()){
if (WertMinusButton.pressed() && (Tastercounter == 1 || Tastercounter == 2 || Tastercounter == 3)){
CaseTasterMerker--;}}
if (WertPlusButton.update()){
if (WertPlusButton.pressed() && (Tastercounter == 1 || Tastercounter == 2 || Tastercounter == 3)){
CaseTasterMerker++;
}}
if (CaseTasterMerker <= 0){
CaseTasterMerker = 0;
}
else if (CaseTasterMerker > 6){
CaseTasterMerker = 6;
}}

void Casewechsel(){ //Wechselt zwischen den Caseses für Plus und Minus 
if  (Tastercounter == 1 || Tastercounter == 2 || Tastercounter == 3){
switch (CaseTasterMerker){
case 0:
EinHz(); //1Hz Plus oder Minus 
break;
case 1:
ZehnHz(); //10Hz Plus oder Minus 
break;
case 2:
HundertHz(); //100Hz Plus oder Minus 
break;
case 3:
EinkHz(); //1kHz Plus oder Minus 
break;
case 4:
ZehnkHz(); //10kHz Plus oder Minus 
break;
case 5:
HundertkHz(); //100kHz Plus oder Minus 
break;
}}}

void EinHz(){ //Springt immer 1Hz
 

  


lcd.setCursor(4,2);
lcd.print("Schritt: 1Hz    ");
}
void ZehnHz(){ //Springt immer 10Hz
if (MinusButton.update()){
if (MinusButton.pressed() && Zaehler >= 115 && Frequenzeinstellung >= 115){
Zaehler -= 10;
Frequenzeinstellung = Frequenzeinstellung - 10;}
else if  (MinusButton.pressed()){
CaseTasterMerker = 0;

}}

if (PlusButton.update()){
if (PlusButton.pressed()){
Zaehler += 10;
Frequenzeinstellung = Frequenzeinstellung + 10;
}}
lcd.setCursor(4,2);
lcd.print("Schritt: 10Hz   ");
}

void HundertHz(){ //Springt immer 100HZ

if (MinusButton.update()){
if (MinusButton.pressed() && Zaehler >= 200 && Frequenzeinstellung >= 200){
Zaehler -= 100;
Frequenzeinstellung = Frequenzeinstellung - 100;}
 else if  (MinusButton.pressed()){
CaseTasterMerker = 1;

}}
if (PlusButton.update()){
if (PlusButton.pressed()){
Zaehler += 100;
Frequenzeinstellung = Frequenzeinstellung + 100;
}}
lcd.setCursor(4,2);
lcd.print("Schritt: 100Hz   ");
}

void EinkHz(){ //Springt 1kHz nach oben und solange nach unten bis der Zaehlerwert 1000 erreicht
if (MinusButton.update()){
if (MinusButton.pressed() && Zaehler >= 2000 && Frequenzeinstellung >= 2000){
Zaehler -= 1000;
Frequenzeinstellung = Frequenzeinstellung - 1000;}
else if  (MinusButton.pressed()){
CaseTasterMerker = 2;
}}
if (PlusButton.update()){
if (PlusButton.pressed()){
Zaehler += 1000;
Frequenzeinstellung = Frequenzeinstellung + 1000;
}}
lcd.setCursor(4,2);
lcd.print("Schritt: 1kHz   ");
}

void ZehnkHz(){ //Springt 10kHz nach oben und solange nach unten bis der Zaehlerwert 1000 erreicht
if (MinusButton.update()){
if (MinusButton.pressed() && Zaehler >= 20000 && Frequenzeinstellung >= 20000){
Zaehler -= 10000;
Frequenzeinstellung = Frequenzeinstellung - 10000;}
else if  (MinusButton.pressed()){
CaseTasterMerker = 3;

}}

if (PlusButton.update()){
if (PlusButton.pressed()){
Zaehler += 10000;
Frequenzeinstellung = Frequenzeinstellung + 10000;;
}}
lcd.setCursor(4,2);
lcd.print("Schritt: 10kHz   ");
}

void HundertkHz(){ //Springt 100kHz nach oben und solange nach unten bis der Zaehlerwert 1000 erreicht
if (MinusButton.update()){
if (MinusButton.pressed() && Zaehler >= 200000 && Frequenzeinstellung >= 200000){
Zaehler -= 100000;
Frequenzeinstellung = Frequenzeinstellung - 100000;}
else if  (MinusButton.pressed()){
CaseTasterMerker = 4;

}}
if (PlusButton.update()){
if (PlusButton.pressed()){
Zaehler += 100000;
Frequenzeinstellung = Frequenzeinstellung + 100000;
}}
lcd.setCursor(4,2);
lcd.print("Schritt: 100kHz   ");
}

void AutoNull(){ //Setzt den Zaehler auf Null und die Wellenart auf Sinus zurück sobald der MinusButton länger als 5 Sekunden gedrückt ist
VerlaufButton.update();
if (VerlaufButton.read() == HIGH){
  
if (AutoNullMerker == 0){

Vorzeit = millis();
AutoNullMerker = 1;
}
ZeitstatusMerker = millis();

if (ZeitstatusMerker - Vorzeit >= MinusDruckZeit){
Zaehler = 100;
Frequenzeinstellung = 100;
CaseTasterMerker = 0;
Tastercounter = 1;
AD.setFrequency(0, Frequenzeinstellung);
AD.setMode(MD_AD9833::MODE_SINE);
}
}
else { AutoNullMerker = 0;}
}

void Welle(){ //Einstellung der Wellenform des AD9833
if ((VerlaufButton.pressed() || MinusButton.pressed() || PlusButton.pressed()) && (Tastercounter == 1 || Tastercounter == 2 || Tastercounter == 3)){
if (VerlaufButton.pressed ()){
  Welleneinstellung++;
}
if (Welleneinstellung > 3){
Welleneinstellung = 1;
}
if (Welleneinstellung == 1){
AD.setFrequency(0, Frequenzeinstellung); //Start Sinus-Signalausgabe des AD9833 bei einer Frequenz von 100Hz alles unterhalb gibt kein gescheites Signal ab
AD.setMode(MD_AD9833::MODE_SINE);
}
else if (Welleneinstellung == 2){
AD.setFrequency(0, Frequenzeinstellung); //Start Sinus-Signalausgabe des AD9833 bei einer Frequenz von 100Hz alles unterhalb gibt kein gescheites Signal ab
AD.setMode(MD_AD9833::MODE_TRIANGLE);
}
else if (Welleneinstellung == 3){
AD.setFrequency(0, Frequenzeinstellung); //Start Sinus-Signalausgabe des AD9833 bei einer Frequenz von 100Hz alles unterhalb gibt kein gescheites Signal ab
AD.setMode(MD_AD9833::MODE_SQUARE1);
}}}



void Sinus(){ //Display Einstellung für Sinuswelle
ClearMerker++;//Löscht einmalig das gesamte Display
if (ClearMerker == 1){//Löscht einmalig das gesamte Display
lcd.clear();//Löscht einmalig das gesamte Display
}
lcd.setCursor(5,0);
lcd.print(" ");
lcd.setCursor(6,0);
lcd.write(1);
lcd.setCursor(7,0);
lcd.print("Sinus");
lcd.setCursor(12,0);
lcd.write(1);
lcd.setCursor(13,0);
lcd.print("  ");
}




void Dreieck(){ //Display Einstellung für Dreieck
lcd.setCursor(5,0);
lcd.write(2);
lcd.setCursor(6,0);
lcd.print("Dreieck");
lcd.setCursor(13,0);
lcd.write(3);

}
void Rechteck(){ //Display Einstellung für Rechteck
lcd.setCursor(5,0);
lcd.write(4);
lcd.setCursor(6,0);
lcd.print("Rechteck");
lcd.setCursor(14,0);
lcd.write(5);


}
void Hertz(){ //Displayeinstellung für Hz
lcd.setCursor (4,1);
lcd.print("f=");
lcd.print (Zaehler);
lcd.print("Hz       ");
}
void KHertz(){ //Dislayeinstellung für kHz
lcd.setCursor (4,1);
lcd.print("f=");
lcd.print (Zaehler/1000.00); //Wert des Zähler geteilt durch 1.000 für um diesen in kHz umzurechnen
lcd.print("kHz    ");
}
void MHertz(){ //Dislayeinstellung für kHz
lcd.setCursor (4,1);
lcd.print("f=");
lcd.print (Zaehler/1000000.00); //Wert des Zähler geteilt durch 1.000 für um diesen in kHz umzurechnen
lcd.print("MHz    ");
}

Tschuldige wusste nicht dass geht, wird sich aber gemerkt

Hallo,

mit dem Stiftsymbol kann man jederzeit sinnvoll editieren. Missbrauchen sollte man das allerdings nicht. Wenn jemand geantwortet hat sollte man nichts mehr ändern. Außer vielleicht es fallen einem Rechtschreibfehler ins Auge. Nur inhaltliche Änderungen wären nachträglich dann blöd. Ansonsten kann man jederzeit maßvoll Änderungen vornehmen. Und auch wenn es gelöscht ist, kann jeder den alten Inhalt lesen. Also richtig gelöscht ist es nie. Soviel zur Info zum Text verfassen.

Jetzt schaue ich mir deinen Sketch mal an ...

1 Like

Danke für die Info, dass mit dem Löschen wusste ich z.B nicht, ich dachte dannach ist es für alle weg, werde es mir aber merken und beim nächstenmal nur noch editieren.

Hallo,

ich kann keine Auswertung nach dem Drehencoder Prinzip erkennen. Du hast praktisch nur 2 Tasten plus und minus erstellt

MinusButton.update();
PlusButton.update();

die du unterschiedlich behandelst. Bounce2 macht nur Tastenentprellung hat aber keine Encoderauswertung an Bord.
Das Encoder Hauptprinzip beruht darauf das man die beiden Signale zeitgleich einliest und zwar immer zeitgleich bzw. direkt hintereinander. Du machst das jedoch im großen Sketch zu Begin der loop, was okay ist und dann leider vereinzelt in den Funktionen. Das muss zu Problemen führen. Das ginge so nur wenn du wirklich nur 2 reine Taster für +/- Änderung hast. Wenn du einen Handdrehencoder hast funktioniert das nicht. Weil sich immer beide Phasensignale beim drehen verändern die immer gemeinsam ausgewertet werden müssen.

Man benötigt eine Funktion die den Encoder auswertet und der Rest vom Sketch arbeitet nur mit dem Ergebnis des Zählers. Und diese Funktion der Encoderauswertung muss oft genug aufgerufen werden können. Man sagt aller 1ms. Wenn man normal von Hand dreht funktionieren auch 2-3ms. Dreht man jedoch schnell sind aller 1ms schon erforderlich. Das heißt deine loop muss in 1ms durchlaufen sein. Wenn ich das richtig überblicke sollte das bei dir so sein, solange die seriellen Ausgaben nicht zu viel werden. Das heißt du benötigst aktuell eine Encoderauswertefunktion die oft genug an einer Stelle aufgerufen wird.

Hier stehen die Grundlagen zum Verstehen warum wieso weshalb. Das was ich als Referenz bezeichnet habe. Artikel Drehgeber von Peter Sollte man einmal komplett durchlesen. Weil nach dem einlesen beider Signale müssen diese auch ausgewertet werden damit richtig gezählt wird.

Servus,
ich hätte vielleicht dazu schreiben sollen das ich das Programm anfangs für reine Taster für +/- programmiert habe, ohne Drehimpulsgeber, die Idee mit der eigenen Funktion werde ich Versuchen. Die Seriellen Ausgaben sind nur für mich zum Überprüfen und werden am Ende sobald alles Funktioniert wieder gelöscht.