avr-chat
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]