B4R Tutorial Using an incremental rotary encoder

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.
B4X:
'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(100, Max(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:

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!
 

Hypnos

Active Member
Licensed User
Hi Peter,

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

B4X:
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:

B4X:
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
 

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:
Top