Reading a Quad encoder and converting to a function


hi all,


i have project want incorporate rotary encoder purpose of making selections midi presets.  i'm sort of sick of hunting around , trying libraries time decided try hand @ writing own code reading quadrature encoder (mechanical, not opto), 1 specific: link

i have sketch works ok , nice , simple want do:

code: [select]

//manually read quadrature encoder

int enca = 2;
int encb = 3;

byte  bits;
byte  oldbits;
int value = 0;

void setup() {

  serial.begin(9600);

  pinmode (enca, input_pullup);
  pinmode (encb, input_pullup);

}

void loop() {

  bits = digitalread(enca) << 1 | digitalread(encb);

  if (bits == b00 && oldbits == b10)
  {
    value++;
    publish();
    while (bits != b11)
    {
      bits = digitalread(enca) << 1 | digitalread(encb);
    }

  }
  else if (bits == b00 && oldbits == b01)
  {
    value--;
    publish();
    while (bits != b11)
    {
      bits = digitalread(enca) << 1 | digitalread(encb);
    }
  }

  oldbits = bits;

} // end loop


void publish(){

  serial.print(value);
  serial.print("\t");
  serial.print(bits,bin);

  serial.print("\t");
  serial.println(oldbits,bin);
}




it works pretty well.  i'm reading 2 inputs , converting them nibble , doing if logic determine if shaft rotating , in direction.  while statements force loop wait total 180 degree encoder cycle finish before proceeding - acts debounce switches , prevent duplicate values getting.  can give details on encoder behavior if need be.  problem want call functionality in various places , different variables, want convert self contained function.  isn't going well.

code: [select]
//manually read quadrature encoder

int enca = 2;
int encb = 3;
int sum;
int starterval = 3;

void setup() {

  serial.begin(9600);

  pinmode (enca, input_pullup);
  pinmode (encb, input_pullup);

}

void loop() {

  sum = encoder(starterval);
  serial.println(sum);

}
int encoder(int value){

  byte  bits;
  byte  oldbits;
  int result;

  bits = digitalread(enca) << 1 | digitalread(encb);

  if (bits == b00 && oldbits == b10)
  {
    value++;
    while (bits != b11)
    {
      bits = digitalread(enca) << 1 | digitalread(encb);
    }

  }
  else if (bits == b00 && oldbits == b01)
  {
    value--;
    while (bits != b11)
    {
      bits = digitalread(enca) << 1 | digitalread(encb);
    }
  }

  oldbits = bits;

  return result;
}



i've been trouble shooting day i'm getting no return @ all, zeros, alternating 257 , 514 values!  there obvious errors @ point.  can nudge me in right direction?



brian

when handling encoder crucial inputs read @ least once every change. can done in 2 ways:
  • polling inputs in tight loop without any blocking code
  • using interrupts

i use technique reading encoder:
code: [select]

const char enctable[16] ={0, 1, -1, -0, -1, 0, -0, 1, 1, -0, 0, -1, -0, -1, 1, 0};//gives -1, 0 or 1 depending on encoder movement
byte encstate;//remembering encoder output , acting index enctable[]
byte inp;
long actpos;//encoder position

void loop(){
    //aquire input values
    inp = digitalread(pina)|(digitalread(pinb)<<1);
    encstate = ((encstate<<2)|((inp)&3))&15;//use encoder bits , last state form index
    actpos += enctable[encstate];//update actual position on encoder movement
}//loop()

the same technique can used in interrupt remember declare variable in interrupt routine volatile. also, since pin numbers determined can read input pins (pin 2&3 equal pind 2 & 3) directly instead of using digitalread() faster.
code: [select]
const char enctable[16] ={0, 1, -1, -0, -1, 0, -0, 1, 1, -0, 0, -1, -0, -1, 1, 0};//gives -1, 0 or 1 depending on encoder movement
byte encstate;//remembering encoder output , acting index enctable[]
byte inp;
volatile long actpos;//encoder position


void setup(){
    serial.begin(115200);
    attachinterrupt(0, updateenc, change);//monitor pin 2
    attachinterrupt(1, updateenc, change);//monitor pin 3
}//setup()

void loop(){
  serial.println(actpos);//report positioin twice second
  delay(500);
}//loop()

void updateenc(){
  encstate = ((encstate<<2)|((pind>>2)&3))&15;//use encoder bits , last state form index
  actpos += enctable[encstate];//update actual position on encoder movement
}//updateenc()


Arduino Forum > Using Arduino > Programming Questions > Reading a Quad encoder and converting to a function


arduino

Comments

Popular posts from this blog

invalid use of void expresion in FlexiTimer2 library

error: a function-definition is not allowed here before '{' token

LED Strip Code