gesucht >> Pin-Port.Bitfolge oder Wurzelfunktion

Hallo,

combie hat hat in seinen combiepin Tools
zum Bsp. sowas stehen … Index ist die Arduino Pin-Nummer.

byte pinMaske[]     = {0b1,0b10,0b10000,0b100000,0b100000,0b1000,0b1000, ...

Gibt es so eine Pin Reihenfolge auch mit Port Bits?
Wenn nicht, gibt es eine Wurzelfunktion mit der man beliebige Wurzeln ziehen kann?
Damit könnte ich aus der combie Maske das Bit berechnen.
Ich finde nur Quadrat- und Kubikwurzelfunktionen.

Edit:
Was ich machen möchte ist. Ich möchte statt Port und Bits meinen GrayEncoder Code die Arduino Pinnummern übergeben. Dazu muss ich intern den Port auslesen, Bitmaske drüberlegen und um entsprechende Bitstelle nach rechts schieben. Dazu muss ich die Bitstelle ermitteln.

  Serial.println(__builtin_ctz(0b100));

Das sollte funktionieren.

Aber...? Was willst du wirklich erreichen?

Hallo,

das Wurzel ziehen funktioniert. Wo haste das her?

Ich möchte meine GrayEncoder von außen vereinfachen. Weg von den Port und Bit Parametern hin zu einfachen Arduino Pinnummern.

Jetzt habe ich das soweit vorbereitet und für das Bsp. mit Pinnummern 37 und 36 müßte das eigentlich funktionieren. Klappt aber nicht. Der Encoderzähler zählt nicht. Kompilierung jedoch fehlerfrei. Irgendwie ist in den Zeilen ein Fehler drin.

Phase_A = (*getPort(Pin_A) & getMaske(Pin_A)) >> 0;  // einzelnes Bit heraus fischen
Phase_B = (*getPort(Pin_B) & getMaske(Pin_B)) >> 1;

Später soll für das schieben die 0 und 1 in Zeile 55 und 56 durch die automatisch ermittelte Bitnummer ersetzt werden.

  using Register = volatile byte *;
  
  // UNO, Nano, Pro Mini usw.
  #if defined(__AVR_ATmega328P__) | defined(__AVR_ATmega328__) | defined(__AVR_ATmega168P__) | defined(__AVR_ATmega168__)
    constexpr byte pinMaske[]     = {0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1000000, 0b10000000, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000,};
    constexpr Register portList[] = {&PORTD, &PORTD, &PORTD, &PORTD, &PORTD, &PORTD, &PORTD, &PORTD, &PORTB, &PORTB, &PORTB, &PORTB, &PORTB, &PORTB, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC,};
    constexpr Register ddrList[]  = {&DDRD, &DDRD, &DDRD, &DDRD, &DDRD, &DDRD, &DDRD, &DDRD, &DDRB, &DDRB, &DDRB, &DDRB, &DDRB, &DDRB, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC,};
    constexpr Register pinList[]  = {&PIND, &PIND, &PIND, &PIND, &PIND, &PIND, &PIND, &PIND, &PINB, &PINB, &PINB, &PINB, &PINB, &PINB, &PINC, &PINC, &PINC, &PINC, &PINC, &PINC,};
  //    #endif
    
  // Mega
  #elif defined(__AVR_ATmega2560__) | defined(__AVR_ATmega1280__)
    constexpr byte pinMaske[]     = {0b1, 0b10, 0b10000, 0b100000, 0b100000, 0b1000, 0b1000, 0b10000, 0b100000, 0b1000000, 0b10000, 0b100000, 0b1000000, 0b10000000, 0b10, 0b1, 0b10, 0b1, 0b1000, 0b100, 0b10, 0b1, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1000000, 0b10000000, 0b10000000, 0b1000000, 0b100000, 0b10000, 0b1000, 0b100, 0b10, 0b1, 0b10000000, 0b100, 0b10, 0b1, 0b10000000, 0b1000000, 0b100000, 0b10000, 0b1000, 0b100, 0b10, 0b1, 0b1000, 0b100, 0b10, 0b1, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1000000, 0b10000000, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1000000, 0b10000000,};
    constexpr Register portList[] = {&PORTE, &PORTE, &PORTE, &PORTE, &PORTG, &PORTE, &PORTH, &PORTH, &PORTH, &PORTH, &PORTB, &PORTB, &PORTB, &PORTB, &PORTJ, &PORTJ, &PORTH, &PORTH, &PORTD, &PORTD, &PORTD, &PORTD, &PORTA, &PORTA, &PORTA, &PORTA, &PORTA, &PORTA, &PORTA, &PORTA, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTD, &PORTG, &PORTG, &PORTG, &PORTL, &PORTL, &PORTL, &PORTL, &PORTL, &PORTL, &PORTL, &PORTL, &PORTB, &PORTB, &PORTB, &PORTB, &PORTF, &PORTF, &PORTF, &PORTF, &PORTF, &PORTF, &PORTF, &PORTF, &PORTK, &PORTK, &PORTK, &PORTK, &PORTK, &PORTK, &PORTK, &PORTK,};
    constexpr Register ddrList[]  = {&DDRE, &DDRE, &DDRE, &DDRE, &DDRG, &DDRE, &DDRH, &DDRH, &DDRH, &DDRH, &DDRB, &DDRB, &DDRB, &DDRB, &DDRJ, &DDRJ, &DDRH, &DDRH, &DDRD, &DDRD, &DDRD, &DDRD, &DDRA, &DDRA, &DDRA, &DDRA, &DDRA, &DDRA, &DDRA, &DDRA, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC, &DDRD, &DDRG, &DDRG, &DDRG, &DDRL, &DDRL, &DDRL, &DDRL, &DDRL, &DDRL, &DDRL, &DDRL, &DDRB, &DDRB, &DDRB, &DDRB, &DDRF, &DDRF, &DDRF, &DDRF, &DDRF, &DDRF, &DDRF, &DDRF, &DDRK, &DDRK, &DDRK, &DDRK, &DDRK, &DDRK, &DDRK, &DDRK,};
    constexpr Register pinList[]  = {&PINE, &PINE, &PINE, &PINE, &PING, &PINE, &PINH, &PINH, &PINH, &PINH, &PINB, &PINB, &PINB, &PINB, &PINJ, &PINJ, &PINH, &PINH, &PIND, &PIND, &PIND, &PIND, &PINA, &PINA, &PINA, &PINA, &PINA, &PINA, &PINA, &PINA, &PINC, &PINC, &PINC, &PINC, &PINC, &PINC, &PINC, &PINC, &PIND, &PING, &PING, &PING, &PINL, &PINL, &PINL, &PINL, &PINL, &PINL, &PINL, &PINL, &PINB, &PINB, &PINB, &PINB, &PINF, &PINF, &PINF, &PINF, &PINF, &PINF, &PINF, &PINF, &PINK, &PINK, &PINK, &PINK, &PINK, &PINK, &PINK, &PINK,};
  //    #endif
  
  #else
    #error “This AVR type is currently not yet supported.”
  #endif


class GrayEncoder
{
  protected:
    byte const Pin_A;         // Phase A
    byte const Pin_B;         // Phase B
    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
            
    Register getPort(byte pin) {
      return portList[pin];
    }

    byte getMaske(byte pin) {
      return pinMaske[pin];
    }
        
    int getPhases() {
      int n = 0;                      // new

      Phase_A = ( *getPort(Pin_A) & getMaske(Pin_A)) >> 0;  // einzelnes Bit heraus fischen
      Phase_B = ( *getPort(Pin_B) & getMaske(Pin_B)) >> 1;
      
      if ( Phase_A ) n = 3;
      if ( Phase_B ) n ^= 1;          // convert gray to binary
      return n;
    }

  public:
    GrayEncoder (byte _A, byte _B): 
      Pin_A(_A),
      Pin_B(_B),
      abs_counter(0),               // Zähler
      direction(0)                  // Richtungsanzeige  +1 / -1
    { }

    void init()
    {
      last = getPhases();           // power on state
      enc_delta = 0;
    }

    void encode()
    {
      int n = getPhases();
      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
    }

};

GrayEncoder Encoder1(37, 36);            // Phase A/B, Pin 37/36 > Port.C Bit.0 / Bit.1

Wie kommst du auf Wurzeln? ctz = count trailing zeroes. Ganz einfach. Das ist eine Funktion des Compilers

getMaske(Pin_A) >> x

Solche Ausdrücke, mit schieben zur Laufzeit, sind auf AVR erstaunlich teuer. Denn er hat keinen Barrelshifter.

Darum wunderte ich mich auch über die Bitpostition, die du haben möchtest. Meist ist es klüger, zur Laufzeit nur mit Masken zu arbeiten, und dem Compiler das schieben zu überlassen.

Wo haste das her?

Aus der Compiler Doku.

Hallo,

ich muss doch dem Compiler bzw. dem Code sagen um wieviel Stellen er schieben muss. Das kann man dann bestimmt noch mit constexpr zur Compilezeit machen lassen.

Mit meinem Testsketch, Register auslesen, Maske drüber und schieben klappt das. Fehlende Klammer vorm schieben ist oben korrigiert. Testsketch macht was er soll, GrayEncoder zählt weiterhin kein Stück. Ich weiß nicht warum.

#if defined(__AVR_ATmega2560__) | defined(__AVR_ATmega1280__)
  constexpr byte pinMaske[]     = {0b1,0b10,0b10000,0b100000,0b100000,0b1000,0b1000,0b10000,0b100000,0b1000000,0b10000,0b100000,0b1000000,0b10000000,0b10,0b1,0b10,0b1,0b1000,0b100,0b10,0b1,0b1,0b10,0b100,0b1000,0b10000,0b100000,0b1000000,0b10000000,0b10000000,0b1000000,0b100000,0b10000,0b1000,0b100,0b10,0b1,0b10000000,0b100,0b10,0b1,0b10000000,0b1000000,0b100000,0b10000,0b1000,0b100,0b10,0b1,0b1000,0b100,0b10,0b1,0b1,0b10,0b100,0b1000,0b10000,0b100000,0b1000000,0b10000000,0b1,0b10,0b100,0b1000,0b10000,0b100000,0b1000000,0b10000000};
  constexpr volatile byte *portList[] = {&PORTE,&PORTE,&PORTE,&PORTE,&PORTG,&PORTE,&PORTH,&PORTH,&PORTH,&PORTH,&PORTB,&PORTB,&PORTB,&PORTB,&PORTJ,&PORTJ,&PORTH,&PORTH,&PORTD,&PORTD,&PORTD,&PORTD,&PORTA,&PORTA,&PORTA,&PORTA,&PORTA,&PORTA,&PORTA,&PORTA,&PORTC,&PORTC,&PORTC,&PORTC,&PORTC,&PORTC,&PORTC,&PORTC,&PORTD,&PORTG,&PORTG,&PORTG,&PORTL,&PORTL,&PORTL,&PORTL,&PORTL,&PORTL,&PORTL,&PORTL,&PORTB,&PORTB,&PORTB,&PORTB,&PORTF,&PORTF,&PORTF,&PORTF,&PORTF,&PORTF,&PORTF,&PORTF,&PORTK,&PORTK,&PORTK,&PORTK,&PORTK,&PORTK,&PORTK,&PORTK};
  constexpr volatile byte *ddrList[]  = {&DDRE,&DDRE,&DDRE,&DDRE,&DDRG,&DDRE,&DDRH,&DDRH,&DDRH,&DDRH,&DDRB,&DDRB,&DDRB,&DDRB,&DDRJ,&DDRJ,&DDRH,&DDRH,&DDRD,&DDRD,&DDRD,&DDRD,&DDRA,&DDRA,&DDRA,&DDRA,&DDRA,&DDRA,&DDRA,&DDRA,&DDRC,&DDRC,&DDRC,&DDRC,&DDRC,&DDRC,&DDRC,&DDRC,&DDRD,&DDRG,&DDRG,&DDRG,&DDRL,&DDRL,&DDRL,&DDRL,&DDRL,&DDRL,&DDRL,&DDRL,&DDRB,&DDRB,&DDRB,&DDRB,&DDRF,&DDRF,&DDRF,&DDRF,&DDRF,&DDRF,&DDRF,&DDRF,&DDRK,&DDRK,&DDRK,&DDRK,&DDRK,&DDRK,&DDRK,&DDRK};
  constexpr volatile byte *pinList[]  = {&PINE,&PINE,&PINE,&PINE,&PING,&PINE,&PINH,&PINH,&PINH,&PINH,&PINB,&PINB,&PINB,&PINB,&PINJ,&PINJ,&PINH,&PINH,&PIND,&PIND,&PIND,&PIND,&PINA,&PINA,&PINA,&PINA,&PINA,&PINA,&PINA,&PINA,&PINC,&PINC,&PINC,&PINC,&PINC,&PINC,&PINC,&PINC,&PIND,&PING,&PING,&PING,&PINL,&PINL,&PINL,&PINL,&PINL,&PINL,&PINL,&PINL,&PINB,&PINB,&PINB,&PINB,&PINF,&PINF,&PINF,&PINF,&PINF,&PINF,&PINF,&PINF,&PINK,&PINK,&PINK,&PINK,&PINK,&PINK,&PINK,&PINK};
//    #endif
#else
  #error “This AVR type is currently not yet supported.”
#endif


byte getMaske(byte pin) {
  return pinMaske[pin];
}
    
volatile byte *ddrPort(byte pin) {
  return ddrList[pin];
}   

volatile byte *ptr;


void setup()
{
  Serial.begin(250000);
  Serial.println();
  
  pinMode(30, OUTPUT);    // Pin 30, Port C, Bit 7
  pinMode(35, OUTPUT);    // Pin 35, Port C, Bit 2  

  byte maske = 0;
  byte value = 0;
  
  ptr = ddrPort(35);
  maske = getMaske(35);
  value = *ptr & maske;
  Serial.println(value, BIN);
  
  value = (*ddrPort(35) & getMaske(35)) >> 2;
  Serial.println(value, BIN);

  ptr = ddrPort(30);
  maske = getMaske(30);
  value = *ptr & maske;
  Serial.println(value, BIN);
  
  value = (*ddrPort(30) & getMaske(30)) >> 7;
  Serial.println(value, BIN);
    
}


void loop()
{ }

Hallo,

Danke Euch für die Wurzel Funktionsinfo. Zusatzfrage. Ich dachte bis jetzt das es nichts schnelleres gibt wie shiften. Weil immer versucht wird zu shiften statt zu dividieren wo es möglich ist.

Dividieren ist noch teurer.

Es ist schneller als dividieren, aber braucht immer noch einen Takt pro Bit. Man kann nicht mehrere Bits auf einmal schieben

Der Compiler sollte aber so intelligent sein das zu optimieren wenn die Werte zur Compile-Zeit bekannt sind

Dann muss man letztlich shiften. Mit der Maske isoliert man nur das gewünschte Bit. Compileroptimierungen kann ich am Ende noch machen mit constexpr zum Bsp.

Zurück zum Problem. Die Werte der beiden Phasen bleiben konstant auf 1. Warum das? Es wird doch immer neu berechnet. Ist irgendein Logikfehler drin?

  using Register = volatile byte *;
  
  // UNO, Nano, Pro Mini usw.
  #if defined(__AVR_ATmega328P__) | defined(__AVR_ATmega328__) | defined(__AVR_ATmega168P__) | defined(__AVR_ATmega168__)
    constexpr byte pinMaske[]     = {0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1000000, 0b10000000, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000,};
    constexpr Register portList[] = {&PORTD, &PORTD, &PORTD, &PORTD, &PORTD, &PORTD, &PORTD, &PORTD, &PORTB, &PORTB, &PORTB, &PORTB, &PORTB, &PORTB, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC,};
    constexpr Register ddrList[]  = {&DDRD, &DDRD, &DDRD, &DDRD, &DDRD, &DDRD, &DDRD, &DDRD, &DDRB, &DDRB, &DDRB, &DDRB, &DDRB, &DDRB, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC,};
    constexpr Register pinList[]  = {&PIND, &PIND, &PIND, &PIND, &PIND, &PIND, &PIND, &PIND, &PINB, &PINB, &PINB, &PINB, &PINB, &PINB, &PINC, &PINC, &PINC, &PINC, &PINC, &PINC,};
  //    #endif
  
  // Leonardo, Micro, usw.
  #elif defined(__AVR_ATmega32U4__)
    constexpr byte pinMaske[]     = {0b100, 0b1000, 0b10, 0b1, 0b10000, 0b1000000, 0b10000000, 0b1000000, 0b10000, 0b100000, 0b1000000, 0b10000000, 0b1000000, 0b10000000, 0b1000, 0b10, 0b100, 0b1, 0b10000000, 0b1000000, 0b100000, 0b10000, 0b10, 0b1, 0b10000, 0b10000000, 0b10000, 0b100000, 0b1000000, 0b1000000, 0b100000,};
    constexpr Register portList[] = {&PORTD, &PORTD, &PORTD, &PORTD, &PORTD, &PORTC, &PORTD, &PORTE, &PORTB, &PORTB, &PORTB, &PORTB, &PORTD, &PORTC, &PORTB, &PORTB, &PORTB, &PORTB, &PORTF, &PORTF, &PORTF, &PORTF, &PORTF, &PORTF, &PORTD, &PORTD, &PORTB, &PORTB, &PORTB, &PORTD, &PORTD,};
    constexpr Register ddrList[]  = {&DDRD, &DDRD, &DDRD, &DDRD, &DDRD, &DDRC, &DDRD, &DDRE, &DDRB, &DDRB, &DDRB, &DDRB, &DDRD, &DDRC, &DDRB, &DDRB, &DDRB, &DDRB, &DDRF, &DDRF, &DDRF, &DDRF, &DDRF, &DDRF, &DDRD, &DDRD, &DDRB, &DDRB, &DDRB, &DDRD, &DDRD,};
    constexpr Register pinList[]  = {&PIND, &PIND, &PIND, &PIND, &PIND, &PINC, &PIND, &PINE, &PINB, &PINB, &PINB, &PINB, &PIND, &PINC, &PINB, &PINB, &PINB, &PINB, &PINF, &PINF, &PINF, &PINF, &PINF, &PINF, &PIND, &PIND, &PINB, &PINB, &PINB, &PIND, &PIND,};
  // #endif
  
  // Mega
  #elif defined(__AVR_ATmega2560__) | defined(__AVR_ATmega1280__)
    constexpr byte pinMaske[]     = {0b1, 0b10, 0b10000, 0b100000, 0b100000, 0b1000, 0b1000, 0b10000, 0b100000, 0b1000000, 0b10000, 0b100000, 0b1000000, 0b10000000, 0b10, 0b1, 0b10, 0b1, 0b1000, 0b100, 0b10, 0b1, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1000000, 0b10000000, 0b10000000, 0b1000000, 0b100000, 0b10000, 0b1000, 0b100, 0b10, 0b1, 0b10000000, 0b100, 0b10, 0b1, 0b10000000, 0b1000000, 0b100000, 0b10000, 0b1000, 0b100, 0b10, 0b1, 0b1000, 0b100, 0b10, 0b1, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1000000, 0b10000000, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1000000, 0b10000000,};
    constexpr Register portList[] = {&PORTE, &PORTE, &PORTE, &PORTE, &PORTG, &PORTE, &PORTH, &PORTH, &PORTH, &PORTH, &PORTB, &PORTB, &PORTB, &PORTB, &PORTJ, &PORTJ, &PORTH, &PORTH, &PORTD, &PORTD, &PORTD, &PORTD, &PORTA, &PORTA, &PORTA, &PORTA, &PORTA, &PORTA, &PORTA, &PORTA, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTD, &PORTG, &PORTG, &PORTG, &PORTL, &PORTL, &PORTL, &PORTL, &PORTL, &PORTL, &PORTL, &PORTL, &PORTB, &PORTB, &PORTB, &PORTB, &PORTF, &PORTF, &PORTF, &PORTF, &PORTF, &PORTF, &PORTF, &PORTF, &PORTK, &PORTK, &PORTK, &PORTK, &PORTK, &PORTK, &PORTK, &PORTK,};
    constexpr Register ddrList[]  = {&DDRE, &DDRE, &DDRE, &DDRE, &DDRG, &DDRE, &DDRH, &DDRH, &DDRH, &DDRH, &DDRB, &DDRB, &DDRB, &DDRB, &DDRJ, &DDRJ, &DDRH, &DDRH, &DDRD, &DDRD, &DDRD, &DDRD, &DDRA, &DDRA, &DDRA, &DDRA, &DDRA, &DDRA, &DDRA, &DDRA, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC, &DDRD, &DDRG, &DDRG, &DDRG, &DDRL, &DDRL, &DDRL, &DDRL, &DDRL, &DDRL, &DDRL, &DDRL, &DDRB, &DDRB, &DDRB, &DDRB, &DDRF, &DDRF, &DDRF, &DDRF, &DDRF, &DDRF, &DDRF, &DDRF, &DDRK, &DDRK, &DDRK, &DDRK, &DDRK, &DDRK, &DDRK, &DDRK,};
    constexpr Register pinList[]  = {&PINE, &PINE, &PINE, &PINE, &PING, &PINE, &PINH, &PINH, &PINH, &PINH, &PINB, &PINB, &PINB, &PINB, &PINJ, &PINJ, &PINH, &PINH, &PIND, &PIND, &PIND, &PIND, &PINA, &PINA, &PINA, &PINA, &PINA, &PINA, &PINA, &PINA, &PINC, &PINC, &PINC, &PINC, &PINC, &PINC, &PINC, &PINC, &PIND, &PING, &PING, &PING, &PINL, &PINL, &PINL, &PINL, &PINL, &PINL, &PINL, &PINL, &PINB, &PINB, &PINB, &PINB, &PINF, &PINF, &PINF, &PINF, &PINF, &PINF, &PINF, &PINF, &PINK, &PINK, &PINK, &PINK, &PINK, &PINK, &PINK, &PINK,};
  //    #endif
  
  #else
    #error “This AVR type is currently not yet supported.”
  #endif


class GrayEncoder
{
  protected:
    byte const Pin_A;         // Phase A
    byte const Pin_B;         // Phase B
    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
            
    Register getPort(byte pin) {
      return portList[pin];
    }

    byte getMaske(byte pin) {
      return pinMaske[pin];
    }
        
    int getPhases() {
      int n = 0;                      // new

      Phase_A = (*getPort(Pin_A) & getMaske(Pin_A)) >> 0;  // einzelnes Bit heraus fischen
      Phase_B = (*getPort(Pin_B) & getMaske(Pin_B)) >> 1;
      
      if ( Phase_A ) n = 3;
      if ( Phase_B ) n ^= 1;          // convert gray to binary
      return n;
    }

  public:
    GrayEncoder (byte _A, byte _B): 
      Pin_A(_A),
      Pin_B(_B),
      abs_counter(0),               // Zähler
      direction(0)                  // Richtungsanzeige  +1 / -1
    { }

    void init()
    {
      last = getPhases();           // power on state
      enc_delta = 0;
    }

    void encode()
    {
      int n = getPhases();
      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 B
    }
};

// ------------------------------------------------------------------------------------

GrayEncoder Encoder1(37, 36);            // Phase A/B, Pin 37/36 > Port.C Bit.0 / Bit.1

int Encoder1_Direction;
int Encoder1_AbsCounter;
byte Encoder1_PhaseA;
byte Encoder1_PhaseB;


void setup() {
  Serial.begin(9600);

  pinMode(36, INPUT_PULLUP);
  pinMode(37, INPUT_PULLUP);
  Encoder1.init();
}

void loop() {

  update_Encoder();

  Ausgabe();
  
  serieller_Monitor();  // zum debuggen hervorgeholt
}


// ****** Funktionen ******

void update_Encoder ()
{

  Encoder1.encode();
  Encoder1_Direction  = Encoder1.getDirection();
  Encoder1_PhaseA     = Encoder1.getA();
  Encoder1_PhaseB     = Encoder1.getB();
  Encoder1_AbsCounter = Encoder1.getAbsCounter();
}

void Ausgabe()
{
  static long Enc1_old_abs = 0;
  
  if (Encoder1_AbsCounter != Enc1_old_abs) {
    serieller_Monitor();
    Enc1_old_abs = Encoder1_AbsCounter;
  }
}


void serieller_Monitor ()
{
  Serial.print(Encoder1_Direction);       Serial.print('\t');
  Serial.print(Encoder1_PhaseA);          Serial.print('\t');
  Serial.print(Encoder1_PhaseB);          Serial.print('\t');
  Serial.print(Encoder1_AbsCounter);     
  Serial.println();
}

Dann muss man letztlich shiften. Mit der Maske isoliert man nur das gewünschte Bit.

bool(isoliertes_bit)

Hallo,

bool Trick, aha und gleich eingebaut. Danke.

Habe einen einfacheren überblickbaren Testsketch erstellt der das gleiche Verhalten zeigt. Vielleicht kann jetzt jemand helfen? Die Werte ändern sich nicht wenn ich langsam am Encoder drehe. Können auch Taster ran.

using Register = volatile byte *;

// UNO, Nano, Pro Mini usw.
  #if defined(__AVR_ATmega328P__) | defined(__AVR_ATmega328__) | defined(__AVR_ATmega168P__) | defined(__AVR_ATmega168__)
    constexpr byte pinMaske[]     = {0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1000000, 0b10000000, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000,};
    constexpr Register portList[] = {&PORTD, &PORTD, &PORTD, &PORTD, &PORTD, &PORTD, &PORTD, &PORTD, &PORTB, &PORTB, &PORTB, &PORTB, &PORTB, &PORTB, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC,};
    constexpr Register ddrList[]  = {&DDRD, &DDRD, &DDRD, &DDRD, &DDRD, &DDRD, &DDRD, &DDRD, &DDRB, &DDRB, &DDRB, &DDRB, &DDRB, &DDRB, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC,};
    constexpr Register pinList[]  = {&PIND, &PIND, &PIND, &PIND, &PIND, &PIND, &PIND, &PIND, &PINB, &PINB, &PINB, &PINB, &PINB, &PINB, &PINC, &PINC, &PINC, &PINC, &PINC, &PINC,};
  //    #endif
  
  // Leonardo, Micro, usw.
  #elif defined(__AVR_ATmega32U4__)
    constexpr byte pinMaske[]     = {0b100, 0b1000, 0b10, 0b1, 0b10000, 0b1000000, 0b10000000, 0b1000000, 0b10000, 0b100000, 0b1000000, 0b10000000, 0b1000000, 0b10000000, 0b1000, 0b10, 0b100, 0b1, 0b10000000, 0b1000000, 0b100000, 0b10000, 0b10, 0b1, 0b10000, 0b10000000, 0b10000, 0b100000, 0b1000000, 0b1000000, 0b100000,};
    constexpr Register portList[] = {&PORTD, &PORTD, &PORTD, &PORTD, &PORTD, &PORTC, &PORTD, &PORTE, &PORTB, &PORTB, &PORTB, &PORTB, &PORTD, &PORTC, &PORTB, &PORTB, &PORTB, &PORTB, &PORTF, &PORTF, &PORTF, &PORTF, &PORTF, &PORTF, &PORTD, &PORTD, &PORTB, &PORTB, &PORTB, &PORTD, &PORTD,};
    constexpr Register ddrList[]  = {&DDRD, &DDRD, &DDRD, &DDRD, &DDRD, &DDRC, &DDRD, &DDRE, &DDRB, &DDRB, &DDRB, &DDRB, &DDRD, &DDRC, &DDRB, &DDRB, &DDRB, &DDRB, &DDRF, &DDRF, &DDRF, &DDRF, &DDRF, &DDRF, &DDRD, &DDRD, &DDRB, &DDRB, &DDRB, &DDRD, &DDRD,};
    constexpr Register pinList[]  = {&PIND, &PIND, &PIND, &PIND, &PIND, &PINC, &PIND, &PINE, &PINB, &PINB, &PINB, &PINB, &PIND, &PINC, &PINB, &PINB, &PINB, &PINB, &PINF, &PINF, &PINF, &PINF, &PINF, &PINF, &PIND, &PIND, &PINB, &PINB, &PINB, &PIND, &PIND,};
  // #endif
  
  // Mega
  #elif defined(__AVR_ATmega2560__) | defined(__AVR_ATmega1280__)
    constexpr byte pinMaske[]     = {0b1, 0b10, 0b10000, 0b100000, 0b100000, 0b1000, 0b1000, 0b10000, 0b100000, 0b1000000, 0b10000, 0b100000, 0b1000000, 0b10000000, 0b10, 0b1, 0b10, 0b1, 0b1000, 0b100, 0b10, 0b1, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1000000, 0b10000000, 0b10000000, 0b1000000, 0b100000, 0b10000, 0b1000, 0b100, 0b10, 0b1, 0b10000000, 0b100, 0b10, 0b1, 0b10000000, 0b1000000, 0b100000, 0b10000, 0b1000, 0b100, 0b10, 0b1, 0b1000, 0b100, 0b10, 0b1, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1000000, 0b10000000, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1000000, 0b10000000,};
    constexpr Register portList[] = {&PORTE, &PORTE, &PORTE, &PORTE, &PORTG, &PORTE, &PORTH, &PORTH, &PORTH, &PORTH, &PORTB, &PORTB, &PORTB, &PORTB, &PORTJ, &PORTJ, &PORTH, &PORTH, &PORTD, &PORTD, &PORTD, &PORTD, &PORTA, &PORTA, &PORTA, &PORTA, &PORTA, &PORTA, &PORTA, &PORTA, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTD, &PORTG, &PORTG, &PORTG, &PORTL, &PORTL, &PORTL, &PORTL, &PORTL, &PORTL, &PORTL, &PORTL, &PORTB, &PORTB, &PORTB, &PORTB, &PORTF, &PORTF, &PORTF, &PORTF, &PORTF, &PORTF, &PORTF, &PORTF, &PORTK, &PORTK, &PORTK, &PORTK, &PORTK, &PORTK, &PORTK, &PORTK,};
    constexpr Register ddrList[]  = {&DDRE, &DDRE, &DDRE, &DDRE, &DDRG, &DDRE, &DDRH, &DDRH, &DDRH, &DDRH, &DDRB, &DDRB, &DDRB, &DDRB, &DDRJ, &DDRJ, &DDRH, &DDRH, &DDRD, &DDRD, &DDRD, &DDRD, &DDRA, &DDRA, &DDRA, &DDRA, &DDRA, &DDRA, &DDRA, &DDRA, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC, &DDRD, &DDRG, &DDRG, &DDRG, &DDRL, &DDRL, &DDRL, &DDRL, &DDRL, &DDRL, &DDRL, &DDRL, &DDRB, &DDRB, &DDRB, &DDRB, &DDRF, &DDRF, &DDRF, &DDRF, &DDRF, &DDRF, &DDRF, &DDRF, &DDRK, &DDRK, &DDRK, &DDRK, &DDRK, &DDRK, &DDRK, &DDRK,};
    constexpr Register pinList[]  = {&PINE, &PINE, &PINE, &PINE, &PING, &PINE, &PINH, &PINH, &PINH, &PINH, &PINB, &PINB, &PINB, &PINB, &PINJ, &PINJ, &PINH, &PINH, &PIND, &PIND, &PIND, &PIND, &PINA, &PINA, &PINA, &PINA, &PINA, &PINA, &PINA, &PINA, &PINC, &PINC, &PINC, &PINC, &PINC, &PINC, &PINC, &PINC, &PIND, &PING, &PING, &PING, &PINL, &PINL, &PINL, &PINL, &PINL, &PINL, &PINL, &PINL, &PINB, &PINB, &PINB, &PINB, &PINF, &PINF, &PINF, &PINF, &PINF, &PINF, &PINF, &PINF, &PINK, &PINK, &PINK, &PINK, &PINK, &PINK, &PINK, &PINK,};
  //    #endif
#else
  #error “This AVR type is currently not yet supported.”
#endif


byte getMaske(byte pin) {
  return pinMaske[pin];
}
    
volatile byte *getPort(byte pin) {
  return portList[pin];
}   

bool value;

void setup()
{
  Serial.begin(9600);
   
  pinMode(37, INPUT_PULLUP);    // Pin 37, Port C, Bit 0
  pinMode(36, INPUT_PULLUP);    // Pin 36, Port C, Bit 1      
}


void loop()
{
  value = bool(*getPort(37) & getMaske(37));
  Serial.print(value); Serial.print(" ");
  
  value = bool(*getPort(36) & getMaske(36));
  Serial.println(value);

  delay(5);
}

Hallo,

ihr habt bestimmt darauf gewartet bis ich den Fehler selbst finde. :slight_smile:
Ich muss natürlich das PINx Register abfragen und nicht das PORTx Register.
Läuft. Jetzt gehts ans aufräumen.

Die besten Erkenntnisse sind die, die man selbst gewinnt :wink:

Gruß Tommy

Genau. Ich hoffe das bleibt hängen. Meistens das ist so. :)

Hallo nochmal,

ich habe versucht die Masken zur Compilezeit berechnen zulassen. Das mag er jedoch nicht.
Wenn ich die auskommentierten Codezeilen verwende erhalte ich diesen Fehler.

ALPS_EM20_Encoder_RelativCounter_G:60:37: error: non-static data member 'var' declared 'constexpr'
     constexpr byte var = Maske(Pin_A);

Wenn ich diesen Syntax ohne Klassen verwende klappt das.
Ist es innerhalb der Klasse mit constexpr überhaupt möglich?
Oder ist das Vorhaben eh sinnlos?

// Flash 3030 Byte, 422 Byte RAM

using Register = volatile byte *;

// UNO, Nano, Pro Mini usw.
#if defined(__AVR_ATmega328P__) | defined(__AVR_ATmega328__) | defined(__AVR_ATmega168P__) | defined(__AVR_ATmega168__)
  constexpr byte pinMaske[]     = {0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1000000, 0b10000000, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000,};
  constexpr Register portList[] = {&PORTD, &PORTD, &PORTD, &PORTD, &PORTD, &PORTD, &PORTD, &PORTD, &PORTB, &PORTB, &PORTB, &PORTB, &PORTB, &PORTB, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC,};
  constexpr Register ddrList[]  = {&DDRD, &DDRD, &DDRD, &DDRD, &DDRD, &DDRD, &DDRD, &DDRD, &DDRB, &DDRB, &DDRB, &DDRB, &DDRB, &DDRB, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC,};
  constexpr Register pinList[]  = {&PIND, &PIND, &PIND, &PIND, &PIND, &PIND, &PIND, &PIND, &PINB, &PINB, &PINB, &PINB, &PINB, &PINB, &PINC, &PINC, &PINC, &PINC, &PINC, &PINC,};
//    #endif

// Leonardo, Micro, usw.
#elif defined(__AVR_ATmega32U4__)
  constexpr byte pinMaske[]     = {0b100, 0b1000, 0b10, 0b1, 0b10000, 0b1000000, 0b10000000, 0b1000000, 0b10000, 0b100000, 0b1000000, 0b10000000, 0b1000000, 0b10000000, 0b1000, 0b10, 0b100, 0b1, 0b10000000, 0b1000000, 0b100000, 0b10000, 0b10, 0b1, 0b10000, 0b10000000, 0b10000, 0b100000, 0b1000000, 0b1000000, 0b100000,};
  constexpr Register portList[] = {&PORTD, &PORTD, &PORTD, &PORTD, &PORTD, &PORTC, &PORTD, &PORTE, &PORTB, &PORTB, &PORTB, &PORTB, &PORTD, &PORTC, &PORTB, &PORTB, &PORTB, &PORTB, &PORTF, &PORTF, &PORTF, &PORTF, &PORTF, &PORTF, &PORTD, &PORTD, &PORTB, &PORTB, &PORTB, &PORTD, &PORTD,};
  constexpr Register ddrList[]  = {&DDRD, &DDRD, &DDRD, &DDRD, &DDRD, &DDRC, &DDRD, &DDRE, &DDRB, &DDRB, &DDRB, &DDRB, &DDRD, &DDRC, &DDRB, &DDRB, &DDRB, &DDRB, &DDRF, &DDRF, &DDRF, &DDRF, &DDRF, &DDRF, &DDRD, &DDRD, &DDRB, &DDRB, &DDRB, &DDRD, &DDRD,};
  constexpr Register pinList[]  = {&PIND, &PIND, &PIND, &PIND, &PIND, &PINC, &PIND, &PINE, &PINB, &PINB, &PINB, &PINB, &PIND, &PINC, &PINB, &PINB, &PINB, &PINB, &PINF, &PINF, &PINF, &PINF, &PINF, &PINF, &PIND, &PIND, &PINB, &PINB, &PINB, &PIND, &PIND,};
// #endif

// Mega
#elif defined(__AVR_ATmega2560__) | defined(__AVR_ATmega1280__)
  constexpr byte pinMaske[]     = {0b1, 0b10, 0b10000, 0b100000, 0b100000, 0b1000, 0b1000, 0b10000, 0b100000, 0b1000000, 0b10000, 0b100000, 0b1000000, 0b10000000, 0b10, 0b1, 0b10, 0b1, 0b1000, 0b100, 0b10, 0b1, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1000000, 0b10000000, 0b10000000, 0b1000000, 0b100000, 0b10000, 0b1000, 0b100, 0b10, 0b1, 0b10000000, 0b100, 0b10, 0b1, 0b10000000, 0b1000000, 0b100000, 0b10000, 0b1000, 0b100, 0b10, 0b1, 0b1000, 0b100, 0b10, 0b1, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1000000, 0b10000000, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1000000, 0b10000000,};
  constexpr Register portList[] = {&PORTE, &PORTE, &PORTE, &PORTE, &PORTG, &PORTE, &PORTH, &PORTH, &PORTH, &PORTH, &PORTB, &PORTB, &PORTB, &PORTB, &PORTJ, &PORTJ, &PORTH, &PORTH, &PORTD, &PORTD, &PORTD, &PORTD, &PORTA, &PORTA, &PORTA, &PORTA, &PORTA, &PORTA, &PORTA, &PORTA, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTD, &PORTG, &PORTG, &PORTG, &PORTL, &PORTL, &PORTL, &PORTL, &PORTL, &PORTL, &PORTL, &PORTL, &PORTB, &PORTB, &PORTB, &PORTB, &PORTF, &PORTF, &PORTF, &PORTF, &PORTF, &PORTF, &PORTF, &PORTF, &PORTK, &PORTK, &PORTK, &PORTK, &PORTK, &PORTK, &PORTK, &PORTK,};
  constexpr Register ddrList[]  = {&DDRE, &DDRE, &DDRE, &DDRE, &DDRG, &DDRE, &DDRH, &DDRH, &DDRH, &DDRH, &DDRB, &DDRB, &DDRB, &DDRB, &DDRJ, &DDRJ, &DDRH, &DDRH, &DDRD, &DDRD, &DDRD, &DDRD, &DDRA, &DDRA, &DDRA, &DDRA, &DDRA, &DDRA, &DDRA, &DDRA, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC, &DDRD, &DDRG, &DDRG, &DDRG, &DDRL, &DDRL, &DDRL, &DDRL, &DDRL, &DDRL, &DDRL, &DDRL, &DDRB, &DDRB, &DDRB, &DDRB, &DDRF, &DDRF, &DDRF, &DDRF, &DDRF, &DDRF, &DDRF, &DDRF, &DDRK, &DDRK, &DDRK, &DDRK, &DDRK, &DDRK, &DDRK, &DDRK,};
  constexpr Register pinList[]  = {&PINE, &PINE, &PINE, &PINE, &PING, &PINE, &PINH, &PINH, &PINH, &PINH, &PINB, &PINB, &PINB, &PINB, &PINJ, &PINJ, &PINH, &PINH, &PIND, &PIND, &PIND, &PIND, &PINA, &PINA, &PINA, &PINA, &PINA, &PINA, &PINA, &PINA, &PINC, &PINC, &PINC, &PINC, &PINC, &PINC, &PINC, &PINC, &PIND, &PING, &PING, &PING, &PINL, &PINL, &PINL, &PINL, &PINL, &PINL, &PINL, &PINL, &PINB, &PINB, &PINB, &PINB, &PINF, &PINF, &PINF, &PINF, &PINF, &PINF, &PINF, &PINF, &PINK, &PINK, &PINK, &PINK, &PINK, &PINK, &PINK, &PINK,};
//    #endif

#else
  #error “This AVR type is currently not yet supported.”
#endif

constexpr byte Maske(byte pin) {
  return pinMaske[pin];
}
     
class GrayEncoder
{
  protected:
    byte const Pin_A;           // Phase A
    byte const Pin_B;           // Phase B
    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
            
    Register getInPort(byte pin) {
      return pinList[pin];
    }
    
    byte getMaske(byte pin) {
      return pinMaske[pin];
    }

/*    
    constexpr byte var = Maske(Pin_A);
*/

    int getPhases() {
      int n = 0;                      // new

      // Phase_A = bool(*getInPort(Pin_A) & var);              // Test
      
      Phase_A = bool(*getInPort(Pin_A) & getMaske(Pin_A));              // Test
      Phase_B = bool(*getInPort(Pin_B) & getMaske(Pin_B));  // die Zeile funktioniert
      
      if ( Phase_A ) n = 3;
      if ( Phase_B ) n ^= 1;          // convert gray to binary
      return n;
    }

  public:
    GrayEncoder (byte _A, byte _B): 
      Pin_A(_A),
      Pin_B(_B),
      abs_counter(0),               // Zähler
      direction(0)                  // Richtungsanzeige  +1 / -1
    { }

    void init()
    {
      //pinMode(Pin_A, INPUT_PULLUP);   // spart in setup 4 Byte Flash
      //pinMode(Pin_B, INPUT_PULLUP);
      last = getPhases();           // power on state
      enc_delta = 0;
    }

    void encode()
    {
      int n = getPhases();
      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 >> 2;  // absoluten Zählwert abfragen
    }

    int getA()  {
      return Phase_A;  // Signal von Phase A
    }

    int getB()  {
      return Phase_B;  // Signal von Phase B
    }
};

// ------------------------------------------------------------------------------------

GrayEncoder Encoder1(37, 36);            // Phase A/B, Pin 37/36 > Port.C Bit.0 / Bit.1

int Encoder1_Direction;
int Encoder1_AbsCounter;
byte Encoder1_PhaseA;
byte Encoder1_PhaseB;


void setup() {
  Serial.begin(9600);

  pinMode(36, INPUT_PULLUP);
  pinMode(37, INPUT_PULLUP);
  Encoder1.init();
}

void loop() {

  update_Encoder();

  Ausgabe();
  
}


// ****** Funktionen ******

void update_Encoder ()
{

  Encoder1.encode();
  Encoder1_Direction  = Encoder1.getDirection();
  Encoder1_PhaseA     = Encoder1.getA();
  Encoder1_PhaseB     = Encoder1.getB();
  Encoder1_AbsCounter = Encoder1.getAbsCounter();
}

void Ausgabe()
{
  static long Enc1_old_abs = 0;
  
  if (Encoder1_AbsCounter != Enc1_old_abs) {
    serieller_Monitor();
    Enc1_old_abs = Encoder1_AbsCounter;
  }
}


void serieller_Monitor ()
{
  Serial.print(Encoder1_Direction);       Serial.print('\t');
  Serial.print(Encoder1_PhaseA);          Serial.print('\t');
  Serial.print(Encoder1_PhaseB);          Serial.print('\t');
  Serial.print(Encoder1_AbsCounter);     
  Serial.println();
}

ich habe versucht die Masken zur Compilezeit berechnen zulassen.

Nöö, das versuchst du nicht... OK, du versuchst es, aber so gehts nicht.

Denn obwohl konstant, kann/wird sich der Pin doch von Instanz zu Instanz unterscheiden. Und die Instanzen werden halt zur Laufzeit angelegt.

Die einzige mir bekannte Möglichkeit ist es, den Pin, als Teil des Datentypes, als Teil der Klassen Definition, zu verwenden. --> Templates.

Hallo,

wenn das so ist verschwende ich daran keine Minute mehr. Danke Dir & Euch.

Doc_Arduino: wenn das so ist verschwende ich daran keine Minute mehr.

Warum?

Da eine Template Klasse draus zu machen, ist furzpupen einfach! Und alle deine/diese Sorgen sind Schnee von Gestern.

Die Pins werden zur Kompilezeit übergeben, und der Kompiler kann den Code bis zum abwinken optimieren.

Beispiel:

using Register = volatile byte *;

// UNO, Nano, Pro Mini usw.
#if defined(__AVR_ATmega328P__) | defined(__AVR_ATmega328__) | defined(__AVR_ATmega168P__) | defined(__AVR_ATmega168__)
  constexpr byte pinMaske[]     = {0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1000000, 0b10000000, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000,};
  constexpr Register portList[] = {&PORTD, &PORTD, &PORTD, &PORTD, &PORTD, &PORTD, &PORTD, &PORTD, &PORTB, &PORTB, &PORTB, &PORTB, &PORTB, &PORTB, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC,};
  constexpr Register ddrList[]  = {&DDRD, &DDRD, &DDRD, &DDRD, &DDRD, &DDRD, &DDRD, &DDRD, &DDRB, &DDRB, &DDRB, &DDRB, &DDRB, &DDRB, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC,};
  constexpr Register pinList[]  = {&PIND, &PIND, &PIND, &PIND, &PIND, &PIND, &PIND, &PIND, &PINB, &PINB, &PINB, &PINB, &PINB, &PINB, &PINC, &PINC, &PINC, &PINC, &PINC, &PINC,};
//    #endif

// Leonardo, Micro, usw.
#elif defined(__AVR_ATmega32U4__)
  constexpr byte pinMaske[]     = {0b100, 0b1000, 0b10, 0b1, 0b10000, 0b1000000, 0b10000000, 0b1000000, 0b10000, 0b100000, 0b1000000, 0b10000000, 0b1000000, 0b10000000, 0b1000, 0b10, 0b100, 0b1, 0b10000000, 0b1000000, 0b100000, 0b10000, 0b10, 0b1, 0b10000, 0b10000000, 0b10000, 0b100000, 0b1000000, 0b1000000, 0b100000,};
  constexpr Register portList[] = {&PORTD, &PORTD, &PORTD, &PORTD, &PORTD, &PORTC, &PORTD, &PORTE, &PORTB, &PORTB, &PORTB, &PORTB, &PORTD, &PORTC, &PORTB, &PORTB, &PORTB, &PORTB, &PORTF, &PORTF, &PORTF, &PORTF, &PORTF, &PORTF, &PORTD, &PORTD, &PORTB, &PORTB, &PORTB, &PORTD, &PORTD,};
  constexpr Register ddrList[]  = {&DDRD, &DDRD, &DDRD, &DDRD, &DDRD, &DDRC, &DDRD, &DDRE, &DDRB, &DDRB, &DDRB, &DDRB, &DDRD, &DDRC, &DDRB, &DDRB, &DDRB, &DDRB, &DDRF, &DDRF, &DDRF, &DDRF, &DDRF, &DDRF, &DDRD, &DDRD, &DDRB, &DDRB, &DDRB, &DDRD, &DDRD,};
  constexpr Register pinList[]  = {&PIND, &PIND, &PIND, &PIND, &PIND, &PINC, &PIND, &PINE, &PINB, &PINB, &PINB, &PINB, &PIND, &PINC, &PINB, &PINB, &PINB, &PINB, &PINF, &PINF, &PINF, &PINF, &PINF, &PINF, &PIND, &PIND, &PINB, &PINB, &PINB, &PIND, &PIND,};
// #endif

// Mega
#elif defined(__AVR_ATmega2560__) | defined(__AVR_ATmega1280__)
  constexpr byte pinMaske[]     = {0b1, 0b10, 0b10000, 0b100000, 0b100000, 0b1000, 0b1000, 0b10000, 0b100000, 0b1000000, 0b10000, 0b100000, 0b1000000, 0b10000000, 0b10, 0b1, 0b10, 0b1, 0b1000, 0b100, 0b10, 0b1, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1000000, 0b10000000, 0b10000000, 0b1000000, 0b100000, 0b10000, 0b1000, 0b100, 0b10, 0b1, 0b10000000, 0b100, 0b10, 0b1, 0b10000000, 0b1000000, 0b100000, 0b10000, 0b1000, 0b100, 0b10, 0b1, 0b1000, 0b100, 0b10, 0b1, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1000000, 0b10000000, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1000000, 0b10000000,};
  constexpr Register portList[] = {&PORTE, &PORTE, &PORTE, &PORTE, &PORTG, &PORTE, &PORTH, &PORTH, &PORTH, &PORTH, &PORTB, &PORTB, &PORTB, &PORTB, &PORTJ, &PORTJ, &PORTH, &PORTH, &PORTD, &PORTD, &PORTD, &PORTD, &PORTA, &PORTA, &PORTA, &PORTA, &PORTA, &PORTA, &PORTA, &PORTA, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTD, &PORTG, &PORTG, &PORTG, &PORTL, &PORTL, &PORTL, &PORTL, &PORTL, &PORTL, &PORTL, &PORTL, &PORTB, &PORTB, &PORTB, &PORTB, &PORTF, &PORTF, &PORTF, &PORTF, &PORTF, &PORTF, &PORTF, &PORTF, &PORTK, &PORTK, &PORTK, &PORTK, &PORTK, &PORTK, &PORTK, &PORTK,};
  constexpr Register ddrList[]  = {&DDRE, &DDRE, &DDRE, &DDRE, &DDRG, &DDRE, &DDRH, &DDRH, &DDRH, &DDRH, &DDRB, &DDRB, &DDRB, &DDRB, &DDRJ, &DDRJ, &DDRH, &DDRH, &DDRD, &DDRD, &DDRD, &DDRD, &DDRA, &DDRA, &DDRA, &DDRA, &DDRA, &DDRA, &DDRA, &DDRA, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC, &DDRD, &DDRG, &DDRG, &DDRG, &DDRL, &DDRL, &DDRL, &DDRL, &DDRL, &DDRL, &DDRL, &DDRL, &DDRB, &DDRB, &DDRB, &DDRB, &DDRF, &DDRF, &DDRF, &DDRF, &DDRF, &DDRF, &DDRF, &DDRF, &DDRK, &DDRK, &DDRK, &DDRK, &DDRK, &DDRK, &DDRK, &DDRK,};
  constexpr Register pinList[]  = {&PINE, &PINE, &PINE, &PINE, &PING, &PINE, &PINH, &PINH, &PINH, &PINH, &PINB, &PINB, &PINB, &PINB, &PINJ, &PINJ, &PINH, &PINH, &PIND, &PIND, &PIND, &PIND, &PINA, &PINA, &PINA, &PINA, &PINA, &PINA, &PINA, &PINA, &PINC, &PINC, &PINC, &PINC, &PINC, &PINC, &PINC, &PINC, &PIND, &PING, &PING, &PING, &PINL, &PINL, &PINL, &PINL, &PINL, &PINL, &PINL, &PINL, &PINB, &PINB, &PINB, &PINB, &PINF, &PINF, &PINF, &PINF, &PINF, &PINF, &PINF, &PINF, &PINK, &PINK, &PINK, &PINK, &PINK, &PINK, &PINK, &PINK,};
//    #endif

#else
  #error "This AVR type is currently not yet supported."
#endif

        constexpr Register getOutPort(const byte pin)
        {
          return portList[pin];
        };
        
        constexpr Register getDdrPort(const byte pin)
        {
          return ddrList[pin];
        };
        
        constexpr Register getInPort(const byte pin)
        {
          return pinList[pin];
        };
        
        
        constexpr byte getMaske(const byte pin)
        {
          return pinMaske[pin];
        };



template<byte pin_a, byte pin_b>     
class GrayEncoder
{
  protected:
    volatile long abs_counter;  // absoluter Zähler, nicht veränderbar
    int direction;              // Richtungsanzeige  +1 / -1
    int enc_delta;
    int last;
    bool Phase_A;               // erste Phase
    bool Phase_B;               // zweite Phase
    
    int getPhases() {
      int n = 0;                      // new

      // Phase_A = bool(*getInPort(Pin_A) & var);              // Test
      
      Phase_A = bool(*getInPort(pin_a)  &  getMaske(pin_a)); 
      Phase_B = bool(*getInPort(pin_b)  &  getMaske(pin_b));  
      
      if ( Phase_A ) n = 3;
      if ( Phase_B ) n ^= 1;          // convert gray to binary
      return n;
    }

  public:
    GrayEncoder(): 
      abs_counter(0),               // Zähler
      direction(0)                  // Richtungsanzeige  +1 / -1
    { }

    void init()
    {

      *getDdrPort(pin_a) &= ~getMaske(pin_a);
      *getOutPort(pin_a) |=  getMaske(pin_a);
      
      *getDdrPort(pin_b) &= ~getMaske(pin_b);
      *getOutPort(pin_b) |=  getMaske(pin_b);

      last = getPhases();           // power on state
      enc_delta = 0;
    }

    void encode()
    {
      int n = getPhases();
      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 >> 2;  // absoluten Zählwert abfragen
    }

    int getA()  {
      return Phase_A;  // Signal von Phase A
    }

    int getB()  {
      return Phase_B;  // Signal von Phase B
    }
};

// ------------------------------------------------------------------------------------

GrayEncoder<37,36> Encoder1;            // Phase A/B, Pin 37/36 > Port.C Bit.0 / Bit.1

int Encoder1_Direction;
int Encoder1_AbsCounter;
byte Encoder1_PhaseA;
byte Encoder1_PhaseB;


void setup() {
  Serial.begin(9600);

  Encoder1.init();
}

void loop() {

  update_Encoder();

  Ausgabe();
  
}


// ****** Funktionen ******

void update_Encoder ()
{

  Encoder1.encode();
  Encoder1_Direction  = Encoder1.getDirection();
  Encoder1_PhaseA     = Encoder1.getA();
  Encoder1_PhaseB     = Encoder1.getB();
  Encoder1_AbsCounter = Encoder1.getAbsCounter();
}

void Ausgabe()
{
  static long Enc1_old_abs = 0;
  
  if (Encoder1_AbsCounter != Enc1_old_abs) {
    serieller_Monitor();
    Enc1_old_abs = Encoder1_AbsCounter;
  }
}


void serieller_Monitor ()
{
  Serial.print(Encoder1_Direction);       Serial.print('\t');
  Serial.print(Encoder1_PhaseA);          Serial.print('\t');
  Serial.print(Encoder1_PhaseB);          Serial.print('\t');
  Serial.print(Encoder1_AbsCounter);     
  Serial.println();
}

Es kompiliert, auf korrekte Funktion habe ich nicht getestet.

Der Sketch verwendet 2476 Bytes (0%) des Programmspeicherplatzes. Das Maximum sind 253952 Bytes.
Globale Variablen verwenden 210 Bytes (2%) des dynamischen Speichers, 7982 Bytes für lokale Variablen verbleiben.

Statt: Flash 3030 Byte, 422 Byte RAM