New approach to Rotary Encoder


Closed Thread
Page 1 of 3 123 LastLast
Results 1 to 40 of 91
  1. #1
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    4,036

    Default New approach to Rotary Encoder

    Here is an experiment on Rotary Encoders and a different approach than the standard XOR way.

    Code:
    loop1:
    if portb.1=0 then                 'here is switch 1 of the rotary encoder
        counter=counter+1
        goto lcd
    endif
    
    if portb.0=0 then                 'here is switch 2 of the rotary encoder
        counter=counter-1
        goto lcd
    endif
    
    goto loop1
    
    lcd:
    lcdout $fe,$c0,dec5 counter
    while (portb.0=0 or portb.1=0):pause 10:wend
    goto loop1
    The key is the last While/Wend command where it checks for the next pulse comming after the first edge of either switch of the encoder.

    Common of the encoder is Low and Pull Up is supposed to be active.

    Ioannis
    Last edited by Ioannis; - 8th December 2010 at 10:44. Reason: loop is reserved in 2.60 and later

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


    Did you find this post helpful? Yes | No

    Default

    Can you refresh our memory and show us an example of "the standard XOR way"?

  3. #3
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    4,036


    Did you find this post helpful? Yes | No

    Default

    Two examples in the attachments. They use Interrupts though. When I find some spare time I wll try to make the routines work with IOC and DT-INTS too.

    Ioannis
    Attached Files Attached Files

  4. #4
    Join Date
    Aug 2007
    Posts
    26


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    Did you try this code with mechanical encoder, or normal optical encoder?

  5. #5
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    4,036


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    That was with mechanical one.

    Ioannis

  6. #6
    Join Date
    Aug 2011
    Location
    Manaus - Brazil
    Posts
    24


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    With use 4 mecanic rotary encoder with this code (pic18f4550) ?

  7. #7
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    4,036


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    I don't see why not. Its fast enough.

    Ioannis

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


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    A question, please? With the following "while" statement, does the program wait there until both encoder pins are high? If so, then you're only detecting one of every four AB transitions when moving continually in one direction, correct?

    Code:
    while (portb.0=0 or portb.1=0):pause 10:wend
    Name:  Encoder AB States.png
Views: 10853
Size:  4.1 KB
    Last edited by Mike, K8LH; - 16th August 2011 at 02:55.

  9. #9
    Join Date
    Aug 2010
    Location
    Maryland, USA
    Posts
    869


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    Yes I think you are correct, this will only detect from 3 to 0 or 3 to 2. So it does not count in quadrature mode. It could be modified with a few more while loops to detect when it leaves the current state.
    -Bert

    The glass is not half full or half empty, Its twice as big as needed for the job!

    http://foamcasualty.com/ - Warbird R/C scratch building with foam!

  10. #10
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    4,036


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    I think not since there is OR in the WHILE statement.

    Ioannis

  11. #11
    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 Ioannis View Post
    I think not since there is OR in the WHILE statement.
    But doesn't the OR mean that you're stuck in this loop while either A OR B is low? In other words, you can only get out of the loop when both A and B are high?

  12. #12
    Join Date
    Jan 2005
    Location
    Montreal, Quebec, Canada
    Posts
    3,039


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    Yup, as long as one is LOW, it remains in the loop.

    Robert

  13. #13
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    4,036


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    Yes it will for the time that either is in LOW state. If there is a possibility that this condition is likely to happn pemanently, then you have other options to choose.

    As stated on he first post, that is an interesting experiment of another way (more simple) to do the same task. No-one is forced to accept it. Or use it. Just forget it and you will be just fine.

    Ioannis

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


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    Please forgive me if it seemed that I was complaining. I was just trying to understand how your method worked.

    If you're using a rotary encoder with detents as a control, detecting a single AB transition (out of four) between detents is probably preferable. That's how I do it but I use a switch state latch and simple parallel switch state logic to filter out the unwanted switch states.

    Your method is simple and elegant. Thank you for sharing with us...

    Cheerful regards, Mike

  15. #15
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    4,036


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    No problem Mike. I have to admit that I was a little touchy.

    Yes, the idea was to read a mechanical rotary encoder with detents. Sure is better to buffer the port states and then do the processing.

    Even better, use interrups to grab the port change and then do whatever you want. More, make a debounce based on interrupts since mechanical switch of the encoder do bounce a little. But this is for more advanced programmers. Maybe later when my related project allows.

    Ioannis

  16. #16
    Join Date
    Nov 2011
    Posts
    2


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    Hello world. I have learnt a lot from lurking these threads so i thought i would try and help someone else out a bit.




    All your encoder worries can be over for about 50 pence and if i can get a picture in here i will show you how...........

    Name:  encoder interface to pic.bmp
Views: 16874
Size:  442.0 KB

    the thing to realise is that moving along waveform A from left to right the negative edge of A is always when B is low. moving back the other way the negative edge is always when B is high.

    the jk flip flop clock input is negative edge triggered and when triggered it feeds the input on J through to Q -- but only if j and k inputs are opposite hence section 1 of the nor gate to invert the signal. j is always opposite to k now. and the clock input always gets triggered right in the middle of the high or low so it never misses.

    so, when moving clockwise Q will be high and anticlockwise it will go low.

    two other parts of the quad nor gate (2 and 3 above) to produce a hardware XOR on output C and producing the waveform at bottom of screen.

    Now all you need to do is feed C into an input that generates interrupts on a negative edge trigger. when the interrupt fires all it has to do is look at the level of D and either add 1 to clockwise total or subtract 1. Thats it. Your programming days are over.

    And, all the mushy signal edges and bounce are tidied up too. Lovely solid latched outputs.
    And you are going to have to go some to bother them with speed or with slowness.

    Not bad for 50p I hope you will agree.

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


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    Hey podgycode...
    I have not tried your circuit. I would guess it works as you describe.

    What I can't understand is why is this so difficult to do using two PIC pins and some code. Are these rotary encoders so difficult to read using code??

    I am struggling with this very thing myself. I have two rotary encoders... one that I have wired up and done some basic testing... one that I have not tried yet.

    I have also done quite a bit of searching over on the Parallax Basic Stamp forum, since the basic stamp uses VERY similar language to our PICbasic.

    I really would like to use interrupts (DT instant INT's, if possible)

    My real problem is TIME. If I only had more of it, I'm sure you all can relate.

    Any way, if anyone has some good sample code (that used interrupts) for one to try... that they might be willing to share
    Last edited by Heckler; - 4th November 2011 at 15:43.
    Dwight
    These PIC's are like intricate puzzles just waiting for one to discover their secrets and MASTER their capabilities.

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


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    Here the code for a rotary optical encoder, using quadrature.
    Just connect the Channel A to portB.6 and channel B to portB.7, ground portB.5 and portB.4

    Connection for LCD can be found to page 96 of PBP user manual.



    Code:
    include "ALLDIGITAL.pbp"
    INCLUDE "DT_INTS-14.bas"        ; Base Interrupt System
    'INCLUDE "ReEnterPBP.bas"        ; Include if using PBP interrupts
    
    DEFINE OSC 20
    
    '                       PIC 16F628
    ' PicBasic program to demonstrate operation of an LCD in 4-bit mode
    '          and reading an optical encoder in quadrature
    '
    ' LCD should be connected as follows:
    '       LCD     PIC
    '       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 connect
    
    
    TrisA = 000000
    TrisB = 110000
    PortB=0
    
    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
    
    Flag                var bit
    wsave               VAR BYTE    $70     SYSTEM  ' alternate save location for W 
    Q_New               var Byte
    Q_Old               var byte
    Q_Count             var word
    
    
    ' Set variable value @ startup
              Flag = 0          
             Q_New = 0
             Q_Old = 0
           Q_Count = 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
    
    
    Lcdout $fe, 1                       ' Clear LCD screen
    Lcdout "System Ready"               ' Display message
    Pause 500                           ' Wait .5 second
    
    Goto Main_Loop
    
    Encoder:
    Q_New = PortB.7 + PortB.7 + PortB.6
    
    if Q_Old = 0 then
    if Q_New = 2 then Minus_Count
    if Q_New = 1 then Plus_Count
    endif
    
    if Q_Old = 1 then
    if Q_New = 0 then Minus_Count
    if Q_New = 3 then Plus_Count
    endif
    
    if Q_Old = 3 then
    if Q_New = 1 then Minus_Count
    if Q_New = 2 then Plus_Count
    endif
    
    if Q_Old = 2 then
    if Q_New = 3 then Minus_Count
    if Q_New = 0 then Plus_Count
    endif
    
    goto Q_Skip
    
    Minus_Count:
    Q_Count = Q_Count - 1
       Flag = 1
    goto Q_Skip
    
    Plus_Count:
    Q_Count = Q_Count + 1
       Flag = 1
    Q_Skip:
    Q_Old = Q_New
     
     
    @ INT_RETURN
    
    Main_Loop:   
    
    if Flag = 1 then
    Lcdout $fe, 1                    
    Lcdout Dec Q_Count
    Flag = 0
    endif
    
    goto Main_Loop
    
    end
    Enjoy

    Cheers

    Al.
    All progress began with an idea

  19. #19
    Join Date
    Nov 2011
    Posts
    2


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    heckler,
    have a look at this:-

    ' Target PIC : 12F, 16F, 18F
    ' Hardware : Non specific
    ' Oscillator : internal or external
    ' Keywords : ON INTERRUPT
    ' Description : PICBASIC PRO program to demonstrate use of On Interrupt
    ' Interrupts in BASIC. Turn LED on. Interrupt on PORTB.0 (INTE) turns LED off.
    ' Program waits .5 seconds and turns LED back on.

    led Var PORTB.7

    OPTION_REG = $7f ' Enable PORTB pullups

    On Interrupt Goto myint ' Define interrupt handler
    INTCON = $90 ' Enable INTE interrupt

    mainloop:
    High led ' Turn LED on
    Goto mainloop ' Do it forever

    ' Interrupt handler
    Disable ' No interrupts past this point
    myint:
    Low led ' If we get here, turn LED off
    Pause 500 ' Wait .5 seconds
    INTCON.1 = 0 ' Clear interrupt flag
    Resume ' Return to main program
    Enable

    End

    ------------------------
    the main loop runs and when an interrupt happens the program jumps to the handler called myint. does what is in myint and then returns to resume where it left off in the main loop.

    just set the config so your interrupt is enabled that you want to use and put the code to read it in the myint routine. the main loop can do whatever it likes.

    what do you think?

  20. #20
    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
    Connection for LCD can be found to page 96 of PBP user manual.
    Do you have a link the that manual, please? I've looked at two different PBP Compiler Manuals so far and neither has a schematic for an LCD interface on page 96...
    Last edited by Mike, K8LH; - 5th November 2011 at 02:26.

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


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    @ podgycode... Thanks for your example, but what I meant was I would like to implement a rotary encoder via DT's Instant Interupts. I have used "on interrupt" successfully before to detect push buttons, etc. I have yet to use InstantINT's. I am going to try aratti's example in post #18 above.

    @ aratti... could you please clarify a couple of questions regarding your example...
    ground portB.5 and portB.4
    Why is this necessary?


    Q_New = PortB.7 + PortB.7 + PortB.6
    What does this line of code do??


    TrisA = 000000
    TrisB = 110000
    I assume these need % in front of the binary number??

    I hope this is not considered "hijacking" of this thread... as it still regards implementing Rotary Encoders.
    Thanks for your help




    example
    Last edited by Heckler; - 5th November 2011 at 06:10.
    Dwight
    These PIC's are like intricate puzzles just waiting for one to discover their secrets and MASTER their capabilities.

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


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    @ aratti... one more question

    wsave VAR BYTE $70 SYSTEM ' alternate save location for W
    could you help me with this line? Is it correct or did the forum software mess it up??

    thanks

    P.S. Oh yea... disregard this question... I think I see how it works..
    Q_New = PortB.7 + PortB.7 + PortB.6 What does this line of code do??
    Last edited by Heckler; - 5th November 2011 at 06:33.
    Dwight
    These PIC's are like intricate puzzles just waiting for one to discover their secrets and MASTER their capabilities.

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


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    Heckler, yes trisA and trisB need "%" (don't know Why have been removed)

    PortB.4 and portB.5 are set as input and never leave an input pin floating.

    Wsave is a variable used by DT INT-14.


    @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.

    Cheers

    Al.
    All progress began with an idea

  24. #24
    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!!!

  25. #25
    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.

  26. #26
    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...

  27. #27
    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

  28. #28
    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 15:14.
    Dwight
    These PIC's are like intricate puzzles just waiting for one to discover their secrets and MASTER their capabilities.

  29. #29
    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 06:15.

  30. #30
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    4,036


    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: 10451
Size:  165.5 KB

    Ioannis

  31. #31
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,580


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    Hi Ioannis,
    I haven't looked at the particular code in question but generally, you decode all 4 edges, hence the term quadrature. Look at the capture for one click, first Ch.0 goes low (1) then Ch.1 goes low (2), then Ch.0 goes high (3) and finally Ch.1 goes high (4). So, 4 counts per click.

    /Henrik.

  32. #32
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    4,036


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    Hmm, thanks Henrik, it looks logic now... well...

    Ioannis

  33. #33
    Join Date
    Jan 2005
    Location
    Montreal, Quebec, Canada
    Posts
    3,039


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    I need a rotary encoder for manual input in flight simulator; changing radio frequency, autopilot altitude, etc. I like the "slower" detection in post #1 for this particular application or else I'd issue 4 keyboard commands in a single detent. 100 feet would change to 500 feet with a single click with no way to set to the in-between values.

    But Podgy brings up a very important point; all rotary encoder datasheets I've seen mention debounce. I know most PIC inputs have Schmitt triggers, but just how effective are they in these cases? I can't test until my batch arrives.

    Robert
    Last edited by Demon; - 28th February 2012 at 00:01.

  34. #34
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    4,036


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    a couple of 100nF were needed for mine. After placing the caps to ground from each encoder output pin, false readings were a past.

    Ioannis

  35. #35
    Join Date
    Dec 2008
    Location
    Ploiesti, ROMANIA
    Posts
    582


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    Need help with one enconder ... a little different.
    How can I read the "up/+" and "down/-" action of this particular encoder ?
    Any help will be appreciated ! Thanks in advance !
    Attached Images Attached Images  

  36. #36
    Join Date
    Dec 2008
    Location
    Ploiesti, ROMANIA
    Posts
    582


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    It's ok something like this ?!
    Code:
    TrisA = %00000000
    TrisB = %11110000
    PortB = 0
    
    Flag                var bit
    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  
                            
    
    Goto Main_Loop
    
    Encoder:                                    '
    Q_New = PortB.7 + PortB.6 + PortB.5         ' get port status
     
    If M_Count[Q_Old] = Q_New then              ' if M_Count code satisfied then minus
              Q_Count = Q_Count - 1
                 Flag = 0                       ' set flag for DOWN
    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 for UP
    endif
    
    
    Q_Skip:
    Q_Old = Q_New                               ' update Q_Old Byte
     
    
    Main_Loop:   
    if Flag = 1 then do command1                             
    if Flag = 0 then do command2                                  
    goto Main_Loop

  37. #37
    Join Date
    Dec 2008
    Location
    Ploiesti, ROMANIA
    Posts
    582


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    So far...no good ...
    Complete "hardware" it's like in picture . I intend to use an remote with some "rotary encoder" ...
    The remote controller has six wires . They are connected to three rows and three columns. This allows maximum of 3*3=9 functions. Roller takes three functions because it must be possible to know which way it is rotated (how doing this in PBP ?!?). Rest of the functions are assigned to six buttons.
    I use great pice of code (keypad matrix routine) of Mr. Mister-e and the "regular" buttons works verry fine...but I want to use the function of roller too.
    I can't figure out how doing this, so any "clue" will be appreciated !
    Attached Images Attached Images  

  38. #38
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,580


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    Hi,
    Without analyzing your code in detail one possible problem might be this line
    Code:
    Q_New = PortB.7 + PortB.6 + PortB.5         ' get port status
    In this case you'll get Q_New = 1 no matter WHICH of the three pins are high. I'm not sure but I guess that's not what you want.

    You could try something like Q_New = PortB & %11100000 >> 5 instead.

    Here's another approach (untested) which is smaller in terms of program space and RAM but like I said it's untested so it might not even work.
    Code:
    oldState VAR BYTE
    newState VAR BYTE
    Q_Count VAR WORD
    DIR VAR BIT
    
    UP CON 1
    DN CON 0
    
    newState = (PortB & %11100000)      ' Isolate top three bits, newState will be 32, 64 or 128 
    
    If newState <> 0 THEN
    If newState <> oldState THEN        ' Changed from last time?
    
      Select Case oldState
        Case 32
        If NewState = 128 THEN          ' Was 1 now 4 = Up
          Q_Count = Q_Count + 1
          DIR = UP
        ELSE                          ' Was 1 now 2 = Down
          Q_Count = Q_Count - 1
          DIR = DN
        ENDIF
    
      
        Case 64
        If NewState = 32 THEN        ' Was 2 now 1 = Up
          Q_Count = Q_Count + 1
          DIR = UP
        ELSE                           ' Was 2 now 4 = Down
          Q_Count = Q_Count - 1
          DIR = DN
        ENDIF
    
      
        Case 128
        If NewState = 64 THEN        ' Was 4 now 2 = Up
          Q_Count = Q_Count + 1
          DIR = UP
        ELSE                       ' Was 4 now 1 = Down
          Q_Count = Q_Count - 1
          DIR = DN
        ENDIF
    
      END SELECT
    
      oldState = NewState
    
    ENDIF
    ENDIF

  39. #39
    Join Date
    Dec 2008
    Location
    Ploiesti, ROMANIA
    Posts
    582


    Did you find this post helpful? Yes | No

    Default Re: New approach to Rotary Encoder

    It a real pleasure to see how generous some people can be ... Thank You, AGAIN, Mr. Henrik !
    ...I think I missing something ... If UP do something, If Down do something else...dont ?!
    But nothing happens.
    Code:
    '****************************************************************
     @ DEVICE pic16F628A, XT_OSC, WDT_OFF, PWRT_ON, BOD_OFF, MCLR_ON, LVP_OFF
    
       Define   OSC 4           ' 4MHz 
       CMCON = 7                ' Disable on-chip comparator, PORTA in digital mode
    
    include "alldigital.pbp"
    
    TrisA = 000000
    PortB = 010000
    TrisB = 000000
    
    oldState VAR BYTE
    newState VAR BYTE
    Q_Count VAR WORD
    DIR VAR BIT
    
    UP CON 1
    DN CON 0
    
    
    Main_Loop:  
    newState = (PortB & 100000)    
    goto encoder
    if dir = up then portb.0 = 1                           
    if dir = dn then portb.1 = 1 
    goto Main_Loop 
    goto encoder
    if dir = up then 
    portb.4 = 1
    portb.0 = 1
    endif                           
    if dir = dn then 
    portb.4 = 0
    portb.1 = 1
    endif
    goto Main_Loop
    
    
    encoder:
    
    If newState <> 0 THEN
    If newState <> oldState THEN        ' Changed from last time?
    
      Select Case oldState
        Case 32
        If NewState = 128 THEN          ' Was 1 now 4 = Up
          Q_Count = Q_Count + 1
          DIR = UP
        ELSE                          ' Was 1 now 2 = Down
          Q_Count = Q_Count - 1
          DIR = DN
        ENDIF
    
      
        Case 64
        If NewState = 32 THEN        ' Was 2 now 1 = Up
          Q_Count = Q_Count + 1
          DIR = UP
        ELSE                           ' Was 2 now 4 = Down
          Q_Count = Q_Count - 1
          DIR = DN
        ENDIF
    
      
        Case 128
        If NewState = 64 THEN        ' Was 4 now 2 = Up
          Q_Count = Q_Count + 1
          DIR = UP
        ELSE                       ' Was 4 now 1 = Down
          Q_Count = Q_Count - 1
          DIR = DN
        ENDIF
    
      END SELECT
    
      oldState = NewState 
    
    ENDIF
    ENDIF
    Or I wired the roller wrong ?
    Here ( http://www.angelfire.com/nd/maza/kenwood.html ) it's a working variant, but in other "way" , using Atmega ...
    Attached Images Attached Images
    Attached Files Attached Files
    Last edited by fratello; - 13th April 2012 at 10:46.

  40. #40
    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

    Dave
    Always wear safety glasses while programming.

Members who have read this thread : 4

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