Hallo,
kann man die Vererbungen "einkürzen"?
Die Methode long getRelCounter() gibt es nur in den Vererbungen und ist dort unverändert gleich. Die Basisklasse GrayEncoder soll diese jedoch nicht besitzen. Muss dass hier demnach doppelt sein also 1:1 mit geschleppt werden?
Die encode() Methode ist wird in den Vererbungen nur um einen Methodenaufruf ergänzt. Muss auch hier der Grundstock von encode() mitgeschleppt werden oder geht das noch einfacher bzw. kürzer?
Auch die rein interne Methode update_relCounter() unterscheidet sich nur im halbieren oder vierteln des Absolutwertes.
Der Kram mit dem relativen Zähler soll es nur in den Vererbungen geben.
Im Grunde möchte ich eine Allzweckklasse für alle meine Encoder. Wie würdet ihr es sonst machen? Was kann man anders bzw. besser machen?
class GrayEncoder // Klassenname "GrayEncoder"
{
protected: // private wird zu protected, nur intern zugängliche Elemente ...
volatile byte const *PORT; // verwendeter Port
byte const PinA; // Pin Port.Bit erste Phase
byte const PinB; // Pin Port.Bit zweite Phase
int relMin;
int relMax;
volatile long rel_counter; // relativer Zähler, veränderbar
volatile long abs_counter; // absoluter Zähler, nicht veränderbar
int direction; // Richtungsanzeige +1 / -1
int enc_delta;
int last;
byte Phase_A; // erste Phase
byte Phase_B; // zweite Phase
public: // von außen zugängliche Elemente ...
GrayEncoder (volatile byte *p_Port, byte _A, byte _B):
// Initialisierungsliste
PORT(p_Port),
PinA(_A),
PinB(_B),
relMin(0),
relMax(0),
rel_counter(0), // Zähler
abs_counter(0), // Zähler
direction(0) // Richtungsanzeige +1 / -1
{ }
GrayEncoder (volatile byte *p_Port, byte _A, byte _B, int _min, int _max):
// Initialisierungsliste
PORT(p_Port),
PinA(_A),
PinB(_B),
relMin(_min),
relMax(_max),
rel_counter(0), // Zähler
abs_counter(0), // Zähler
direction(0) // Richtungsanzeige +1 / -1
{ }
void init()
{
int n = 0; // new
Phase_A = (*PORT >> PinA & 1); // einzelnes Bit heraus fischen
Phase_B = (*PORT >> PinB & 1);
if ( Phase_A ) n = 3;
if ( Phase_B ) n ^= 1;
last = n; // power on state
enc_delta = 0;
}
void encode()
{
int n = 0; // new
Phase_A = (*PORT >> PinA & 1); // einzelnes Bit heraus fischen
Phase_B = (*PORT >> PinB & 1);
if ( Phase_A ) n = 3;
if ( Phase_B ) n ^= 1; // convert gray to binary
int diff = last - n;
if ( diff & 1 ) { // bit 0 = value (1)
last = n; // store new as next last
enc_delta = (diff & 2) - 1; // bit 1 = direction (+/-), Zähler
abs_counter += (long) enc_delta;
direction = enc_delta; // Richtungsanzeige (+1 / -1)
}
}
int getDirection() {return direction; } // Richtungsabfrage
long getAbsCounter() {return abs_counter; } // absoluten Zählwert abfragen
int getA() { return Phase_A; } // Signal von Phase A
int getB() { return Phase_B; } // Signal von Phase A
};
// Klasse "ALPS_EM20B" erbt von "GrayEncoder" aber nur mit dem zweiten Konstruktor
class ALPS_EM20B : public GrayEncoder
{
public: // von außen zugängliche Elemente ...
ALPS_EM20B(volatile byte *p_Port, byte _A, byte _B, byte _min, byte _max): GrayEncoder (p_Port, _A, _B, _min, _max)
{ }
void encode()
{
int n = 0; // new
Phase_A = (*PORT >> PinA & 1); // einzelnes Bit heraus fischen
Phase_B = (*PORT >> PinB & 1);
if ( Phase_A ) n = 3;
if ( Phase_B ) n ^= 1; // convert gray to binary
int diff = last - n;
if ( diff & 1 ) { // bit 0 = value (1)
last = n; // store new as next last
enc_delta = (diff & 2) - 1; // bit 1 = direction (+/-), Zähler
abs_counter += (long) enc_delta;
direction = enc_delta; // Richtungsanzeige (+1 / -1)
}
update_relCounter();
}
void update_relCounter () {
static long abs_old = 0;
long new_abs = abs_counter>>2; // geviertelt, 4 Steps pro Rastung
if ( new_abs != abs_old) {
if (new_abs > abs_old) {
rel_counter++;
}
else {
rel_counter--;
}
abs_old = new_abs;
}
if (rel_counter < relMin) {
rel_counter = relMax;
}
else if (rel_counter > relMax) {
rel_counter = relMin;
}
}
long getRelCounter() { // relativen Zählwert abfragen
return rel_counter; // wird schon geviertelt +/- geändert
}
long getAbsCounter() { // absoluten Zählwert abfragen
return abs_counter >> 2; // 4 Steps pro Rastung
}
};
// Klasse "ALPS_EC11" erbt von "GrayEncoder" aber nur mit dem zweiten Konstruktor
class ALPS_EC11 : public GrayEncoder
{
public: // von außen zugängliche Elemente ...
ALPS_EC11(volatile byte *p_Port, byte _A, byte _B, byte _min, byte _max): GrayEncoder (p_Port, _A, _B, _min, _max)
{ }
void encode()
{
int n = 0; // new
Phase_A = (*PORT >> PinA & 1); // einzelnes Bit heraus fischen
Phase_B = (*PORT >> PinB & 1);
if ( Phase_A ) n = 3;
if ( Phase_B ) n ^= 1; // convert gray to binary
int diff = last - n;
if ( diff & 1 ) { // bit 0 = value (1)
last = n; // store new as next last
enc_delta = (diff & 2) - 1; // bit 1 = direction (+/-), Zähler
abs_counter += (long) enc_delta;
direction = enc_delta; // Richtungsanzeige (+1 / -1)
}
update_relCounter();
}
void update_relCounter () {
static long abs_old = 0;
long new_abs = abs_counter >> 1; // halbiert, 2 Steps pro Rastung
if ( new_abs != abs_old) {
if (new_abs > abs_old) {
rel_counter++;
}
else {
rel_counter--;
}
abs_old = new_abs;
}
if (rel_counter < relMin) {
rel_counter = relMax;
}
else if (rel_counter > relMax) {
rel_counter = relMin;
}
}
long getRelCounter() { // relativen Zählwert abfragen
return rel_counter; // wird schon halbiert +/- geändert
}
long getAbsCounter() { // absoluten Zählwert abfragen
return abs_counter >> 1; // 2 Steps pro Rastung
}
};
// ---------------------------------------------------------------------------------------
GrayEncoder Encoder1 (&PINC, 0, 1); // Phase A/B, Pin 37/36 > Port.C Bit.0 / Bit.1
ALPS_EM20B Encoder2 (&PINC, 0, 1, 0, 10); // Phase A/B, Pin 37/36 > Port.C Bit.0 / Bit.1 / RelMin / RelMax
ALPS_EC11 Encoder3 (&PING, 1, 0, 0, 10); // Phase A/B, Pin 40/41 > Port.G Bit.1 / Bit.0 / RelMin / RelMax
int Encoder1_Direction;
int Encoder1_AbsCounter;
byte Encoder1_PhaseA;
byte Encoder1_PhaseB;
int Encoder2_Direction;
int Encoder2_RelCounter;
int Encoder2_AbsCounter;
int Encoder3_Direction;
int Encoder3_RelCounter;
int Encoder3_AbsCounter;
void setup() {
Serial.begin(250000);
pinMode(36, INPUT_PULLUP);
pinMode(37, INPUT_PULLUP);
pinMode(40, INPUT_PULLUP);
pinMode(41, INPUT_PULLUP);
Encoder1.init();
Encoder2.init();
Encoder3.init();
}
void loop() {
update_Encoder();
Ausgabe();
}