1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

Quadrature Encoder Debounce in ASM

Discussion in 'Code Repository' started by Mosaic, May 30, 2014.

  1. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    8,571
    Likes:
    820
    Location:
    Rochdale UK
    Ok! I concede!! But just don't use a gray wheel decoder or it will just count up and down repeatedly!!!
     
  2. JimB

    JimB Super Moderator Most Helpful Member

    Joined:
    Sep 11, 2004
    Messages:
    6,096
    Likes:
    551
    Location:
    Peterhead, Scotland
    That is a fair comment.
    I guess that Gray codes give an absolute position, whereas the Quad code gives a relative position and is often used in conjunction with an index pulse to define a fixed position.

    The only place where I have seen Gray codes used was in a remote display for a tank* level measurement system.

    * A BIG oil storage tank.
    If I remember correctly it had a float on the end of a steel wire.
    As the level went up/down, the steel wire turned around a drum which drove allsorts of gears and numbers for a local display, and a GrayCode disc for the remote display.

    JimB
     
  3. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    8,571
    Likes:
    820
    Location:
    Rochdale UK
    Gosh!! We seem to have dominated this thread..... Sorry Mosaic !!
     
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. Tony Stewart

    Tony Stewart Well-Known Member Most Helpful Member

    Joined:
    Aug 31, 2012
    Messages:
    3,069
    Likes:
    257
    Location:
    Richmond Hill , ON Canada near Toronto

    Gray wheel decoder is just direction and count pulse just like Quadrature. Not up and down, rather up OR down, Or CW or CCW. Or in the case of stepper motors Step in/out from Direction and step. It is a reversible process used everywhere , even wind direction and anenometers.
     
    Last edited: May 6, 2015
  6. manoj soorya

    manoj soorya Member

    Joined:
    Aug 23, 2014
    Messages:
    136
    Likes:
    1
    Hello

    can you somebody help to make the hex file from this code?

    Code (text):
     

    #include <stdint.h>
    #include <avr/pgmspace.h>
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/wdt.h>

    #define F_CPU 12000000
    #include <util/delay.h>

    #define DEPRESS_TIME    1

    #define sbi(sfr, bit)   ((sfr) |= _BV(bit))             // Set bit
    #define cbi(sfr, bit)   ((sfr) &= ~(_BV(bit)))          // Clear bit
    #define xbi(sfr, bit)   ((sfr) ^= _BV(bit))             // Flip bit
    #define rbi(sfr, bit)   (((sfr) >> (bit)) & 0x01)

    volatile uint8_t pcIntCurr = 0;
    volatile uint8_t pcIntLast = 0;
    volatile uint8_t pcIntMask = 0;

    volatile uint8_t timer0_ovf = 0;
    volatile uint8_t time_rot = 0;

    void doInt();

    int main() {
    cbi(DDRB, PCINT2);
    cbi(DDRB, PCINT3);

    TIMSK = (1<<TOIE0);                   // Eable timer overflow for Timer0
    TCNT0 = 0x00;                         // Set Timer0 to 0
    TCCR0B = (1<< CS02) | (1<<CS00);      // /1024 prescaler

    PORTB |= (( 1 << PCINT2 ) | ( 1 << PCINT3 )); //turn on pullups
    PCMSK |= (( 1 << PCINT2 ) | ( 1 << PCINT3 )); //enable encoder pins interrupt sources
    sei();
    GIMSK |= ( 1 << PCIE ); //enable pin change interupts

    DDRD |= ( 1 << PD4 );
    DDRD |= ( 1 << PD5 );
    DDRD |= ( 1 << PD6 );

    sbi(PORTD, PD6);
    _delay_ms(1000);
    cbi(PORTD, PD6);

    for (;;) {

    if (!time_rot) {
    cbi(PORTD, PD4);
    cbi(PORTD, PD5);
    }

    if (pcIntMask)
    doInt();
    }
    }

    void doInt() {
    xbi(PORTD, PD6);

    if (rbi(pcIntCurr, PCINT2) == 0 && rbi(pcIntCurr, PCINT3) == 0 && rbi(pcIntMask, PCINT2) ) {
    cbi(PORTD, PD5);
    sbi(PORTD, PD4);
    time_rot = 5;
    } else if (rbi(pcIntCurr, PCINT3) == 0 && rbi(pcIntCurr, PCINT2) == 0 && rbi(pcIntMask, PCINT3) ) {
    cbi(PORTD, PD4);
    sbi(PORTD, PD5);
    time_rot = 5;
    }

    pcIntMask = 0;
    }

    ISR(TIMER0_OVF_vect) {
    timer0_ovf++;

    if (time_rot) {
    time_rot--;
    }
    }

    ISR(PCINT_vect)
    {
    pcIntCurr = PINB;
    pcIntMask = pcIntCurr ^ pcIntLast;
    pcIntLast = pcIntCurr;
    }


    [code]

    thank you and this is the circuit I have[ATTACH]92380[/ATTACH] [ATTACH=full]92380[/ATTACH]
     
  7. manoj soorya

    manoj soorya Member

    Joined:
    Aug 23, 2014
    Messages:
    136
    Likes:
    1
    the circuit is here...

    rotaryencoder_schematic.png
     
  8. manoj soorya

    manoj soorya Member

    Joined:
    Aug 23, 2014
    Messages:
    136
    Likes:
    1
    Hello Friends

    Thank you for all the reply...

    I got this circuit from internet..Its completely working, I tested...


    Encoder Tester.GIF

    I atteached the hex file too...


    Thank you
     

    Attached Files:

  9. Mosaic

    Mosaic Well-Known Member

    Joined:
    Jun 3, 2010
    Messages:
    2,375
    Likes:
    87
    Location:
    Caribbean
    This is interesting:
    from : BobW


    Code (text):

        Code (asm):

        ; Encoder service routine
        ; for midrange PIC 12F, 16F...
        ; Inputs:
        ;    PortA,0 - Phase A input (position critical) - IOC
        ;    PortA,1 - Optional Index input
        ;    PortA,2 - Phase B input (position critical) - IOC
        ;
        ; Encoder variables:
        ;    CountH, CountL - High and Low byte of Encoder count
        ;    SaveA - Previous state of Phase A input
        ;
        EncdrSvc
            rrf portA,w      ;load, shift and save phase A
            rlf SaveA,f      ;new Phase B and “delayed” Phase A are now aligned
            xorwf SaveA,w    ;XOR to calculate direction
            andlw 0x02       ;mask off all but direction value which is either 0 or 2
            subwf CountL,f   ;subtract 0 or 2 from count depending on direction
            btfsc status,c
            incf CountH,f
            incfsz CountL,f  ;then add 1 to adjust the 0/+2 increment to +/-1
            decf CountH,f
     
     
    It is based on the fact that once a change of state of either encoder output (A or B) is detected (by means of the IOC—Interrupt On Change setting), then the direction of rotation can be determined by XORing the current state of one output with the previous state of the other output. This fully decodes every state transition, giving the maximum possible resolution. Note also that the PIC inputs are arranged for maximum efficiency. The above code doesn't include the standard ISR preamble and postamble, for saving and restoring the W and Status registers, which is still required .
     

Share This Page