Verschiedene Encoder in einem Projekt (half step / full step)

Hallo zusammen,

mein Name ist Andreas, ich bin 44 Jahre alt, relativ neu in dem Thema Arduino und C++ und dies ist mein erster Beitrag in diesem Forum.

Ich habe ein Projekt realisiert, in welchem diverse Buttons, Head Switches und Encoder mithilfe eines Arduino Pro Micro und zweier Adafruit MCP23017 ausgelesen und dann via Joystick Bibliothek als Gamecontroller an den PC ausgegeben werden.

Anfangs habe ich mich mit Copy & Paste und ChatGPT durchgehangelt und nach und nach auch so ziemlich alles verstanden, was der Sketch so macht, so konnte ich noch einiges optimieren, allerdings bin ich jetzt bei einer Kleinigkeit an meine Grenzen gestossen und auch die Suche im Netz und hier im Forum bringt mich leider nicht weiter, also frage ich hier mal ganz dumm:

Ich habe in meinem Projekt zwei Alps-Alpine RKJXT1F42001 und zwei billige China Encoder, welche dem KY-040 entsprechen, verwendet. Der RKJXT1F42001 ist ein 7-Wege Multi-Switch, der vier Richtungen, eine Push-Funktion, sowie einen Drehencoder vereint. Mein Problem ist nun, dass wenn ich den Sketch im Half-Step-Modus laufen lasse, zwar die Encoder der RKJXT1F42001 einwandfrei funktionieren, die zwei KY-040 jedoch bei einer Rastung zwei mal auslösen. Kommentiere ich den Half-Step-Modus aus, dann funktionieren die zwei KY-040 einwandfrei, aber die Encoder der RKJXT1F42001 lösen nur bei jeder zweiten Rastung aus.

Die RKJXT1F42001 sind jeweils an den Pins 0 & 1 der MCP23017 angeschlossen, die KY-040 an den Pins 2 & 3.

Gibt es die Möglichkeit, den Sketch so umzuschreiben, dass jeder Encoder in seinem eigenen Step-Modus ausgelesen wird?

Ich habe mal alles andere aus dem Sketch gelöscht und nur die vier Encoder drin gelassen:

#include <Wire.h>
#include <Joystick.h>
#include <Adafruit_MCP23X17.h>

// Konfiguration der Portexpander
Adafruit_MCP23X17 mcp1;
Adafruit_MCP23X17 mcp2;


// Konfiguration der Rotary Encoder
//#define HALF_STEP
#define NUMROTARIES 4

struct rotariesdef {
  byte pin1;
  byte pin2;
  int ccwchar;
  int cwchar;
  volatile unsigned char state;
};

rotariesdef rotaries[NUMROTARIES] {
  {0, 1, 17, 18, 0},
  {2, 3, 21, 22, 0},
  {0, 1, 19, 20, 0},
  {2, 3, 23, 24, 0},
};

#define DIR_CCW 0x10
#define DIR_CW 0x20
#define R_START 0x0

#ifdef HALF_STEP
#define R_CCW_BEGIN 0x1
#define R_CW_BEGIN 0x2
#define R_START_M 0x3
#define R_CW_BEGIN_M 0x4
#define R_CCW_BEGIN_M 0x5

const unsigned char ttable[6][4] = {
  // R_START (00)
  {R_START_M,            R_CW_BEGIN,     R_CCW_BEGIN,  R_START},
  // R_CCW_BEGIN
  {R_START_M | DIR_CCW, R_START,        R_CCW_BEGIN,  R_START},
  // R_CW_BEGIN
  {R_START_M | DIR_CW,  R_CW_BEGIN,     R_START,      R_START},
  // R_START_M (11)
  {R_START_M,            R_CCW_BEGIN_M,  R_CW_BEGIN_M, R_START},
  // R_CW_BEGIN_M
  {R_START_M,            R_START_M,      R_CW_BEGIN_M, R_START | DIR_CW},
  // R_CCW_BEGIN_M
  {R_START_M,            R_CCW_BEGIN_M,  R_START_M,    R_START | DIR_CCW},
};

#else
#define R_CW_FINAL 0x1
#define R_CW_BEGIN 0x2
#define R_CW_NEXT 0x3
#define R_CCW_BEGIN 0x4
#define R_CCW_FINAL 0x5
#define R_CCW_NEXT 0x6

const unsigned char ttable[7][4] = {
  // R_START
  {R_START,    R_CW_BEGIN,  R_CCW_BEGIN, R_START},
  // R_CW_FINAL
  {R_CW_NEXT,  R_START,     R_CW_FINAL,  R_START | DIR_CW},
  // R_CW_BEGIN
  {R_CW_NEXT,  R_CW_BEGIN,  R_START,     R_START},
  // R_CW_NEXT
  {R_CW_NEXT,  R_CW_BEGIN,  R_CW_FINAL,  R_START},
  // R_CCW_BEGIN
  {R_CCW_NEXT, R_START,     R_CCW_BEGIN, R_START},
  // R_CCW_FINAL
  {R_CCW_NEXT, R_CCW_FINAL, R_START,     R_START | DIR_CCW},
  // R_CCW_NEXT
  {R_CCW_NEXT, R_CCW_FINAL, R_CCW_BEGIN, R_START},
};
#endif

// Konfiguration des Joysticks
Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,
                   JOYSTICK_TYPE_JOYSTICK, 25, 2,
                   false, false, false, false, false, false,
                   false, false, false, false, false);

void setup() {

  Serial.begin(115200);

  // Initialisierung der Joystick Bibliothek
  Joystick.begin();

  // Initialisierung des I2C Bus
  Wire.begin();

  // Initialisierung der beiden Port Expander
  mcp1.begin_I2C(0x20);
  mcp2.begin_I2C(0x21);

  // Setzen der Bus-Geschwindigkeit
  Wire.setClock(400000);

  // Konfiguration der Pins des ersten Port Expanders als Inputs
  mcp1.pinMode(0, INPUT_PULLUP);
  mcp1.pinMode(1, INPUT_PULLUP);
  mcp1.pinMode(2, INPUT_PULLUP);
  mcp1.pinMode(3, INPUT_PULLUP);

  // Konfiguration der Pins des zweiten Port Expanders als Inputs
  mcp2.pinMode(0, INPUT_PULLUP);
  mcp2.pinMode(1, INPUT_PULLUP);
  mcp2.pinMode(2, INPUT_PULLUP);
  mcp2.pinMode(3, INPUT_PULLUP);

}

void loop() {

  CheckAllEncoders();

}

// Abfrage der Zustände der Rotary Encoder und Übergabe an den Joystick
unsigned char rotary_process(int _i) {
  unsigned char pinstate = (mcp1.digitalRead(rotaries[_i].pin2) << 1) | mcp1.digitalRead(rotaries[_i].pin1);
  rotaries[_i].state = ttable[rotaries[_i].state & 0xf][pinstate];
  return (rotaries[_i].state & 0x30);
}

unsigned char rotary_process2(int _j) {
  unsigned char pinstate = (mcp2.digitalRead(rotaries[_j].pin2) << 1) | mcp2.digitalRead(rotaries[_j].pin1);
  rotaries[_j].state = ttable[rotaries[_j].state & 0xf][pinstate];
  return (rotaries[_j].state & 0x30);
}

void CheckAllEncoders(void) {
  for (int i = 0; i < 2; i++) {
    unsigned char result = rotary_process(i);
    if (result == DIR_CCW) {
      Joystick.setButton(rotaries[i].ccwchar, 1); delay(50); Joystick.setButton(rotaries[i].ccwchar, 0);
    };
    if (result == DIR_CW) {
      Joystick.setButton(rotaries[i].cwchar, 1); delay(50); Joystick.setButton(rotaries[i].cwchar, 0);
    };
  }

  for (int i = 2; i < 4; i++) {
    unsigned char result = rotary_process2(i);
    if (result == DIR_CCW) {
      Joystick.setButton(rotaries[i].ccwchar, 1); delay(50); Joystick.setButton(rotaries[i].ccwchar, 0);
    };
    if (result == DIR_CW) {
      Joystick.setButton(rotaries[i].cwchar, 1); delay(50); Joystick.setButton(rotaries[i].cwchar, 0);
    };
  }
}


LG
Andreas

Dafür brauchst Du je eine Übergangs-Tabelle für die Step-Modi und verwendest dann für jeden Encoder die passende Tabelle.

Ok, sowas in der Art dachte ich mir schon... nur wie mache ich das?

Zwei Tabellen hast Du doch schon, mit Half-Step und was anderem. Was da genau drinsteht, entzieht sich meinem Verständnis. Meine Tabellen enthalten nur 0, +1 und -1, um wieviel die Position jeweils geändert wird. Danach kommt es drauf an, ob eine oder beide Flanken des Taktsignals ausgewertet werden, oder beide Signale als Taktsignal verwendet werden.

Das macht, außer dem Einlesen der Signale, gerade mal einen Tabellenzugriff und die entsprechende Änderung der Position aus, paßt bequem in eine ISR.

Durch diese ganze Encoder Thematik steige ich noch nicht durch, ich suche gerade nach einer Möglichkeit, wie ich die Tabellen den entsprechenden Encodern zuweisen kann, doch irgendwie finde ich da keine Lösung..

Hallo,

wenn man von irgendwas mehrere Dinge hat, hier Objekte, dann schreibt man sich eigentlich eine Klasse dafür. Erstmal egal ob Klasse oder nicht. Erstelle einen Parameter der für den jeweiligen Encoder typisch ist und mitgegeben wird. Üblicherweise sind das die Counts pro Rastung. Üblich 2 oder 4. Anhand des Parameters wird dann die "Untersetzung", deine Tabelle oder wie auch immer, ausgewählt.

Umschauen kannste dich hier: article Drehgeber
oder schaust dir irgendeine Encoder Lib an.
Die werden sich in Detail unterscheiden aber das Grundprinzip ist immer gleich.

welche GANZ GENAU? Die von Guiseppe Martini ist es offenbar nicht zumindest bekomm ich da einige Fehler beim kompilieren.
Am besten schreibst du einen funktionierenden Sketch ohne einer weiteren Library nur mit der Ausgabe auf die Serielle Schnittstelle

Es ist die Joystick Library von MHeironimus: https://github.com/MHeironimus/ArduinoJoystickLibrary

Ich habe sie gefunden.

Es handelt sich um diese Lib, die man allerdings wohl nur per Download von github und aus dem Zip-File installieren muss ...

https://github.com/MHeironimus/ArduinoJoystickLibrary/tree/master

funktioniert das noch?

/*
https://forum.arduino.cc/t/verschiedene-encoder-in-einem-projekt-half-step-full-step/1171405
 */

#include <Wire.h>

#include <Adafruit_MCP23X17.h>

// Konfiguration der Portexpander
Adafruit_MCP23X17 mcp1;
Adafruit_MCP23X17 mcp2;

// Konfiguration der Rotary Encoder
//#define HALF_STEP
#define NUMROTARIES 4

struct rotariesdef {
  byte pin1;
  byte pin2;
  int ccwchar;
  int cwchar;
  volatile unsigned char state;
};

rotariesdef rotaries[NUMROTARIES] {
  {0, 1, 17, 18, 0},
  {2, 3, 21, 22, 0},
  {0, 1, 19, 20, 0},
  {2, 3, 23, 24, 0},
};

#define DIR_CCW 0x10
#define DIR_CW 0x20
#define R_START 0x0

#ifdef HALF_STEP
#define R_CCW_BEGIN 0x1
#define R_CW_BEGIN 0x2
#define R_START_M 0x3
#define R_CW_BEGIN_M 0x4
#define R_CCW_BEGIN_M 0x5

const unsigned char ttable[6][4] = {
  // R_START (00)
  {R_START_M,            R_CW_BEGIN,     R_CCW_BEGIN,  R_START},
  // R_CCW_BEGIN
  {R_START_M | DIR_CCW, R_START,        R_CCW_BEGIN,  R_START},
  // R_CW_BEGIN
  {R_START_M | DIR_CW,  R_CW_BEGIN,     R_START,      R_START},
  // R_START_M (11)
  {R_START_M,            R_CCW_BEGIN_M,  R_CW_BEGIN_M, R_START},
  // R_CW_BEGIN_M
  {R_START_M,            R_START_M,      R_CW_BEGIN_M, R_START | DIR_CW},
  // R_CCW_BEGIN_M
  {R_START_M,            R_CCW_BEGIN_M,  R_START_M,    R_START | DIR_CCW},
};

#else
#define R_CW_FINAL 0x1
#define R_CW_BEGIN 0x2
#define R_CW_NEXT 0x3
#define R_CCW_BEGIN 0x4
#define R_CCW_FINAL 0x5
#define R_CCW_NEXT 0x6

const unsigned char ttable[7][4] = {
  // R_START
  {R_START,    R_CW_BEGIN,  R_CCW_BEGIN, R_START},
  // R_CW_FINAL
  {R_CW_NEXT,  R_START,     R_CW_FINAL,  R_START | DIR_CW},
  // R_CW_BEGIN
  {R_CW_NEXT,  R_CW_BEGIN,  R_START,     R_START},
  // R_CW_NEXT
  {R_CW_NEXT,  R_CW_BEGIN,  R_CW_FINAL,  R_START},
  // R_CCW_BEGIN
  {R_CCW_NEXT, R_START,     R_CCW_BEGIN, R_START},
  // R_CCW_FINAL
  {R_CCW_NEXT, R_CCW_FINAL, R_START,     R_START | DIR_CCW},
  // R_CCW_NEXT
  {R_CCW_NEXT, R_CCW_FINAL, R_CCW_BEGIN, R_START},
};
#endif


void setup() {

  Serial.begin(115200);

  // Initialisierung der Joystick Bibliothek
//  Joystick.begin();

  // Initialisierung des I2C Bus
  Wire.begin();

  // Initialisierung der beiden Port Expander
  mcp1.begin_I2C(0x20);
  mcp2.begin_I2C(0x21);

  // Setzen der Bus-Geschwindigkeit
  Wire.setClock(400000);

  // Konfiguration der Pins des ersten Port Expanders als Inputs
  mcp1.pinMode(0, INPUT_PULLUP);
  mcp1.pinMode(1, INPUT_PULLUP);
  mcp1.pinMode(2, INPUT_PULLUP);
  mcp1.pinMode(3, INPUT_PULLUP);

  // Konfiguration der Pins des zweiten Port Expanders als Inputs
  mcp2.pinMode(0, INPUT_PULLUP);
  mcp2.pinMode(1, INPUT_PULLUP);
  mcp2.pinMode(2, INPUT_PULLUP);
  mcp2.pinMode(3, INPUT_PULLUP);

}

void loop() {

  CheckAllEncoders();

}

// Abfrage der Zustände der Rotary Encoder und Übergabe an den Joystick
unsigned char rotary_process(int _i) {
  unsigned char pinstate = (mcp1.digitalRead(rotaries[_i].pin2) << 1) | mcp1.digitalRead(rotaries[_i].pin1);
  rotaries[_i].state = ttable[rotaries[_i].state & 0xf][pinstate];
  return (rotaries[_i].state & 0x30);
}

unsigned char rotary_process2(int _j) {
  unsigned char pinstate = (mcp2.digitalRead(rotaries[_j].pin2) << 1) | mcp2.digitalRead(rotaries[_j].pin1);
  rotaries[_j].state = ttable[rotaries[_j].state & 0xf][pinstate];
  return (rotaries[_j].state & 0x30);
}

void CheckAllEncoders(void) {
  for (int i = 0; i < 2; i++) {
    unsigned char result = rotary_process(i);
    if (result == DIR_CCW) {
      //Joystick.setButton(rotaries[i].ccwchar, 1); delay(50); Joystick.setButton(rotaries[i].ccwchar, 0);
      Serial.print(i); Serial.println(" A CCW");
    };
    if (result == DIR_CW) {
      //Joystick.setButton(rotaries[i].cwchar, 1); delay(50); Joystick.setButton(rotaries[i].cwchar, 0);
      Serial.print(i); Serial.println(" A CW");
    };
  }

  for (int i = 2; i < 4; i++) {
    unsigned char result = rotary_process2(i);
    if (result == DIR_CCW) {
      //Joystick.setButton(rotaries[i].ccwchar, 1); delay(50); Joystick.setButton(rotaries[i].ccwchar, 0);
      Serial.print(i); Serial.println(" B CCW");
    };
    if (result == DIR_CW) {
      //Joystick.setButton(rotaries[i].cwchar, 1); delay(50); Joystick.setButton(rotaries[i].cwchar, 0);
      Serial.print(i); Serial.println(" B CW");
    };
  }
}

Bitte mach meinen Schaltplan woraus man erkennt, welcher Encoder an welchem MCP - an welchem PIN hängt.
Kennzeichne welcher Encoder mit wie vielen Schritten arbeitet.

Die anderen haben schon recht, da gehört eine Klasse her.
Jeder Encoder ist ein Objekt,
Dem Encoder-Objekt übergibt man das passende MCP Objekt und die Pins sowie die Tabelle 1 oder 2.

Versuche gerne mal diese Version:

/*
Die RKJXT1F42001 sind jeweils an den Pins 0 & 1 der MCP23017 angeschlossen, die KY-040 an den Pins 2 & 3.

rotariesdef rotaries[NUMROTARIES] {
  {0, 1, 17, 18, 0},                     // RKJXT1F42001          rotaries[0]
  {2, 3, 21, 22, 0},                     // KY-040                rotaries[1]
  {0, 1, 19, 20, 0},                     // RKJXT1F42001          rotaries[2]
  {2, 3, 23, 24, 0},                     // KY-040                rotaries[3]
};

*/

#include <Wire.h>
#include <Joystick.h>
#include <Adafruit_MCP23X17.h>

// Konfiguration der Portexpander
Adafruit_MCP23X17 mcp1;
Adafruit_MCP23X17 mcp2;


// Konfiguration der Rotary Encoder
//#define HALF_STEP
#define NUMROTARIES 4

struct rotariesdef {
  byte pin1;
  byte pin2;
  int ccwchar;
  int cwchar;
  volatile unsigned char state;
};

rotariesdef rotaries[NUMROTARIES] {
  {0, 1, 17, 18, 0},
  {2, 3, 21, 22, 0},
  {0, 1, 19, 20, 0},
  {2, 3, 23, 24, 0},
};

#define DIR_CCW 0x10
#define DIR_CW 0x20
#define R_START 0x0

#define HR_CCW_BEGIN 0x1
#define HR_CW_BEGIN 0x2
#define HR_START_M 0x3
#define HR_CW_BEGIN_M 0x4
#define HR_CCW_BEGIN_M 0x5

const unsigned char ttableHalf[6][4] = {
  // R_START (00)
  {HR_START_M,            HR_CW_BEGIN,     HR_CCW_BEGIN,  R_START},
  // R_CCW_BEGIN
  {HR_START_M | DIR_CCW, R_START,        HR_CCW_BEGIN,  R_START},
  // R_CW_BEGIN
  {HR_START_M | DIR_CW,  HR_CW_BEGIN,     R_START,      R_START},
  // R_START_M (11)
  {HR_START_M,           HR_CCW_BEGIN_M,  HR_CW_BEGIN_M, R_START},
  // R_CW_BEGIN_M
  {HR_START_M,            HR_START_M,      HR_CW_BEGIN_M, R_START | DIR_CW},
  // R_CCW_BEGIN_M
  {HR_START_M,            HR_CCW_BEGIN_M,  HR_START_M,    R_START | DIR_CCW},
};

#define R_CW_FINAL 0x1
#define R_CW_BEGIN 0x2
#define R_CW_NEXT 0x3
#define R_CCW_BEGIN 0x4
#define R_CCW_FINAL 0x5
#define R_CCW_NEXT 0x6

const unsigned char ttableFull[7][4] = {
  // R_START
  {R_START,    R_CW_BEGIN,  R_CCW_BEGIN, R_START},
  // R_CW_FINAL
  {R_CW_NEXT,  R_START,     R_CW_FINAL,  R_START | DIR_CW},
  // R_CW_BEGIN
  {R_CW_NEXT,  R_CW_BEGIN,  R_START,     R_START},
  // R_CW_NEXT
  {R_CW_NEXT,  R_CW_BEGIN,  R_CW_FINAL,  R_START},
  // R_CCW_BEGIN
  {R_CCW_NEXT, R_START,     R_CCW_BEGIN, R_START},
  // R_CCW_FINAL
  {R_CCW_NEXT, R_CCW_FINAL, R_START,     R_START | DIR_CCW},
  // R_CCW_NEXT
  {R_CCW_NEXT, R_CCW_FINAL, R_CCW_BEGIN, R_START},
};


// Konfiguration des Joysticks
Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,
                   JOYSTICK_TYPE_JOYSTICK, 25, 2,
                   false, false, false, false, false, false,
                   false, false, false, false, false);

void setup() {

  Serial.begin(115200);

  // Initialisierung der Joystick Bibliothek
  Joystick.begin();

  // Initialisierung des I2C Bus
  Wire.begin();

  // Initialisierung der beiden Port Expander
  mcp1.begin_I2C(0x20);
  mcp2.begin_I2C(0x21);

  // Setzen der Bus-Geschwindigkeit
  Wire.setClock(400000);

  // Konfiguration der Pins des ersten Port Expanders als Inputs
  mcp1.pinMode(0, INPUT_PULLUP);
  mcp1.pinMode(1, INPUT_PULLUP);
  mcp1.pinMode(2, INPUT_PULLUP);
  mcp1.pinMode(3, INPUT_PULLUP);

  // Konfiguration der Pins des zweiten Port Expanders als Inputs
  mcp2.pinMode(0, INPUT_PULLUP);
  mcp2.pinMode(1, INPUT_PULLUP);
  mcp2.pinMode(2, INPUT_PULLUP);
  mcp2.pinMode(3, INPUT_PULLUP);

}

void loop() {

  CheckAllEncoders();

}

// Abfrage der Zustände der Rotary Encoder und Übergabe an den Joystick
unsigned char rotary_process(int _i) {
  unsigned char pinstate = (mcp1.digitalRead(rotaries[_i].pin2) << 1) | mcp1.digitalRead(rotaries[_i].pin1);
  if (_i == 0) {
     rotaries[_i].state = ttableHalf[rotaries[_i].state & 0xf][pinstate];
  } else {
     rotaries[_i].state = ttableFull[rotaries[_i].state & 0xf][pinstate];
  }
  return (rotaries[_i].state & 0x30);
}

unsigned char rotary_process2(int _j) {
  unsigned char pinstate = (mcp2.digitalRead(rotaries[_j].pin2) << 1) | mcp2.digitalRead(rotaries[_j].pin1);
  if (_j == 2) {
    rotaries[_j].state = ttableHalf[rotaries[_j].state & 0xf][pinstate];
   } else {
    rotaries[_j].state = ttableFull[rotaries[_j].state & 0xf][pinstate];
  }
  return (rotaries[_j].state & 0x30);
}

void CheckAllEncoders(void) {
  for (int i = 0; i < 2; i++) {
    unsigned char result = rotary_process(i);
    if (result == DIR_CCW) {
      Joystick.setButton(rotaries[i].ccwchar, 1); delay(50); Joystick.setButton(rotaries[i].ccwchar, 0);
    };
    if (result == DIR_CW) {
      Joystick.setButton(rotaries[i].cwchar, 1); delay(50); Joystick.setButton(rotaries[i].cwchar, 0);
    };
  }

  for (int i = 2; i < 4; i++) {
    unsigned char result = rotary_process2(i);
    if (result == DIR_CCW) {
      Joystick.setButton(rotaries[i].ccwchar, 1); delay(50); Joystick.setButton(rotaries[i].ccwchar, 0);
    };
    if (result == DIR_CW) {
      Joystick.setButton(rotaries[i].cwchar, 1); delay(50); Joystick.setButton(rotaries[i].cwchar, 0);
    };
  }
}

Ich befürchte, dass Dein Sketch durch den Werdegang (Copy'n Paste plus ChatGPT) zwar irgendwie zur Funktionsfähigkeit gebracht werden konnte, aber die Nachvollziehbarkeit der Funktion dadurch gelitten hat ... Mein Respekt, wenn Du ihn wirklich durchdrungen hast!

Der obige Code compiliert, aber ich kann nicht prüfen, ob das Erwartete herauskommt.

Was habe ich gemacht?

  • Beide Tabellen aktiviert
  • In den Abfragefunktionen dafür gesorgt, dass die jeweiligen Drehencoder auf die zugehörige Tabelle für Halbschritt (oder eben nicht) zugreifen.

Hoffentlich ist das Stichwort ... :wink:

Wenn alles hoffentlich gut geht, wäre Dein Projekt damit fürs Erste gerettet. In Sachen Pflegbarkeit und Nachvollziehbarkeit halte ich den Code für eher bedenklich ...

Viel Glück!

P.S.: Es wäre vermutlich schon etwas übersichtlicher, wenn Du an einem MCP nur identische Encodertypen verwenden würdest ... Dann würde man in der jeweiligen rotary_process-Funktion die gleiche Tabelle verwenden können. So ist das leider nur "Rumgefrickel"...

1 Like

Vielen Dank, so funktioniert das einwandfrei!!

Theoretisch wäre es möglich an jedem MCP nur einen Encoder Typ zu verwenden, dann leidet aber leider die Einbausituation darunter.

Ich stehe, wie eingangs schon erwähnt, noch ganz am Anfang meiner Programmierkenntnisse... so sehr, dass selbst das Entprellen der Buttons in diesem Projekt eine Herausforderung war, von daher hast Du mir sehr geholfen.

Es wäre auch möglich gewesen, dieses Projekt mit meinem vorhandenen Code zu betreiben, jedoch ist es ganz schön nervig, wenn man den einen Encoder immer zwei Rasten drehen muss, bis eine Eingabe erfolgt... Tausend Dank nochmal!!

Jetzt habe ich wieder ein Stückchen Code, den ich verstehen und daraus lernen kann.

Der Encoder Teil dieses Sketches war für den Betrieb direkt am Arduino geschrieben, ich war schon stolz wie Oskar, dass ich die Encoder auf zwei unterschiedlichen MCP zum Laufen gebracht habe... klingt für euch Profis wahrscheinlich lächerlich, aber aller Anfang ist schwer... erstrecht, wenn man vorher noch nie mit C++ in Berührung kam!

Ich hoffe - auch wenn der Code jetzt zu Deiner Zufriedenheit läuft -, dass Du Dir die Vorschläge der anderen Supporter in Deinem Thread anschaust ...

Spätestens beim nächsten Projekt, einer Fehlerbehebung oder Erweiterung dieses Codes wirst Du in vier bis sechs Wochen vermutlich Schwierigkeiten haben, Dich dort wieder einzuarbeiten. Je nachvollziehbarer ein Sketch ist, um so leichter fällt das natürlich. Spätestens in sechs Monaten fragst Du Dich, was Du damals alles gekonnt und gewusst hast :wink:

Hier gleich ein Hinweis, wo das jetzige Konstrukt programmtechnisch absolut "fehlerträchtig" ist. Der Aufruf der Funktionen rotary_process() und rotary_process2() erfolgt derzeit aus for-Schleifen; hier für rotary_process():

 for (int i = 0; i < 2; i++) {
    unsigned char result = rotary_process(i);

Die von mir eingebrachte Anpassung funktioniert nur deshalb, weil ausschliesslich die Indizes 0 und 1 vorkommen:

unsigned char rotary_process(int _i) {
  unsigned char pinstate = (mcp1.digitalRead(rotaries[_i].pin2) << 1) | mcp1.digitalRead(rotaries[_i].pin1);
  if (_i == 0) {
     rotaries[_i].state = ttableHalf[rotaries[_i].state & 0xf][pinstate];
  } else {
     rotaries[_i].state = ttableFull[rotaries[_i].state & 0xf][pinstate];
  }
  return (rotaries[_i].state & 0x30);
}

Insgesamt funktioniert Vieles mit hardcodierten Zahlen/Grenzen.

So etwas sollte man auf jeden Fall vermeiden, wenn man Wert auf Erweiterbarkeit und Zuverlässigkeit legt. Schnell mal um einen Encoder erweitern und schon hat man (u.U.) wieder das alte oder einen Haufen neue Probleme.

Viel Erfolg!

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