[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[avr-chat] Using Rotary Encoders...
From: |
Vincent Trouilliez |
Subject: |
[avr-chat] Using Rotary Encoders... |
Date: |
Wed, 21 Sep 2005 07:00:30 +0200 |
Hi gents,
I would like your opinions/experiences about using rotary encoders. I
have planned on using one for my project, so ordered one to experiment
with (never used them before).
It's a mechanical one, with the usual 2-bit gray code output.
I was expecting loads of bounces, but got only a few glitches, so was
impressed by the quality of the unit despite the affordable price (under
6 Euros). Wanting to get rid of these few glitches and make it perfect,
I used a timer to allow 50ms for bounces to go away, plenty enough
according to the datasheet which stated 5ms max, and my observations on
the scope showing that pulses were mostly about 10 to 15ms wide max,
under normal conditions (ie, not turning it too slowly). So, 15+5 = 20,
50ms should cover any amount of bouncing.
However this is where the problem start : even with this huge delay, I
still get these glitches. Sometimes it will count 2 pulses instead of
one, or the count won't move, or it will decrement instead of
increment...
So since I have zero experience with these things, I don't really know
what to think:
1) The encoder works perfectly most of the time, and the glitches appear
even when I am turning the shaft slowly, one step at a time. So the
encoder must be okay, and my software has a bug.
2) The other way around : my programme is so simple, it can't go wrong,
and since the encoder has mechanical contacts, it's most likely at
fault, you get what you pay for, go fork out the cash for an optical
encoder.
3) The program is fine, the encoder "should" be glitch free, but you
just happen to have a faulty unit (I noticed that the shaft has too much
radial play to my taste, but then what do I know... ), just get another
one and you will be fine.
I pasted the relevant bits of my program below. I wired channel B on
INT0 and set it to trigger on a rising edge. Then in the ISR I increment
or decrement the counter, depending on the logic level of channel A
(going CW or CCW).
That worked fine (bar the random glitches). Then I added the 50ms delay
to see if that would improve things, but no :o(
I turn an LED on when the pulse/rising edge has been detected, and I
turn it off once the 50ms delay has elapsed. This produces a short flash
which I can about see. I just noticed, however, that whenever a glitch
happens, I get a BIG flash from the LED ! Now what does that mean, I
don't know exactly, but at least it gives me something to work on...
Any ideas/comments, are most welcome :-)
--
Vince
SIGNAL (SIG_INTERRUPT0)
{
PORTD = 0xFF; //turn LED on when the pulse has been detected
if ( PIND & _BV(PD6) ) //if Channel A is high
encoder_count++; //then the knob has been turned
clockwise
else
encoder_count--; //if not... then must have been CCW !!
;-)
GICR &= 0xBF; // disable encoder interrupt to avoid counting
bounces
TCNT0 = 0; //reset debounce timer
TIMSK |= _BV( OCIE0 ); //enable timer interrupt
}
SIGNAL (SIG_OUTPUT_COMPARE0)
{
PORTD = 0x00; //50ms debounce delay is over, turn LED off
TIMSK &= ! _BV( OCIE0 ); //disable timer interrupt
GICR |= _BV( INT0 ); //enable encoder interrupt again
}
void ioinit (void) {
DDRD = 0x20; //outputs : PD5 (LED), Inputs : PD6 (Encoder 'A'
channel)
//set up timer0
OCR0 = 50; // about 50ms delay
TCCR0 = 0x1D; // compare mode mode, prescaler = 1024
//set interrupts
GICR = 0x40; //enable INT0 interrupt (Encoder 'B' channel).
MCUCR = 0x03; //set INTO to trigger on rising edge
sei(); //enable global interrupts
}
int main (void){
ioinit ();
lcd_init();
while(TRUE){
lcd_goto_rc(1,1); //print counter value in top left
corner of the LCD
GICR &= ~( _BV( INT0 ) ); //disable INT0 interrupt while
reading counter contents
dot_two(encoder_count); // display counter content on the LCD
GICR |= ( _BV( INT0 ) ); //re-enable interrupt
_delay_ms(100); //simulate a busy main loop
}
}
- [avr-chat] Using Rotary Encoders...,
Vincent Trouilliez <=