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:
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.
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
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:
i use technique reading encoder:
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.
- 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
Post a Comment