+ Reply to Thread
Page 2 of 3 FirstFirst 123 LastLast
Results 41 to 80 of 91
  1. #41
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    2,310

    Default Re: New approach to Rotary Encoder

    Try GOSUB Encoder and put a RETURN at the end of the subroutine. Currently you GOTO Encoder and then you run off into never never land. I'm not saying that will make it work but that's one possible problem.

    Also, make sure that have the "wiper" of the roller connected to 5V, verify that you get signals on the actuall pins of the PIC when you rotate the encoder/roller.

  2. #42
    Join Date
    Dec 2008
    Location
    Ploiesti, ROMANIA
    Posts
    476

    Default Re: New approach to Rotary Encoder

    I think the hardware must be build in this way (since the rest of buttons are allready connected as matrix). I wonder if "KeyPad.bas" of Mr.Mister-e can be addapted to read the increment/decrement of roller, by "including" somehow the code for encoder ....
    Brrrrrr...it's beyond of my intellectual capacities .
    Attached Images Attached Images  

  3. #43
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    2,310

    Default Re: New approach to Rotary Encoder

    Hi,
    I don't have any experience with that routine but provided everything else works the way you want why don't you just set the pin which is common to the encoder (RB5 ?) high, read the port, and return the pin low.

    GOSUB ScanMatrix 'Or whatever
    PortB.5 = 1
    GOSUB Encoder
    PortB.5 = 0

    Finally, in the first code you posted you had the encoder to RB7-5 so I based my code on that. Now, in your latest schematic, you have it on RB2-0 which means that my code (if that's what you're trying) definitely won't work without modifying it since it expects the three "switches" in the encoder to be on RB7-5.

  4. #44
    Join Date
    Dec 2008
    Location
    Ploiesti, ROMANIA
    Posts
    476

    Default Re: New approach to Rotary Encoder

    What I do wrong ?!
    I adapted "keypad.bas" to my hw :
    Code:
    KB_ROW        = 3                                      ; 3 ROW keypad
    KB_ROW_PORT   = PORTB                                  ; Keypad ROW on PORTB
    KB_ROW_BIT    = 3                                      ; ROW0 = PORTB.3
    KB_COL        = 3                                      ; 3 COL keypad
    KB_COL_PORT   = PORTB                                  ; Keypad Col on PORTB
    KB_COL_BIT    = 0                                      ; COL0 = PORTB.0
    DebounceDelay = 0x80                                   ; debounce delay 41mSec
    SINGLE_SCAN   = 0                                      ; Scan ;till a key is pressed   
    KEYPAD_AUTOREPEAT = 1
    and I wrote this pice of code :
    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"
    include "C:\PBP\enc_KEY.BAS" 
    
    TrisA = %00000000
    PortA = %00000000
    PortB = %00111000
    TrisB = %00011000
    
    oldState VAR BYTE
    newState VAR BYTE
    Q_Count VAR WORD
    DIR VAR BIT
    
    UP CON 1
    DN CON 0
    
    
    Main_Loop:  
    newState = (PortB & %00111000)  
    
    portb.5 = 1  
    gosub encoder
    portb.5 = 0
    
    if dir = up then 
    porta.0 = 0
    porta.1 = 1
    endif                           
    if dir = dn then 
    porta.0 = 1
    porta.1 = 0
    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
    Return
    ..but no change in porta.0 or porta.1 state ...

  5. #45
    Join Date
    Dec 2008
    Location
    Ploiesti, ROMANIA
    Posts
    476

    Default Re: New approach to Rotary Encoder

    Update code :
    Code:
    Main_Loop:  
    gosub keypadscan
    newState = (PortB & %00000111) 
    gosub encoder
    gosub check
    goto main_loop
    
    Check :
    if dir = up then 
    porta.0 = 0
    porta.1 = 1
    endif                           
    if dir = dn then 
    porta.0 = 1
    porta.1 = 0
    endif
    return
    
    
    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
    Return
    but no matter what M (1,2 or 3) I push, porta.0 goes high and stay so.

  6. #46
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    2,310

    Default Re: New approach to Rotary Encoder

    Hi,
    In the first code you posted you read the status of PortB before driving the the common pin for the encoder so there probably won't be any signals comming in.
    In the second, updated example, you never drive the common pin for the encoder at all.
    You need to set the "common pin" high (or low depending on hardware) and THEN read the port otherwise you won't get anything back.


    You really need to sit back and think the problem thru, not just cut and paste pieces of code together without understanding what they do and how the hardware they're intended to interface to is supposed to work.

    Think it thru.... The "encoder" has a "wiper" which "cylces" thru the different contacts. Depending on which contact the wipers is positioned at you'll get a signal out on a certain pin. In order to get that signal out the "wiper" must be "powered" in one way or another. If the inputs from the "contacts" are pulled up then wiper must be grounded so that it pulls the contact (and signal LOW). Likewise if the inputs from the contacts are pulled down then the "wiper" must be high in order to pull the inputs high.

    If the inputs are pulled up with resistors then you'll get a "walking zero" across the three pins, if the inputs are pulled down you'll get a "walking one" across the inputs. You must adapt the code to match.

    My suggestion, for now, is that you ditch the matrix routine untill you get the encoder working - and understand how it works.

    /Henrik.

  7. #47
    Join Date
    Dec 2008
    Location
    Ploiesti, ROMANIA
    Posts
    476

    Default Re: New approach to Rotary Encoder

    Thanks for support !
    "In the second, updated example, you never drive the common pin for the encoder at all."
    But ..."keypadscan" don't do this ? Proteus show how "0" walk through portb 3,4,5.
    Attached Files Attached Files

  8. #48
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    2,310

    Default Re: New approach to Rotary Encoder

    Hi,
    Like I said earlier, I don't have any experience with that piece fo code but if I'd venture I guess (and I'm pretty certain I'm right) it scans the pins once each time you GOSUB the routine. This means it does NOT scan the pins during the time you GOSUB the encoder routine.

    Does Proteus show that walking zero across the pins at the same time as you do newState = PortB & %00000111 - I'd say no.

    If your inputs are pulled up with resistors then the common/wiper of the encoder must be LOW at the time you read the status of the port. You must understand and remember that the PIC executes the code sequentially, one instruction after another.

  9. #49
    Join Date
    Dec 2008
    Location
    Ploiesti, ROMANIA
    Posts
    476

    Default Re: New approach to Rotary Encoder

    Step-by-step I think I begin to understand ...
    The correct hardware it's this.
    The software can be this :
    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"
    include "C:\PBP\enc_KEY.BAS" 
    
    TRISB = 000000
    PORTB = 000000 
    
    oldState VAR BYTE
    newState VAR BYTE
    DIR VAR BIT
    
    UP CON 1
    DN CON 0
    
    Main_Loop: 
    portb.5 = 1
    gosub keypadscan
    gosub check
    goto main_loop
    
    Check :
    if dir = up then 
    portb.0 = 1
    pause 1000
    portb.0 = 0
    endif
    if dir = dn then
    portb.1 = 1
    pause 1000
    portb.1 = 0
    endif
    return
    
    encoder:
    portb.5 = 0
        newState = (porta & 000111)
    If newState <> oldState THEN        ' Changed from last time?
      Select Case oldState
        Case 2
        If NewState = 4 THEN          ' Was 1 now 4 = Up
          DIR = up
        ELSE                          ' Was 1 now 2 = Down
          DIR = dn
        ENDIF
      
        Case 4
        If NewState = 1  THEN        ' Was 2 now 1 = Up
          DIR = up
        ELSE                           ' Was 2 now 4 = Down
          DIR = dn
        ENDIF
      
        Case 1
        If NewState = 2 THEN        ' Was 4 now 2 = Up
          DIR = up
        ELSE                       ' Was 4 now 1 = Down
          DIR = dn
        ENDIF
      END SELECT
    
      oldState = NewState 
    endif
    portb.5 = 1
    Return
    The question is : where to put "gosub encoder" ? Inside the "enc_key.bas" (it's keypad.bas addapted to 2 row/3 cols) ???
    Attached Images Attached Images  

  10. #50
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    2,310

    Default Re: New approach to Rotary Encoder

    Hi,
    Now we're getting somewhere - that looks like it might work.
    The keypad routine has nothing to do with reading the encoder. Put the GOSUB Encoder in the mainloop, before GOSUB check obviously....

    And again, if it doesn't work then remove the keypad routine untill you get the encoder routine working - THEN try to make the two coexist. There's no guarantee that the encoder code works, I just posted it as one possible idea of how to read that kind of "encoder".

  11. #51
    Join Date
    Dec 2008
    Location
    Ploiesti, ROMANIA
    Posts
    476

    Default Re: New approach to Rotary Encoder

    No matter what I do, portb.1 goes high and low .... portb.0 don't change ....
    Code:
    TRISB = 000000
    PORTB = 000000 
    
    oldState VAR BYTE
    newState VAR BYTE
    DIR VAR BIT
    
    UP CON 1
    DN CON 0
    
    oldstate = (porta & 000111)
    
    Main_Loop: 
    
    gosub Encoder
    gosub check
    goto main_loop
    
    Check :
    if dir = up then 
    portb.0 = 1
    pause 1000
    portb.0 = 0
    endif
    if dir = dn then
    portb.1 = 1
    pause 1000
    portb.1 = 0
    endif
    return
    
    encoder:
    portb.5 = 1
        pause 100
        newState = (porta & 000111)
    portb.5 = 0
    If newState <> oldState THEN        ' Changed from last time?
      Select Case oldState
        Case 1
        If NewState = 4 THEN dir=up         
        If NewState = 2 THEN dir=dn
      
        Case 2
        If NewState = 4 THEN dir=up        
        If NewState = 1 THEN dir=dn
      
        Case 4
        If NewState = 1 THEN dir=up        
        If NewState = 2 THEN dir=dn
        
      END SELECT
    
    oldstate=newstate
    endif
    Return
    Attached Files Attached Files

  12. #52
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    2,310

    Default Re: New approach to Rotary Encoder

    Hi,
    Since you have the inputs pulled high and the wiper "grounding" each input as it cycles thru them you can't use 1, 2 and 4 as the states since that "looks for" a '1' on the individual pins. You need to use 3, 5 and 6 instead.

  13. #53
    Join Date
    Dec 2008
    Location
    Ploiesti, ROMANIA
    Posts
    476

    Default Re: New approach to Rotary Encoder

    Twillight zone ....
    Code:
      Select Case oldState
        Case 3
        If NewState = 6 THEN dir=up         
        If NewState = 5 THEN dir=dn
      
        Case 5
        If NewState = 3 THEN dir=up        
        If NewState = 6 THEN dir=dn
      
        Case 6
        If NewState = 5 THEN dir=up        
        If NewState = 3 THEN dir=dn
      END SELECT
    No matter what I do, portb.1 goes high and low .... portb.0 don't change ....

  14. #54
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    2,310

    Default Re: New approach to Rotary Encoder

    Don't know what to tell you but the code works just fine here.
    Code:
    HSEROUT ["Program start",13]
    
    Main:
        PortB.5 = 0
        newState = PortA & %00000111
        PortB.5 = 1
        
        If newState <> 7 THEN
            If newState <> oldState THEN
                  
                Select Case oldState
                    Case 3
                    If NewState = 6 THEN dir=up         
                    If NewState = 5 THEN dir=dn
      
                    Case 5
                    If NewState = 3 THEN dir=up        
                    If NewState = 6 THEN dir=dn
      
                    Case 6
                    If NewState = 5 THEN dir=up        
                    If NewState = 3 THEN dir=dn
                END SELECT
    
                HSEROUT["oldState: ", DEC oldState, "   newState: ", DEC newState, "   DIR: ", DEC DIR, 13]        
            
            oldState = newState
            Pause 1000
            ENDIF
        ENDIF
        
    Goto Main
    This was executed on an AMICUS18 board with a PIC18F25K20. A wire from RB5 to the pulled up inputs was used to simulate the "encoder", the results are here:

    Name:  Fratello_encoder.jpg
Views: 1136
Size:  69.7 KB

    As you can see, it works.

    Have you verified that PortB.5 does go LOW?
    Have you verified that you DO get a LOW on RA0,1 and 2 as you rotate the encoder?
    Have you checked the datasheet to see if any other peripherals are multiplexed onto the pins you're trying to use? ADC? Comparator?

  15. #55
    Join Date
    Nov 2003
    Location
    Wellton, U.S.A.
    Posts
    5,824

    Default Re: New approach to Rotary Encoder

    Been said before and I will say it again.

    NEVER TRUST A SIM!
    Dave
    Always wear safety glasses while programming.

  16. #56
    Join Date
    Dec 2008
    Location
    Ploiesti, ROMANIA
    Posts
    476

    Default Re: New approach to Rotary Encoder

    ... ok, so work, despite the "non-working" of simulator !
    Next step is to try to make the two coexist (keypad.bas & encoder.bas) .
    First I will build the schematic and making some tests. Thanks again for the huge support !

  17. #57
    Join Date
    Dec 2008
    Location
    Ploiesti, ROMANIA
    Posts
    476

    Default Re: New approach to Rotary Encoder

    It's this a viable options of reading encoder AND the others buttons ?
    Code:
    Main:
    ;==============
    ;reading buttons on line 0 (pseudo-encoder)
        PortB.5 = 0
        newState = PortA & %00000111
        PortB.5 = 1
        If newState <> 7 THEN
            If newState <> oldState THEN
                  
                Select Case oldState
                    Case 3
                    If NewState = 6 THEN 
                    dir=up         
                    portb.0 = 1
                    endif
                    If NewState = 5 THEN 
                    dir=dn
                    portb.1 = 1
                    endif
                    
                    Case 5
                    If NewState = 3 THEN 
                    dir=up         
                    portb.0 = 1
                    endif      
                    If NewState = 6 THEN 
                    dir=dn
                    portb.1 = 1
                    endif
                    
                    Case 6
                    If NewState = 5 THEN 
                    dir=up
                    portb.0 = 1
                    endif        
                    If NewState = 3 THEN 
                    dir=dn
                    portb.1 = 1
                    endif
                END SELECT      
                oldState = newState
              Pause 100
            ENDIF
        ENDIF
    ;==============
    ;reading buttons on line 1
        Porta.4 = 0
        status_2 = PortA & %00000111
        Porta.4 = 1
        select case status_2
                    case 3
                    gosub trackDn
                    case 5
                    gosub mute
                    case 6
                    gosub trackUp
        end select
    ;==============
    ;reading buttons on line 2    
        Porta.3 = 0
        status_3 = PortA & %00000111
        Porta.3 = 1
        select case status_3
                    case 3
                    gosub volDn
                    case 5
                    gosub volUp
                    case 6
                    gosub Sursa
        end select                           
    Goto Main

  18. #58
    Join Date
    Dec 2008
    Location
    Ploiesti, ROMANIA
    Posts
    476

    Default Re: New approach to Rotary Encoder

    So far, so god ... Now another problem : how can I separates signals?
    If rotary switch is Up, can't read if TK- or V- are pressed ..
    If rotary switch is in middle position, can't read if MUTE or V+ are pressed ...
    If rotary switch is down, can't read if TK+ or S are pressed...


    Hi, we are pleased to see that you are using our forum.

    We'd like you to become a member of our community. Membership is FREE, please REGISTER and view our forums without these annoying reminders!

    Once registered you may post on the forums, download from the file areas and use the WIKI without interruption.







    LE - I think this work :
    Code:
    ;reading buttons on line 1
        Porta.4 = 0
        trisb.5 = 1
        pause 50
        status_2 = PortA & %00000111
        Porta.4 = 1
        trisb.5 = 0
    Attached Images Attached Images  
    Last edited by fratello; - 14th April 2012 at 21:38.

  19. #59
    Join Date
    Dec 2008
    Location
    Ploiesti, ROMANIA
    Posts
    476

    Default Re: New approach to Rotary Encoder

    New code works pretty well ... But, how can I avoid false roller codes ? If I turn up, not always the the code "see" up ; if I turn down, not always the code "see" down ...Sometimes, the commands (Up/Down) are inversed !
    I try to add some "pause" between different commands, but the problem remains.

  20. #60
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    2,310

    Default Re: New approach to Rotary Encoder

    No, don't try to slow it down...speed it up. If you have any pauses in there try removing those. If your program is going to do 'other' things as well (which I'm sure it is) then you may need to sample the encoder several times thru out the main loop.

    The reason is because if you are at one state and then turn forward two states but you do it fast enough so that the code doesn't detect the "middle" state, then it looks like you turned one state backwards instead of two forward.

    So, you want to sample the encoder as fast as you can possibly turn it - and then some.

    /Henrik.

  21. #61
    Join Date
    Dec 2008
    Location
    Ploiesti, ROMANIA
    Posts
    476

    Default Re: New approach to Rotary Encoder

    I try both variants, presented in code, but without major improvements.
    Code:
    ;==============
    ;reading buttons on row 0 (pseudo-encoder)
        PortA.1 = 0
    ;    pause 10
    @   nop
        newState = PortA & %00011100         ; this is for my hw : 11100 = 28
        PortA.1 = 1
        If newState <> 28 THEN
            If newState <> oldState THEN
                  
                Select Case oldState
                    Case 12
                    If NewState = 24 THEN 
                    dir=up         
                    endif
                    If NewState = 20 THEN 
                    dir=dn
                    endif
                    
                    Case 20
                    If NewState = 12 THEN 
                    dir=up         
                    endif      
                    If NewState = 24 THEN 
                    dir=dn
                    endif
                    
                    Case 24
                    If NewState = 20 THEN 
                    dir=up
                    endif        
                    If NewState = 12 THEN 
                    dir=dn
                    endif
                END SELECT
                oldState = newState
                GOSUB UpOrDn  
                pause 100
        endif           
        ENDIF

  22. #62
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    2,310

    Default Re: New approach to Rotary Encoder

    Which two variants? I only see one in your previous message.
    In that one you have a PAUSE 10 at the beginning, which is commented out, and also a @NOP. Then you have a PAUSE 100 near the end which is NOT commented out.

    /Henrik.

  23. #63
    Join Date
    Dec 2008
    Location
    Ploiesti, ROMANIA
    Posts
    476

    Default Re: New approach to Rotary Encoder

    Sorry...
    "@ nop" ... not good
    and then
    "pause 10" ....idem.

  24. #64
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    2,246

    Default Re: New approach to Rotary Encoder

    If you place two 100nF to ground for debouncing false results will be limited.
    Ioannis

  25. #65
    Join Date
    Dec 2008
    Location
    Ploiesti, ROMANIA
    Posts
    476

    Default Re: New approach to Rotary Encoder

    I already tried that...without results ! %$@#^*#@^ roller !

  26. #66
    Join Date
    Sep 2004
    Location
    montreal, canada
    Posts
    6,896

    Default Re: New approach to Rotary Encoder

    not sure to understand your thing, but give yourself a chance, plug the encoder on a set of "interruptable" I/O, the wiper to GND and use interrupt to triger the Encoder reading. end of the story.
    Steve

    It's not a bug, it's a random feature.
    There's no problem, only learning opportunities.

  27. #67
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    2,310

    Default Re: New approach to Rotary Encoder

    Code:
                END SELECT
                oldState = newState
                GOSUB UpOrDn  
                pause 100              ' <--- Have you removed this?
        endif           
        ENDIF

  28. #68
    Join Date
    Dec 2008
    Location
    Ploiesti, ROMANIA
    Posts
    476

    Default Re: New approach to Rotary Encoder

    Mr.Mister_E : Can not put the wiper to GND because of hardware ( http://www.picbasic.co.uk/forum/show...126#post113126 ).
    Mr.Henrik : I remove already this line ; is better but not best.

  29. #69
    Join Date
    Dec 2008
    Location
    Ploiesti, ROMANIA
    Posts
    476

    Default Re: New approach to Rotary Encoder

    I tried to ad a second check of direction :
    Code:
    loop:
        PortA.1 = 0
        newState = PortA & 011100         ; this is for my hw : 11100 = 28
        pause 50                             ; no matter what I put here : none, @ nop , pause 100 !
            newa = PortA & 011100
        PortA.1 = 1
        If newState <> 28 THEN
            If newState <> oldState THEN
                  
                Select Case oldState
                    Case 12
                    If NewState = 20 THEN 
                            if newa = 24 then dir=up
                    endif        
                    
                    case 12
                    If NewState = 24 THEN 
                            if newa = 20 then dir=dn
                    endif
     
                    
                    Case 20
                    If NewState = 24 THEN 
                            if newa = 12 then dir=up
                    endif  
                    
                    Case 20
                    If NewState = 12  THEN 
                            if newa = 24 then dir=dn
                    endif     
                    
                    Case 24
                    If NewState = 12 THEN
                            if newa = 20 then dir=up
                    endif
                    
                    Case 24
                    If NewState = 20 THEN
                            if newa = 12 then dir=dn
                    endif
    
                END SELECT
                oldState = newstate
                GOSUB UpOrDn 
           endif     
        ENDIF
    But, in this way, any direction I rotate, the command is always "Dir Up" ?! Never goes "down" ...

  30. #70
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    2,310

    Default Re: New approach to Rotary Encoder

    And what does the UpOrDn routine look like?

  31. #71
    Join Date
    Dec 2008
    Location
    Ploiesti, ROMANIA
    Posts
    476

    Default Re: New approach to Rotary Encoder

    This routine should do "Track+" /"Track-" :
    Code:
    UpOrDn:
    if dir=1 then
        PortB.4 = 0
        pauseus 3850
        PortB.4 = 1
        pauseus 3850
        PortB.4 = 0
        pauseus 660
        PortB.4 = 1
    endif
    
    if dir=0 then
        PortB.4 = 0
        pauseus 4450
        PortB.4 = 1
        pauseus 4400
        PortB.4 = 0
        pauseus 660
        PortB.4 = 1
    endif    
    return

  32. #72
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    2,310

    Default Re: New approach to Rotary Encoder

    And what do we have in there, if not delays... They are quite short (8-10ms in total) but it's still possible that that is what's messing with you.
    I don't know what you intended to do with that latest version though, why do you have two cases with the same value, just put the code for both in one.

  33. #73
    Join Date
    Dec 2008
    Location
    Ploiesti, ROMANIA
    Posts
    476

    Default Re: New approach to Rotary Encoder

    This is schematic and code...Maybe I miss something important ...
    Code:
    @ DEVICE pic16F628A, XT_OSC, WDT_OFF, PWRT_ON, BOD_OFF, MCLR_ON, LVP_OFF, PROTECT_ON
    
    include "alldigital.pbp"
       Define   OSC 4           ' 4MHz 
       CMCON = 7                ' Disable on-chip comparator, PORTA in digital mode
    
    
    TrisA = %00011100           ; coloane la RA2, 3, 4 ; randuri la RA1, 0 ,7 
    porta = %00011100
    TRISB = %00000000
    PORTB = %00010000 
    
    oldState VAR BYTE
    newState VAR BYTE
    
    UP CON 1
    DN CON 0
    
    
    loop:
        PortA.1 = 0
        newState = PortA & %00011100         ; this is for my hw : 11100 = 28
        PortA.1 = 1
    
        If newState <> 28 THEN
            If newState <> oldState THEN
                  
                Select Case oldState
                    Case 12
                    If NewState = 20 THEN dir=up       
                    If NewState = 24 THEn dir=dn
                    
                    Case 20
                    If NewState = 24 THEN dir=up               
                    If NewState = 12 THEN dir=dn
                   
                    Case 24
                    If NewState = 12 THEN dir=up                       
                    If NewState = 20 THEN dir=dn
                END SELECT
                oldState = newstate
                GOSUB UpOrDn 
           pause 15                    ; time for UpOrDn     
           endif          
        ENDIF
    ;============
    UpOrDn:
    if dir=DN then
        PortB.4 = 0
        pauseus 3850
        PortB.4 = 1
        pauseus 3850
        PortB.4 = 0
        pauseus 660
        PortB.4 = 1
    endif
    
    if dir=UP then
        PortB.4 = 0
        pauseus 4450
        PortB.4 = 1
        pauseus 4400
        PortB.4 = 0
        pauseus 660
        PortB.4 = 1
    endif    
    return
    
    end
    Attached Images Attached Images

  34. #74
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    2,310

    Default Re: New approach to Rotary Encoder

    1) I don't understand why you keep putting those PAUSE statements in there, now you have a PAUSE 15 in there....
    2) There's no GOTO LOOP anywhere so the program will "fall thru" into the UpOrDn routine then hit the RETURN and bad things will happpen. (BTW, Loop is a reserved word in newer versions of PBP, best to get used to not using it.
    3) Try resampling the pins and set oldState when you return from the subroutine, ie (changes in red):
    Code:
    Main:
        PortA.1 = 0
        newState = PortA & %00011100         ; this is for my hw : 11100 = 28
        PortA.1 = 1
        If newState <> 28 THEN
            If newState <> oldState THEN
                  
                Select Case oldState
                    Case 12
                    If NewState = 20 THEN dir=up       
                    If NewState = 24 THEn dir=dn
                    
                    Case 20
                    If NewState = 24 THEN dir=up               
                    If NewState = 12 THEN dir=dn
                   
                    Case 24
                    If NewState = 12 THEN dir=up                       
                    If NewState = 20 THEN dir=dn
                END SELECT
                GOSUB UpOrDn 
                
                PAUSE 15                    ; time for UpOrDn   
             
         ' Now resample the encoder and keep the state as oldState
              PortA.1 = 0
             oldState = PortA & %00011100         ; this is for my hw : 11100 = 28
             PortA.1 = 1     
           
        ENDIF          
      ENDIF
    GOTO MAIN
    ;============
    UpOrDn:
    if dir=DN then
        PortB.4 = 0
        pauseus 3850
        PortB.4 = 1
        pauseus 3850
        PortB.4 = 0
        pauseus 660
        PortB.4 = 1
    endif
    if dir=UP then
        PortB.4 = 0
        pauseus 4450
        PortB.4 = 1
        pauseus 4400
        PortB.4 = 0
        pauseus 660
        PortB.4 = 1
    endif    
    RETURN
    END

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

    Default Re: New approach to Rotary Encoder

    Mr. Henrik I must get my hat in front of you ! (Hope G.translate work well !).
    NOW, the code work verry good !!! Only sometimes the command are inversed , but in 9 case of 10 it's ok, so I can live with this...
    Thanks for lost so much time with me ! I am verry grateful !

  36. #76
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    2,310

    Default Re: New approach to Rotary Encoder

    Great, finally... Now try removing the PAUSE 15 and see if that improves it further.

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

    Default Re: New approach to Rotary Encoder

    Thanks to Mr.Henrik Olsson this code work PERFECT !!! I'm sure I would not have done it without his help !
    Code:
    Main:
        PortA.1 = 0
        newState = PortA & 011100        
        PortA.1 = 1
    
        If newState <> 28 THEN
            If newState <> oldState THEN
                  
                Select Case oldState
                    Case 12
                    If NewState = 20 THEN dir=up       
                    If NewState = 24 THEn dir=dn
                    
                    Case 20
                    If NewState = 24 THEN dir=up               
                    If NewState = 12 THEN dir=dn
                   
                    Case 24
                    If NewState = 12 THEN dir=up                       
                    If NewState = 20 THEN dir=dn
                END SELECT
    
                GOSUB UpOrDn 
    
        PortA.1 = 0
        OldState = PortA & 011100         
        PortA.1 = 1
                   
           endif          
        ENDIF
    Goto Main

  38. #78
    Join Date
    Sep 2011
    Posts
    4

    Default Re: New approach to Rotary Encoder

    Hi to all. I want to use a rotary encoder with a 18f252, and i have a lot of troubles. I want to use interupts, so my only solution PORTB or I can use Portc also?

    I made a pcb and I made the connections to PORTC, and I also use a debounce circuit, which I think causes problems. Anyone has a snipset code cause I do not have any expieriance with encoders?
    5v
    __|__
    | |
    / /
    \ \
    /10k / 10K
    \ \
    | A | B ENC
    - -
    | |-------------------------------
    \ |
    /10K \
    \ /10K
    / \
    |--------------------- |--------------------
    PORTC.2 | PORTC.3 |
    ---- ----- 100nF
    ---- -----
    | |
    --------- -----------
    ----- -----
    - -
    Last edited by kzeoprf; - 21st August 2012 at 09:49.

  39. #79
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    2,310

    Default Re: New approach to Rotary Encoder

    Hello,
    On the 18F252 there's no interrupt capabillity on PortC.

    Your schematic really doesn't show up that good here but it LOOKS like you have a 10k from 5V to the "top" of each of the switches in the encoders, then the other side of each switch thru another 10k to the input with a 100nF cap to GND, is that correct?

    If the above is not correct please post a proper schematic for us to see.
    If the above IS correct then it's not a very good hardware design IMHO. When the switch in the ecoder is closed you have 2*10k in series to the input, decoupled by a 100nF cap, this may be fine. But when the switch is open there's no path for the capacitor to discharge except thru the fairly high input impedance of the pin. In effect the pin floats which is not a good thing for inputs.

    /Henrik.

  40. #80
    Join Date
    Jan 2005
    Location
    Montreal, Quebec, Canada
    Posts
    1,732

    Default Re: New approach to Rotary Encoder

    I finally got around to trying my rotary encoders out on an 18F24K22 using DT interrupts.

    I kept things simple; checking for only 1 movement per click (detent). This encoder also has a momentary ON switch.


    Code:
    '***************************************************************************
    '*  Name    : 18F24K22 encoder.pbp                                         *
    '*  Author  : Robert Hedan                                                 *
    '*  Date    : Sep 5 2012                                                   *
    '*  Version : 1.0                                                          *
    '*  Hardware : PIC 18F24K22, internal oscillator, 8 MHz                    *
    '*           : ICSP                                                        *
    '*           : MeLabs U2 Programmer v4.32                                  *
    '*  Software : PIC Basic Pro v2.60C                                        *
    '*           : MicroCode Studio Plus v2.2.1.1                              *
    '*           : MPASM v5.46                                                 *
    '*  CONFIG   : - if you use these, you must comment the ones in the        *
    '                .INC file in PBP folder                                   *
    '              - available options at the bottom of P*.INC file in         *
    '                MPLAB TOOLS/MPASM SUITE folder                            *
    '***************************************************************************
    asm
     __CONFIG    _CONFIG1H, _FOSC_INTIO67_1H & _PLLCFG_OFF_1H & _PRICLKEN_ON_1H & _FCMEN_OFF_1H & _IESO_OFF_1H
     __CONFIG    _CONFIG2L, _PWRTEN_ON_2L & _BOREN_SBORDIS_2L & _BORV_285_2L
     __CONFIG    _CONFIG2H, _WDTEN_OFF_2H
     __CONFIG    _CONFIG3H, _PBADEN_ON_3H & _HFOFST_OFF_3H & _MCLRE_EXTMCLR_3H
     __CONFIG    _CONFIG4L, _STVREN_ON_4L & _LVP_OFF_4L & _XINST_OFF_4L & _DEBUG_OFF_4L
    endasm
    
    ;--- Oscillator speed ------------------------------------------------------
    
    DEFINE OSC 8
    CLEAR
    
    ;--- Setup Interrupts ------------------------------------------------------
    INCLUDE "DT_INTS-18.bas"        ; Base Interrupt System
    INCLUDE "ReEnterPBP-18.bas"     ; PBP Re-entry for external interrupt
    
    ASM
    INT_LIST  macro    ; IntSource,        Label,  Type, ResetFlag?
            INT_Handler    INT_INT,  _ExternalInterrupt0,   PBP,  yes
        endm
        INT_CREATE               ; Creates the interrupt processor
    ENDASM
    
    @   INT_ENABLE   INT_INT     ; enable external (INT) interrupts
    
    ;--- Setup Registers -------------------------------------------------------
    
    OSCCON = %01100110              ' OSCILLATOR CONTROL REGISTER
    OSCTUNE = %00000000             ' OSCILLATOR TUNING REGISTER
    
    PMD0 = %11111111                ' PERIPHERAL MODULE DISABLE REGISTER 0
    PMD1 = %11111111                ' PERIPHERAL MODULE DISABLE REGISTER 1
    PMD2 = %00001111                ' PERIPHERAL MODULE DISABLE REGISTER 2
    
    INTCON2=%10000100               ' INTERRUPT CONTROL 2 REGISTER
    
    ANSELA = 0                      ' Digital I/O
    ANSELB = 0                      ' Digital I/O
    ANSELC = 0                      ' Digital I/O
    
    ;--- Setup Port directions -------------------------------------------------
    
    TRISA = %00000000               ' Set port A pins to output
    TRISB = %00000001               ' Set port B pin 0 to input, others output
    TRISC = %00000110               ' Set port C pins 1,2 to input, others output
    
    ;--- Pins ------------------------------------------------------------------
    
    WiperA      VAR PortB.0         ' Interrupt 0
    WiperB      VAR PortC.2
    
    Switch      VAR PortC.1
    
    LedPower    VAR PortB.5
    
    ;--- Variables -------------------------------------------------------------
    
    LEDS        VAR BYTE            ' 8 Leds connected on Port A
    
    ;--- Program Start ---------------------------------------------------------
    
    start:
    
    Pause 200                       ' Let PIC stabilize
    
    Ledpower = 0
    
    Leds = %00000001
    PortA = leds
    
    ;--- The Main Loop ---------------------------------------------------------
    
    mainloop:
    
      if Switch = 1 then
        Ledpower = 1                    ' Turn ON Led
        pause 200                       ' Debounce
        Ledpower = 0                    ' Turn it back OFF
      endif
    
      Goto mainloop
    
    end
    
    '---[INT - interrupt handler]---------------------------------------------------
    ExternalInterrupt0:
      if wiperb = 1 then
        if leds.7 = 0 then
          LEDS = LEDs << 1              ' Leds blink counter-clockwise
        endif
      else
        if leds.0 = 0 then
          leds = leds >> 1              ' Leds blink clockwise
        endif
      endif
    
      PortA = leds
      pause 100
    @ INT_RETURN

    I used both 0.01uF and 0.1uF caps to improve debounce and wired the C pin straight to Vss (only check wiper A and B). This is the recommended circuit by the manufacturer:

    Name:  Encoder debounce.JPG
Views: 1279
Size:  39.3 KB

    Robert
    Last edited by Demon; - 7th September 2012 at 01:50.

Members who have read this thread : 45

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