[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [avr-chat] Using Rotary Encoders...
From: |
Richard Urwin |
Subject: |
Re: [avr-chat] Using Rotary Encoders... |
Date: |
Wed, 21 Sep 2005 17:31:07 +0100 |
User-agent: |
KMail/1.7.2 |
On Wednesday 21 Sep 2005 06:00, Vincent Trouilliez wrote:
> 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 mailing list
> address@hidden
> http://lists.nongnu.org/mailman/listinfo/avr-chat
--
Richard Urwin