News:

Let's find out together what makes a PIC Tick!

Main Menu

ALPS EC11 series encoder

Started by See_Mos, Jan 07, 2022, 12:04 PM

Previous topic - Next topic

See_Mos

Is anyone using the ALPS EC11 series encoders, the ones that look like a potentiometer?

I have a bag full of new ones left over from some test equipment that I used to repair.

In the original equipment they worked perfectly but the problem I have is that the output is quite unstable and there is a delay between CHA changing and CHB changing.

At each indent the values are either 11 or 00

I have already tried with two different codes by Les and one of my own.

I just did some more testing with the 'scope and it looks like it might be a contact bounce problem.

Mapo

HI See_Mos,
in this message I have post a little routine for rotary encoder

https://protoncompiler.com/index.php/topic,290.msg1681.html#msg1681

top204

With the contact type encoders there are several ways of debouncing, but all of them should have a 100nF capacitor from the A and B terminals to Gnd, so the capacitor acts as a dampener and removes a lot of the jitter.

Then within the program, you can use a counting type debounce method, so the pin is checked each iteration, and the counter is reset when the pin is open or closed depending on which pin is being checked, and incremented when the pin is in the required state, and only when the count reaches a certain value, has the jitter stopped. This can be done within a simple timer interrupt, so it does not affect the flow of the program, and the rotaty encoder movement is ignored until the jitter is stable and a true reading is made of the change in rotation.

The above method is better than a sequence of delays, because it allows full program flow to happen. There are other methods of debouncing, and some are complex like ladder mechanisms etc, but I have found the above method works very well.


See_Mos

Thanks Mapo, I had forgotten that thread.

Thanks Les, For a long time now I have been using some spare Bournes optical encoders and I had forgotten about the capacitors.  Together with some code previously provided by yourself the ALPS mechanical encoders work very well, Just an occasional missed pulse or wrong direction but nothing to cause a problem with a manually operated encoder.

Below is a slightly modified version of your code which might help others.  The device that I used was 18F25K22 @ 64MHz

   
    TRISB = %00110000 'Set PortB input/output
Declare PORTB_Pullups On     
    Dim OldEncVal As Byte
    Dim EncVal As Byte
    Dim NewPos As Byte
    Dim OldPos As Byte
    Dim Dirflag As Bit = 0                  ' 0 = CW, 1 = CCW
 
 On_Hardware_Interrupt GetEncoder 
 GoTo Main:
 
 
'****************************************************************************** 
GetEncoder:
'******************************************************************************
Context Save

    'Disable interrupts whilst ISR is serviced
    IntConBits_RBIE = 0 'Disable PortB interrupts
    IntConBits_GIE = 0 'Disable Global interrupts
   
    OldPos = NewPos                                                                       
    NewPos = (PORTB & %00110000)
    NewPos = NewPos >> 4                                                                       

If OldPos = 3 Then
    If NewPos = 2 Then
        Inc EncVal
        Dirflag = 0
    ElseIf NewPos = 1 Then
        Dec EncVal
        Dirflag = 1
    EndIf
ElseIf OldPos = 0 Then
    If NewPos = 1 Then
        Inc EncVal
        Dirflag = 0
    ElseIf NewPos = 2 Then
        Dec EncVal
        Dirflag = 1
    EndIf
EndIf

    'Interrupt Serviced so enable interrupts once more.
    IntConBits_RBIF = 0'Port B Interrupt-On-Change Interrupt Flag bit
    IntConBits_RBIE = 1 'Enable PortB interrupts
    IntConBits_GIE = 1 'Enable Global interrupts

 Context Restore
   
'******************************************************************************
Main:
'******************************************************************************

    INTCON = $00 'all interrupts disabled at this point
   
    IOCB.4 = 1  'Interrupt on change PortB pins <4:5>
    IOCB.5 = 1

    IntConBits_RBIE = 1 'Enable PortB interrupts
    IntConBits_GIE = 1 'Enable Global interrupts
    IntConBits_RBIF = 0'Port B Interrupt-On-Change Interrupt Flag bit. Necessary?

    Clear
    DelayMS 1000
    Cls
    Print At 1,1,"Encoder Value "
    Print At 2,1,Dec5 EncVal
   
While
    If EncVal <> OldEncVal Then
    'disable interrupts while screen refresh takes place
    'Could I get away with just disabling global interrupts?
        IntConBits_RBIE = 0 'Disable PortB interrupts
        IntConBits_GIE = 0 'Disable Global interrupts
        Print At 2,1, Dec5 EncVal
        OldEncVal = EncVal
        If Dirflag = 0 Then
            Print At 3,1,"Up  "
        Else
            Print At 3,1,"Down"
        EndIf
    'Refresh done, so enable interrupts again   
        IntConBits_RBIE = 1 'Enable PortB interrupts
        IntConBits_GIE = 1 'Enable Global interrupts
   EndIf
Wend

top204

#4
Just a note See_Mos:

Quote'Disable interrupts whilst ISR is serviced
    IntConBits_RBIE = 0 'Disable PortB interrupts
    IntConBits_GIE = 0 'Disable Global interrupts

Within a high level interrupt handler routine, global interrupts are automatically disabled in hardware, until the Retfie mnemonic is used within the Context Restore directive. Also, the PORTB interrupt will not happen again until its flag is cleared, so there is no need to waste cycles disabling and re-enabling them within the interrupt handler routine, just clear the relevant flag for what caused the interrupt to happen before exiting from the interrupt.