New approach to Rotary Encoder


Closed Thread
Results 1 to 40 of 91

Hybrid View

  1. #1
    Join Date
    Aug 2005
    Location
    Michigan, USA
    Posts
    224


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    Quote Originally Posted by aratti View Post
    @Mike K8LH

    The PBP manual they give me with PBP ver 2.47. But you can Find it also at page 168 of PBP3 manual.
    I wonder if there may be a problem with the PBP3 manual at http://www.pbp3.com/downloads/PBP_Reference_Manual.pdf? It seems to stop downloading at 731 kB (consistently)... Argh!!!

  2. #2
    Join Date
    Nov 2003
    Location
    Wellton, U.S.A.
    Posts
    5,924


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    Works fine here. I just opened it in my browser.
    Dave
    Always wear safety glasses while programming.

  3. #3
    Join Date
    Aug 2005
    Location
    Michigan, USA
    Posts
    224


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    Quote Originally Posted by mackrackit View Post
    Works fine here. I just opened it in my browser.
    Ok, it worked today... I've got it...

  4. #4
    Join Date
    May 2008
    Location
    Italy
    Posts
    825


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    Here I post an update of the code posted in #18. This new code has a more efficient ISR so it can read at higher frequency. I don't know the maximum frequency that the system can acheive, so if someone with some spare time will give a try and post the result, could be useful.

    As the previuos code, the mainloop doesn't do much, it simply update the display.

    Here the code revised:
    Code:
    ' PicBasic program to demonstrate how to read an optical encoder
    ' in quadrature. The code uses a 2 lines LCD in 4-bits mode 
    '                 **** MCU USED: PIC 16F628 ***
    '
    ' ------------------ LCD should be connected as follows -------------------
    '       LCD     PIC Port
    '       ---     --------
    '       DB4     PortA.0
    '       DB5     PortA.1
    '       DB6     PortA.2
    '       DB7     PortA.3
    '       RS      PortA.4 (add 4.7K pullup resistor to 5 volts)
    '       E       PortB.0
    '       RW      Ground
    '       Vdd     5 volts
    '       Vss     Ground
    '       Vo      20K potentiometer (or ground)
    '       DB0-3   No connected
    
    '-------------------------------------------------------------------------
    ' Encoder channel A     PortB.6  (use pullups resistor if necessary)
    ' Encoder channel B     PortB.7  (use pullups resistor if necessary)
    ' N/U                   PortB.0  (output)
    ' N/U                   PortB.1  (output)
    ' N/U                   PortB.2  (output)
    ' N/U                   PortB.3  (output)
    ' N/U                   PortB.4  (input - to be grounded)
    ' N/U                   PortB.5  (input - to be grounded)
    '
    '-------------------------------------------------------------------------
    
    INCLUDE "DT_INTS-14.bas"    ' Base Interrupt System  (by Darrel Taylor)
    
    DEFINE OSC 20
    
    eeprom 0,[2,0,3,1,1,3,0,2]
    
    Define LCD_DREG PORTA
    Define LCD_DBIT 0
    Define LCD_RSREG PORTA
    define LCD_RSBIT 4
    define LCD_EREG PORTB
    define LCD_EBIT 0
    define LCD_BITS 4
    define LCD_LINES 2
    define LCD_COMMANDUS 2000
    define LCD_DATAUS 50
    
    CMCON = %00000111
    TrisA = %00000000
    TrisB = %11110000
    PortB = 0
    
    Flag                var bit
    wsave               VAR BYTE    $70     SYSTEM  ' alternate save location for W 
    Q_New               var Byte
    Q_Old               var byte
    M_Count             var byte [4]
    P_Count             var byte [4]
    Q_Count             var word
    
    ' ---------------------- Set variable value @ startup ----------------------  
         
    For Q_Old = 0 to 3
    Read Q_Old,M_Count[Q_Old]
    Read Q_Old + 4,P_Count[Q_Old]
    Next Q_Old
         
      Q_Count = 0   
        Q_New = 0
        Q_Old = 0
         Flag = 0  
          
    ASM
    INT_LIST  macro    ; IntSource,        Label,  Type,  Resetflag?                
            INT_Handler    RBC_INT,  _Encoder,   ASM,  yes       
        endm
        INT_CREATE                   ; Creates the interrupt processor
    ENDASM
    
    @ INT_ENABLE RBC_INT            ; enable external (INT) interrupts
    
    '---------------------------- Initialize LCD ----------------------------
    
    Lcdout $fe, 1                               ' Clear LCD screen
    Lcdout "System Ready"                       ' Display message
    Pause 500                                   ' Wait .5 second
    
    Goto Main_Loop
    
    Encoder:                                    ' ISR 
    
    Q_New = PortB.7 + PortB.7 + PortB.6         ' get port status
     
    If M_Count[Q_Old] = Q_New then              ' if M_Count code satisfied then minus
              Q_Count = Q_Count - 1
                 Flag = 1                       ' set flag to true to update display
    goto Q_Skip
    endif
    
    If P_Count[Q_Old] = Q_New then              ' if M_Count code satisfied then plus
              Q_Count = Q_Count + 1
                 Flag = 1                       ' set flag to true to update display
    endif
    
    Q_Skip:
    
    Q_Old = Q_New                               ' update Q_Old Byte
     
    @ INT_RETURN
    
    Main_Loop:   
    
    if Flag = 1 then
    Lcdout $fe, 1                              ' Clear LCD screen
    lcdout dec Q_Count                         ' Display encoder position (counts)
    Flag = 0                                   ' reset flag to false, display updated
    endif
    
    goto Main_Loop
    
    end
    Cheers

    Al.
    All progress began with an idea

  5. #5
    Join Date
    Oct 2009
    Location
    Utah, USA
    Posts
    427


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    Thanks! Aratti...

    I had just finished adapting your earlier example for a 16F690 pic. It took me a while to figure out why my LCD was not working... Dang MCLR pin tripped me up untill I rememberd that it could not act as an output... then I had to move my LCD to PortC... then I had to figure out that my OLD 4 line LCD (bought it about 20 Years ago from AllElectronics) needed more time on the LCD_COMMANDUS.

    Anyway it is working GREAT...
    I will give your latest code a spin this weekend.

    As far as update time to the LCD... it seems to be limited to any Pause or other code that is in the Main Loop. I had been blinking an LED in the main loop using a Pause statement and therefore this limited the LCD update frequency. I think I'll try and impliment another DT-Int using a timer to run the blinking LED in the main loop. This should remove any excessive delay to the LCD update.

    PS. I can post Aratti's modified working code for the 16F690 if anybody is interested...
    Last edited by Heckler; - 9th November 2011 at 14:14.
    Dwight
    These PIC's are like intricate puzzles just waiting for one to discover their secrets and MASTER their capabilities.

  6. #6
    Join Date
    Aug 2005
    Location
    Michigan, USA
    Posts
    224


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    Quote Originally Posted by Heckler View Post
    .... As far as update time to the LCD... it seems to be limited to any Pause or other code that is in the Main Loop. I had been blinking an LED in the main loop using a Pause statement and therefore this limited the LCD update frequency. I think I'll try and impliment another DT-Int using a timer to run the blinking LED in the main loop. This should remove any excessive delay to the LCD update.
    May I offer insight into another way around this problem? I've always been concerned about the overhead of printing to an HD44780 compatible character display. For example, if you tie up the processor for 400 usecs while printing eight (8) characters to the LCD, you might have a problem with another process that needs to run at 100 usec intervals. Instead of updating the display the usual way, with a 40 usec delay between each write, why not refresh the LCD from a 32 character buffer as a background task using interrupts. I did this recently on a TI MSP430 Launchpad project and it worked very well.

    Here's the basic idea (C code). Your main program simply writes ASCII data into a 32 character array to update the display. Array elements 0-15 and 16-31 are mapped to LCD lines 1 and 2, respectively. The driver in the ISR only writes one character at a time from the array to the LCD during each interrupt, but I used a 500 usec interrupt interval so the entire display is actually updated around 59 times each second (updates are perceived as instantaneous). Also note that the PutLCD routine (not shown) does not need to include the normal 40 usec LCD inter-character delay.

    Food for thought... Regards, Mike

    Code:
        unsigned char lcd[32] = { "                                " };
    Code:
        void interrupt()
        {                               // 500 us TMR2 interrupts
          static char bndx = 0x00;      // lcd display buffer index, 0..31
          static char line = 0xC0;      // lcd display DDRAM address
    
          pir1.TMR2IF = 0;              // clear TMR2 interrupt flag
       /*                                                                   *
        *  refresh one character on the display each interrupt.  entire     *
        *  display refreshed every 17 msecs (58.8 Hz refresh rate).         *
        *                                                                   */
          if(line.7)                    // if "new line"
            PutLCD(line ^= 64,0);       // toggle LCD DDRAM "line" address
          else                          // not "new line" so
            PutLCD(lcd[bndx++],1);      // refresh display, bump index
          bndx &= 31;                   // pseudo mod 31, 0..31 inclusive
          if((bndx & 15) == 0)          // if new line (0 or 16)
            line.7 ^= 1;                // toggle b7 pseudo "new line" flag
        }
    Last edited by Mike, K8LH; - 12th November 2011 at 05:15.

  7. #7
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,838


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    For some peculiar reason that I cannot understand, Al's code is counting +/- 4 steps instead of one for each click.

    Anyone can speculate why?

    With a logic analyzer I have confirmed that the encoder is working fine. Here is a snapshot for 4 clicks of the encoder.

    Name:  screenshot.png
Views: 8676
Size:  165.5 KB

    Ioannis

Members who have read this thread : 2

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