decoding quadrature encoders


Closed Thread
Results 1 to 40 of 94

Hybrid View

  1. #1
    Join Date
    Oct 2004
    Location
    Italy
    Posts
    695


    Did you find this post helpful? Yes | No

    Default

    If you are losing encoder counts, then use an interrupt service routine.
    Four of PORTB’s pins, RB<7:4>, have an interrupt-onchange feature.
    Use two of these pins for the A/B encoder signals.

    Luciano

  2. #2
    ice's Avatar
    ice Guest


    Did you find this post helpful? Yes | No

    Default

    ok,heres my program ,using interrupts..

    the problems i'm encountering are below the code
    ..
    Code:
    DEFINE LOADER_USED 1
    
    
    led     VAR     PORTB.7
    old 			VAR BYTE
    new 			VAR BYTE
    direction_bit 	VAR BIT
    counter 		VAR WORD
    counter_1		VAR WORD
    counter_2		VAR WORD
    direction_store	VAR BIT
    adval			VAR	WORD				' Create adval to store result
    potval			VAR WORD
    servo_val		VAR	WORD
    difference		VAR WORD
    	
    
    counter=32500		
    	
        	HPwm 0,150,20000    
            OPTION_REG = $7f        
            ON INTERRUPT GoTo myint     ' Define interrupt handler
            INTCON = $90                     ' Enable INTE interrupt
    
    	
    
    loop:   High led                ' Turn LED on
    
    		LCDOut $fe,1,"count:"
    		LCDOut $fe,$c0,DEC counter
    		'Pause 10
    		
            GoTo loop               ' Do it forever
    
    
    
    
    		' Interrupt handler
            Disable                 ' No interrupts past this point
    myint:  Low led                 ' If we get here, turn LED off
           
           
    enc:    new= PORTB & %00000011
    
    
    start_1:
    		old=new & %00000011	
    		
    again:
    
    		new= PORTB & %00000011					'load new value of A/B channels into new by anding with HEX3
    			
    		
    	    'IF new=old Then again
    	    direction_bit=old.bit1 ^ new.bit0		'check direction 
    	
    		
    		IF direction_bit = 1 Then  
    		LCDOut $fe,1,"Last was CW"
    		counter = counter + 1				'increment counter
    		LCDOut $fe,$c0,DEC counter," ",BIN direction_bit
    	
    		Else
    			LCDOut $fe,1,"Last was CCW"
    			counter = counter - 1				'decrement counter
    			LCDOut $fe,$c0,DEC counter," ", BIN direction_bit	
    		
    		EndIF
    		Pause 10
    	   			
    
                  
    		INTCON.1 = 0           ' Clear interrupt flag
    	    Resume                 ' Return to main program
    	    Enable
    1>The interrupts are worng fine,however the code is still unable to distinguish between CW and CCW,because of which the counting goes awry..

    2>if i remove the "if then " statement for CW/CCW direction and only put a
    counter=counter+1,it works well


    The whole problem seems to be the direction decoding part..
    ..i cant seem to find a solution to it..
    Last edited by ice; - 3rd May 2005 at 14:00.

  3. #3
    Join Date
    Oct 2004
    Location
    Italy
    Posts
    695


    Did you find this post helpful? Yes | No

    Default

    Hi!

    1.
    You are using the wrong interrupt.
    Four of PORTB’s pins, RB<7:4>, have an interrupt-onchange feature.
    Use two of these pins for the A/B encoder signals.

    2.
    Use assembly code for the interrupt.
    (See PicBasic Pro manual).

    3.
    In your code the variables "new" and "old" will have
    most of the time the same values.

    In your code you are doing that:

    new= PORTB & %00000011 'get encoder A/B
    old=new & %00000011 'old is now same as new
    new= PORTB & %00000011 'get encoder A/B again

    When you get A/B again, it is very likely that the encoder is
    still in the same position, therefore the variables new and old
    will have the same values.

    * * * *

    Did you try the code I posted the 12th April 2005, 11:00?
    Does it work if you turn the encoder slowly?

    Luciano

  4. #4
    ice's Avatar
    ice Guest


    Did you find this post helpful? Yes | No

    Default

    Luciano,

    when i try the program u recommended [12th april] as below,
    there are alot of instances when the program gets confused with direction,
    so it sometime increments and decrements.Im not using interrupts

    when i move the motor slowly,the problem still persists.

    Code:
    old_val 		VAR BYTE
    new_val 		VAR BYTE
    direction_bit 	VAR BIT
    enc_counter 	VAR WORD
    adval			VAR	WORD				' Create adval to store result
    potval			VAR WORD
    servo_val		VAR	WORD
    difference		VAR WORD
    	
    TRISB=%11111111
    enc_counter=32500		
    HPwm 0,100,20000	
        
    	
    
    	new_val = PORTB & %00000011
    start:
    	old_val = new_val
    	
    	
    again:
    	new_val = PORTB & %00000011
    	'LCDOut $fe,1,"no move"
    	IF new_val = old_val Then again
    
    	direction_bit = old_val.bit0 ^ new_val.bit1
    	
    	IF direction_bit = 1 Then  
    	
    		LCDOut $fe,1,"Last was CW"
    		enc_counter = enc_counter + 1
    		LCDOut $fe,$c0,DEC enc_counter
    
    	Else
    		LCDOut $fe,1,"Last was CCW"
    		enc_counter = enc_counter - 1
    		LCDOut $fe,$c0,DEC enc_counter	
    	
    	EndIF
        	GoTo start
    Thank you for your responses
    Last edited by ice; - 4th May 2005 at 11:55.

  5. #5
    Join Date
    Oct 2004
    Location
    Italy
    Posts
    695


    Did you find this post helpful? Yes | No

    Default

    Hi!

    I need more info.

    The version of the PIC used. (16F628, 16F628A, ...).

    If you are using a commercial board for the PIC, I need
    the URL where I can see the board.

    The brand and model number of the encoder and the URL where I can
    download the data sheet.

    I also need to know how you have connected the encoder to
    PORTB.0 and PORTB.1. (Pull-up resistors? If yes, values).


    Luciano

  6. #6
    ice's Avatar
    ice Guest


    Did you find this post helpful? Yes | No

    Default

    Luciano,

    The version of the PIC used. (16F628, 16F628A, ...).
    im using the PIC16F873A

    If you are using a commercial board for the PIC, I need
    the URL where I can see the board.
    I made my own dev board..has an LCD,A/D..the usual features..
    works on a 4Mhz crystal..
    The board works perfectly as i have run accelerometers,D/A converters from the same board


    The brand and model number of the encoder and the URL where I can
    download the data sheet.
    Maxon 22578
    500 counts per turn
    http://www.maxonmotor.com/docsx/Down...f/05_238_e.pdf

    I also need to know how you have connected the encoder to
    PORTB.0 and PORTB.1. (Pull-up resistors? If yes, values).
    Pull up resistors
    with value 1.8K


    Thanks for all your help
    Last edited by ice; - 5th May 2005 at 08:39.

  7. #7
    ice's Avatar
    ice Guest


    Did you find this post helpful? Yes | No

    Default progress

    ok,a little progress,
    seems like i'm loosing counts ,because of the LCDout commands

    if i make my code tighter[remove the LCDcommands],i am able to monitor direction ,but a bit of interference still persists.
    I'm on a 4Mhz..i'll switch to a 20Mhz tomorrow and post my progress

Similar Threads

  1. Quick thoughts: DT Ints with encoders
    By kevlar129bp in forum mel PIC BASIC Pro
    Replies: 19
    Last Post: - 7th January 2010, 02:01
  2. PMDC SERVO MOTOR WITH quadrature encoder DRIVE ?
    By phoenix_1 in forum Schematics
    Replies: 37
    Last Post: - 22nd November 2009, 20:45
  3. 32-bit Quadrature Counter With Serial Interface
    By precision in forum mel PIC BASIC Pro
    Replies: 4
    Last Post: - 10th June 2008, 03:49
  4. quad encoders
    By cpayne in forum mel PIC BASIC Pro
    Replies: 0
    Last Post: - 13th March 2007, 18:49
  5. "momentary" IR decoding
    By sporker in forum mel PIC BASIC Pro
    Replies: 0
    Last Post: - 20th June 2005, 02:53

Members who have read this thread : 0

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts