B4R Tutorial Using an incremental rotary encoder

Discussion in 'B4R Tutorials' started by Peter Simpson, May 17, 2017.

  1. Peter Simpson

    Peter Simpson Expert Licensed User

    This is a quick tutorial on what an incremental rotary encoder (or rotary encoder for short) is and what it can be used for.

    A rotary encoder is an electromechanical device that generates an electrical signal to convert the angle/position of the shaft or motion/direction of a shaft to either an analogue or digital signal. A rotary encoder does not have a start/stop or high/low position like a potentiometer, it has unlimited rotation in both anticlockwise and clockwise directions, it also has a built in PTM (Push To Make) button on the shaft. The rotary encoders I'm using has 20 positions/stops/clicks per full 360° rotation. Inside a rotary encode there are basically 2 switches offset by 90°, this is what allows you to determine which direction the shaft is being turned/rotated(clockwise or anticlockwise). I'm not going to get into exactly how the 2 switches work together as explaining it is not a simple task using just words, but if you really want to know then I strongly suggest that you watch a YouTube videos on the subject, it is simple enough to follow on video.

    What can you use a rotary encoder for.
    A perfect example would be if you were using an LCD1602 16 x 2 display in one of your projects and you wanted to navigate through a 10 category menu system with sub categories. On the LCD1602 display you can only see 2 category menu items at any one time out of 10, so you have 2 navigation options to choose from. Option 1 uses 3 buttons (up, down and select), option 2 uses 1 rotary encoder (anticlockwise up, clockwise down, push to select), three holes verses one hole.

    AppStart
    Position: 1
    Position: 2
    Position: 3
    Position: 4
    Position: 5
    Position: 6
    Position: 7
    Position: 8
    Position: 7
    Position: 8
    Clicked
    Position: 7
    Position: 6
    Position: 5
    Position: 4
    Position: 3
    Position: 2
    Position: 1
    Position: 2
    Position: 1
    Position: 0
    Position: 1
    Position: 0
    Position: 1
    Position: 2
    Position: 3
    Position: 2
    Position: 3
    Position: 4
    Position: 5
    Clicked
    Clicked
    Position: 6
    Position: 7
    Position: 8
    Position: 9
    Position: 10
    Position: 11
    Position: 12
    Position: 13
    Position: 14
    Clicked
    Position: 15
    Position: 16
    Position: 17
    Position: 18
    Position: 19
    Position: 20
    Position: 19
    Position: 20
    Clicked

    Please note:
    1 physical position/stop/click actually returns as 2 counts when directly reading from the encoder. To work around this you must use StateChanged and only run your add to counter routine after a set amount of time (around 50ms in my case). If you do not use Millis() then the increments will be 2,4,6,8 etc instead of 1,2,3,4 etc.
    Code:
    'WIRE LEGEND for Rotary Encoder
    'VCC/+ = 3.3V to 5V
    'GND = GND
    'SW = D2
    'DT = D3
    'CLK = D4

    Sub Process_Globals
        
    'These global variables will be declared once when the application starts.
        'Public variables can be accessed from all modules.
        Public Serial1 As Serial

        
    Private CLK, DT, SW As Pin
        
    Private Counter As Int = 0
        
    Private LastStateTime As Long = 0
    End Sub

    Private Sub AppStart
        Serial1.Initialize(
    115200)
        
    Log("AppStart")

        SW.Initialize(
    2, SW.MODE_INPUT_PULLUP)
        SW.AddListener(
    "SW_StateChanged")

        DT.Initialize(
    3, DT.MODE_INPUT)
        DT.AddListener(
    "DT_StateChanged")

        CLK.Initialize(
    4, CLK.MODE_INPUT)
    End Sub

    Sub DT_StateChanged (State As Boolean)
        
    Dim StateTime As Long = Millis()

        
    If StateTime - LastStateTime > 50 Then 'Only run if statechange firing interval is larger than 50ms, adjust to suit
            If CLK.DigitalRead Then Counter = Counter - 1 Else Counter = Counter + 1 'Adjust the counter +-1
            Counter = Min(100Max(0, Counter)) 'Limit the counter between 0 and 100
            LastStateTime = StateTime 'Store last state time
            Log("Position: ", Counter)
        
    End If
    End Sub

    Sub SW_StateChanged (State As Boolean)
        
    If Not(State) Then Log("Clicked"'RE Button has been clicked
    End Sub
    What the project looks like
    IMG_20170517_002328.jpg

    A rotary encoder

    $_57.jpg

    Enjoy...
     
    Last edited: Jan 15, 2018
    Hypnos, Cableguy, Mostez and 5 others like this.
  2. Cableguy

    Cableguy Expert Licensed User

    I was wondering if I should ask for a library for my encoder, since every single arduino sketch I found used one, but then decided to search the forum...
    @Peter Simpson , This will be coming in handy in a few weeks, when I start coding for my soldering station!
     
    Peter Simpson likes this.
  3. Hypnos

    Hypnos Active Member Licensed User

    Hi Peter,

    I followed your tutorial but I got the following strange reading like this::

    Code:
    Position: 3
    Position: 
    2
    Position: 
    3
    Position: 
    4
    Position: 
    3
    Position: 
    2
    Position: 
    1
    Position: 
    0
    Position: 
    1
    Position: 
    0
    Position: 
    1
    Position: 
    2
    Position: 
    1
    Position: 
    2
    Position: 
    1
    When I disconnected the 'CLK' pin, the reading seems better but if I turn the encoder anticlockwise, I still got the increase value:

    Code:
    Position: 1
    Position: 
    2
    Position: 
    3
    Position: 
    4
    Position: 
    5
    Position: 
    6
    Position: 
    7
    Position: 
    8
    Position: 
    9
    Position: 
    10
    Position: 
    11
    Position: 
    12
    Position: 
    13

    Seems I got the same device like you but I have tested two device but the result is the same. Do you have any idea for that?

    I find the device have 2 10k resister on the board, will this caused some trouble?

    IMG_0284.JPG IMG_0285.JPG
     
    spairo likes this.
  4. Peter Simpson

    Peter Simpson Expert Licensed User

    Hello @Hypnos,
    Sorry that I've not responded but I was on holiday and only got back 3 days ago.

    Looking at my code above, you could always try adjusting the value 50 either higher or lower to suite your needs...

    You said "When I disconnected the 'CLK' pin, the reading seems better but if I turn the encoder anticlockwise, I still got the increase value:".

    Are you sure that you have followed my directions exactly, if you have then you might have a faulty RE, I tested the code with 2 or 3 encoders (2 of them are by differed manufacturers), it worked perfect for me.

    Enjoy...
     
    Last edited: May 6, 2018
    Hypnos likes this.
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice