Many projects need a user interface to control its settings. Rotary encoders are typically great units for this job.
Multiple rotary encoders can be useful so that each encoder controls a single entity in your project.
But it is not always easy to connect multiple encoders to a processor because each encoder requires 3 pins.
This module supports 3 rotary encoders, each with a push button. A dedicated processor scans the rotary encoders
and provides an I2C interface, so that the main processor can use its I2C interface to read the
status of the 3 rotary encoders.
The main processor no longer needs to handle the time critical rotary interface functions, and can spend its cycles
on more useful actions.
This Rotary controller is intended to provide a user interface, with low-frequency rotary encoders.
High-speed encoders such as on the shaft of electro motors are not supported.
A rotary encoder provides an 'incremental' signal. It can be used to increase/decrease a numerical value,
but you cannot derive the actual value from the position of the knob, as with a potentiometer. This means
that in most cases you will need some display to show actual settings.
Applications
Function generator
1 rotary to set frequency
1 rotary to set amplitude
1 rotary to set offset
Use rotary switch to select rude/fine settings.
Use Long button to activate a function menu.
Power supply unit
1 rotary to set voltage limit
1 rotary to set current limit
Use rotary switch to select rude/fine settings.
1 rotary to select functions such as On/Off, modulation.
Control X-Y-Z robot arm
1 rotary for each direction
Control a model vehicle
1 rotary for speed. (Press button to stop).
1 rotary for steering. (Press button for stright ahead).
1 rotary for function menu.
RGB light control
1 rotary for each color.
Multi light dimmer
1 rotary for each color.
Very accurate Computer mouse replacement.
1 rotary for x.
1 rotary for y.
1 for function selector.
Features
Dual I2C connectors
To allow pass-through of I2C bus to other units.
Programmable I2C address
To prevent address collisions with other I2C units on the bus.
To allow multiple rotary controllers on the same bus.
Rotary direction
A rotary encoder can be rotated clockwise or counter-clockwise. A finite number of 'clicks' can be detected per revolution,
depending on the type of rotary encoders (typically from 12 to 30). The processor monitors the movement of the rotary encoder and counts the number of steps. Clockwise
rotations should result in a positive count value, and counter-clockwise rotations result in a negative value.
Proper detection of direction depends on the type of rotary encoder, and on the actual mounting of the encoder on the board.
Some encoders close the A switch first when turning clockwise, while other encoders start with the B switch. And mounting
the rotary encoder on the backside of the board will effectively exchange the A and B connections.
The direction of rotation can be programmed as needed.
The number of clicks is reported as a 16-bit signed integer (MSB first), resulting in a range of +32767 to -32768.
The master should frequently request status updates to keep the values low enough.
The controller will count the number of clicks between status updates. This click counter is reset with each status request from
the I2C master. So when the master reads the status once per second or so, it still gets the total number of clicks
for each rotary encoder.
The I2C master application should accumulate all movement values to calculate an absolute setting.
System Start
Start Value = 0
Rotary reports +3 clicks
New Value = 3
Rotary reports +2 clicks
New Value = 5
Rotary reports -1 clicks (Turned backwards)
New Value = 4
Rotary acceleration
Sometimes it is needed to update a user value over a large range of values. Such updates would require a large
number of rotations. A rotary acceleration can be enabled so that the weight of a click is increased when the encoder is
rotated faster.
Push Button
Pushing on the shaft of the encoder will close a momentary switch S.
The status of the switch is reported to the I2C master as actual status of the switch.
The master may miss status updates if the status requests are not frequent enough. The controller remembers
a short push event as if the encoder switch is used as a push button.
The switch can be treated as push button.
Short push
A 'short push' is reported when the encoder is pushed briefly, less than 1 second.
This condition is reported as soon as the switch is released.
Long push.
A 'Long Button' is reported when the button is pushed longer than 1 second. This report is sent immediatly when the
push duration is long enough, even when the button is still being pushed.
The duration of a long push (in milliseconds) can be set in the configuration.
Only a single push event can be reported per status message. Pressing the button multiple times between status
requests will have no effect.
Electrical characteristics
Minimum
Nominal
Maximum
Supply voltage range
2.8
5.5
Volt
Supply current
12
mA
Rotary sample speed
5000
Samples per second
Rotary speed
120
Cycles per second
I2C clock frequency
500
kHz
I2C pullup resistors
10
kΩ
Performance
Rotation speed
The datasheet of the rotary encoder (PEC11R-4215F-S0024) mentions a maximum speed of 60 rpm. That is one revolution (24 clicks) per second
which is not very fast. Manual twisting of the shaft results easily in higher speeds. However, testing has shown that contact
bouncing increases with speed, and becomes so bad that it is no longer possible to extract any sensible information from the
contacts signals.
The firmware of this board applies a software debounce algorithm to make the performance a little better. So we can put the limit
a little higher. Testing shows good results up to a speed of 100 clicks (4 revolutions) per second.
The on-board firmware must sample the rotary signals fast enough to catch every state. That is at least 4 states per cycle.
The actual sample frequency in this application is 5000 per second, resulting in 50 samples per cycle at 100 cycles per second.
Contact bouncing
Lets have a look at contact bouncing of a rotary encoder. Here we connected an oscilloscope to the contacts of a rotary encoder,
and gave it a twist. There are no capacitors or filters, just a 40k pullup resistor on each pin. See what happens :
When you twist an encoder shaft, you increase to rotation speed. We see nice undistorted rotary signals on the left-hand side
of the screen, when the speed is relatively low. At the end of the screen we see a higher speed, and a lot of contact noise.
We see that bouncing kicks-in when the low period is shorter than approx 5 milliseconds.
You can see that there is only noise when the signal is low. Which makes sense as the contact is open when the signal is high,
and open contacts don't bounce.
Here we zoom in and see that the noise consists of a lot of narrow spikes, but also some wider errors. The yellow signal is
low for about 2.75 milliseconds. The software samples at 5 samples per millisecond, so we get 14 samples during this period.
Problem is that there is a good chance to capture an error signal and thus to take the wrong conclusion.
We can be quite sure about the low signals. If we see a zero, then the contact is closed for sure. But if we see a high,
then it could be an open contact, but it can also bouncing closed contact.
It may prove difficult to do a software debounce on such noisy signals. But it is also clear that the narrow spikes
can easily be filtered-out by an R/C filter. A filter R*C value of 0.5 milliseconds should be more than adequate.
For example : R = 10K, C = 47nF.
Components
Rotary encoders
3 rotary encoders.
Supported encoders
PEC11R-4215F-S0024 (Bourns)
Metal D-type shaft 15 mm
Bushing
24 detents per revolution
24 cycles per revolution
Switch
Other encoders are compatible:
PEC11-xxxx-S00xx (Bourns)
PEC12-xxxx-S00xx (Bourns)
EC11B (ALPS)
EC11E (ALPS)
EC11G (ALPS)
KY-040
AtMega328P
Dedicated processor.
Features:
To scan the movements of the rotary encoders.
To provide I2C interface.
Arduino bootloader on serial Port to support software updates.
I2C interface
4-pin interface connector.
Features:
To report rotary movements to a host processor.
Leds on SDA and SCL pins.
5 Volt power on interface connector.
UART interface
5-pin interface connector.
Features:
To report rotary movements to a host processor.
Leds on TxD and RxD pins.
5 Volt power on interface connector.
Supports setting of configuration parameters.
Diagnostics by serial port.
DTR pin to trigger arduino bootloader.
Schematic diagram
Special hardware features:
I2C connector has power pins. So a single 4-pin cable is sufficient to connect the board to a host system.
Indicator lights on the I2C data SDA and clock SCL.
Weak pullup resistors on SDA and SCL.
Optional indicator lights on all rotary switches.
Uart connector, with DTR line to allow triggering of bootloader by avrdude.
Optional indicator lights on Uart data pins.
Power on Uart connector.
Board layout
Connector pins : 2.54 mm (100 mil)
Resistors : SMD 1206
Capacitors : SMD 1206
Leds : 5 mm through hole
CPU : AtMega328P (Dil 28 pin).
Rotary Encoder PEC11R-4215F-S0024
Dimensions of the rotary encoder :
( See Bourns Datasheet )
Where
L = 15 mm
LB = 5 mm
F = 7 mm
Firmware functions
I2C interface
The module comes with a pre-programmed microprocessor with a default interface, as described in the next section.
We use different background colors to indicate the direction of the data.
From master to slave
From slave to master
I2C Messages
I2C messages are either 'Write' messages or 'Read' messages. All messages consist of multiple bytes where each byte
has 8 data bits (The most significant bit is sent first). Each byte is followed by an Ack bit to indicate that
the data is received correctly.
The rotary encoder module acts as a slave unit. The host system must provide the I2C
clock signal and decide when to send a message. The slave unit responds to incoming messages,and may return a response
on request of the I2C master.
Each message starts with a 'Start condition'. The first byte of each message consists of a 7-bit device address and
a Read/Write bit. Multiple slave devices can be listening on the bus. Only the slave unit with a matching address is selected
and will respond to the message. All other slave units will ignore the message until a new message is started.
An I2C slave only responds when the address matches with the actual Slave address.
All slaves on a bus must have a different Slave address. This module comes with a default slave
address, but the address can be updated when this address is already in use by other slaves on the bus.
This also makes it possible to have multiple rotary encoder units on the bus in case you need more than 3 encoders.
Default address :
0xA0 : Write messages (R/W = 0).
0xA1 : Read messages (R/W = 1).
This address can be updated through uart commmands. The new address is registered in EEProm memory
and remains active until a new address is set.
Message Id
Several options can be set through the I2C bus. Most options are registered in EEProm and will
remain in effect also after a power cycle. Default options are provided so that the board can be used without any programming.
Options are identified by MsgId number. Setting an option requires a write message consisting of a 'write' address,
a MsgId and the new value.
Most options can be set per rotary encoder. The low nibble of the MsgId is used to indicate a specific rotary
encoder that should be affected.
Supported values :
n = 0 : All.
Option should be applied to all 3 rotary encoders.
n = 1 : Select encoder SW1.
n = 2 : Select encoder SW2.
n = 3 : Select encoder SW3.
The following options are available:
MsgId
Option
Description
0x1n
Direction
Set direction of rotary when turned clockwise:
MsgId variants:
0x11 : Set encoder SW1.
0x12 : Set encoder SW2.
0x13 : Set encoder SW3.
Values:
0x00 : A leads B
0x01 : B leads A
Actual direction depends on the type of rotary encoder and is inverted when the encoder
is mounted on the solder side of the board.
Default : 0x00 (A leads B).
New value is registered in EEProm.
0x2n
Acceleration
Set acceleration. I.E. higher values for fast rotations.
Values:
0x00 : No acceleration.
0x01 : Enable acceleration.
0xAn
Select
To select which encoder is read in the next status reports.
MsgId variants:
0xA0 : Read all 3 rotary encoders (default)
0xA1 : Read encoder SW1.
0xA2 : Read encoder SW2.
0xA3 : Read encoder SW3.
Returns a Rotary status report for one or all rotaries.
Rotary status is cleared when read by the master.
0xBn
Get Button
To read the button status.
MsgId variants:
0xB1 : Button of SW1.
0xB2 : Button of SW2.
0xB3 : Button of SW3.
Returns:
0 : Button not pressed.
1 : Short Button.
2 : Long Button.
Button status is cleared when read by the master.
0xCn
Get-Rotation
To read the encoders rotation.
Returns a signed integer (MSB first) with the nr of clicks.
Rotation is cleared when read by the master.
MsgId variants:
0xC1 : Rotation of SW1.
0xC2 : Rotation of SW2.
0xC3 : Rotation of SW3.
0xF0
Set Address
To change the I2C slave address.
The new address is written in EEProm and is effective immediately.
Value range: 0x08 to 0xFE.
0xF1
Get Name
To read the firmware Name.
Returned as ASCII string in the next read request.
Value : 'I2C-ROT-003'
0xF2
Get Version
To read the firmware Version.
Returned as ASCII string in the next read request.
Value : 'V 01.00'
0xF3
Get Release
To read the firmware release date.
Returned as ASCII string in the next read request.
Value : '2020-04-27'
Response messages
All response messages start with a header consisting of the slave address and a message-id.
Response message
Address+R
Address
MsgId
Msg data
0xA1
0xA0
0xA0
...
...
...
Address+R
The Master starts a session by sending Address+Read. Only the slave with a matching address will respond.
Address
The slave address (with R/W bit = 0) is included in the response so that the master can derive from
the actual message where it came from.
Can be useful in a project with multiple encoder boards.
MsgId
The MsgId indicates the format of the remainder of the message. It matches with the most recent MsgId
as received in a previous I2C write from the master.
Msg data
The data contents depends on the MsgId, as described in the next paragraphs.
MsgId 0xAn : Rotary status report
The master should frequently request for status reports. Such reports will contain the rotary events
since the previous status report. A status report is an I2C read message. The host sends an
address byte with the R/W bit set (Read request). The slave unit will then return the requested status.
MsgId variants:
0xA0 : Status of all 3 rotary encoders.
0xA1 : Status of SW1.
0xA2 : Status of SW2.
0xA3 : Status of SW3.
A typical rotary status event consists of 3 bytes:
Switch
Valuemsb
Valuelsb
Switch
Switch status byte:
b7
b6
b5
b4
b3
b2
b1
b0
0
0
0
B2
B1
S
B
A
0x01 : A is momentary status of contact A. Set if switch is closed.
0x02 : B is momentary status of contact B. Set if switch is closed.
0x04 : S is momentary switch status. Set if switch is closed.
0x08 : B1 is set if the switch was pushed shortly (short push)
0x10 : B2 is set when the switch was pushed for an extended duration (long push).
Valuemsb/lsb
Actual number of rotary clicks since previous status report.
16-bit signed integer.
Positive for clockwise, negative for counter-clockwise rotation. Depending on 'm_Direction' bit.
The controller keeps status of all 3 rotary encoders. The status report message includes the status from the
encoder that is selected in the most recent select message. "All" results in a status report for all 3 rotary encoders.
Example messages : Read SW2
Master sends write request : Select SW2.
Address+W
MsgId
0xA0
0xA2
Master starts a read request. Slave returns a Status report for SW2 as requested by MsgId.
Request
Header
SW2
Address+R
Address
MsgId
Switch
Valuemsb
Valuelsb
0xA1
0xA0
0xA2
0x09
0x00
0x03
Example messages : Read all encoders.
Master sends write request : Select all.
Address+W
MsgId
0xA0
0xA0
Master starts read request. Slave returns Status report for all encoders.
Request
Header
SW1
SW2
SW3
Address+R
Address
MsgId
Switch
Valuemsb
Valuelsb
Switch
Valuemsb
Valuelsb
Switch
Valuemsb
Valuelsb
0xA1
0xA0
0xA0
0x09
0x00
0x03
0x09
0x00
0x03
0x09
0x00
0x03
MsgId 0xBn : Button report
MsgId variants:
0xB1 : Read button of SW1.
0xB2 : Read button of SW2.
0xB3 : Read button of SW3.
The button status is a single byte.
The following values are supported:
0x00 : Button is not pressed.
0x01 : Button is pressed shortly.
0x02 : Button is pressed long.
Example messages : Read button SW2
Master sends write request : 'Read Button SW2'.
Address+W
MsgId
0xA0
0xB2
Master starts a read request. Slave returns a Button report.
Request
Header
SW2
Address+R
Address
MsgId
Button
0xA1
0xA0
0xB2
0x02
MsgId 0xCn : Rotation report
This message reports the number of clicks that the shaft is rotated since the previous rotary report.
Clockwise rotations result in a positive value, counter-clockwise are negative. The value 16-bits.
A third byte indicates if the rotary shaft was pressed down while rotating. A user application may use
that for handling of the rotation.
MsgId variants:
0xC1 : Rotation of SW1.
0xC2 : Rotation of SW2.
0xC3 : Rotation of SW3.
The rotation is returns as a 16-bit signed integer, sent a 2 bytes, MSB first.
A third byte indicates if the shaft was pushed while rotating.
Example messages : Read rotary SW3
Master sends write request : 'Read rotary SW3'.
Address+W
MsgId
0xA0
0xC3
Master starts a read request. Slave returns a Rotary report.
Request
Header
SW3
Address+R
Address
MsgId
Rotary
Switch
0xA1
0xA0
0xC3
0x00
0x07
0x01
Rotary = 0x0007 : 7 clicks clockwise.
Rotating 7 clicks counter-clockwise would result in a value 0xFFF9.
Switch = 0x01 : Button was pressed while turning the knob.
Serial port interface
A serial port is provided.
Features:
Update config options
Status monitoring
Firmware updates
Uart parameters
38400 baud
8 bit
No parity
1 stop bit
No handshake
Serial port connector
Pin
Name
Description.
1
Vcc
Power. 5V. Can be used to power the board.
2
Gnd
Power 0V.
3
RxD
Incoming data to the processor.
4
TxD
Outgoing data.
5
DTR
High-to-Low transition will pull reset. Can be used to trigger the bootloader.
Serial port messages.
All uart messages are plain ASCII text. A simple terminal program will allow you to enter the
messages and examine the response. A built-in command-line interpreter handles the requests and
generates the responses.
[CR] terminates a message and triggers interpretation.
Max message length is 80 characters.
Messages are not case-sensitive. Uppercase and lowercase is treated as identical.
help
Prints a list of supported commands
version
Prints actual firmware version info
I2C Slave 0xAA
Sets a new Slave address 0xAA. This new address is registered in EEProm and remains
valid until a new address is set.
Range 0x08 .. 0xFE.
Lowest bit (Bit 0) is ignored.
I2C uses this Bit 0 to distinguish between Read (0x01) and Write (0x00) messages.
SWn 1
Sets direction of switch SWn (n can be 1, 2 or 3)
Value van be 0 (A leads B) or 1 (B leads A)
Direction is stored in EEProm and remains valid after powerdown.
Config
Prints configuration details.
Software updates
ISP programming
The AtMega328P supports firmware updates by means of ISP programming. A dedicated 6-pin ISP connector is provided.
An ISP programmer can be used to perform the firmware update.
The actual update procedure depends on the ISP programmer that is used. Using ISP will delete the previous
firmware and the bootloader.
Please note that no Xtal is present. The processors fuses are programmed to make the processor run on its
internal 8 MHz RC oscillator.
Optiboot Bootloader
A copy of the 'Optiboot' bootloader is present in the AtMega328P. This allows firmware updates through the serial port.
This bootloader is updated to work on the internal RC oscillator. Communication speed is reduced to 38400.
Verbose. More v's gives more details from avrdude.
-D
Skip chip delete. Not required using bootloader.
-u
Disable 'Safe mode'. Not applicable for bootloader.
-p AtMega328p
Set Cpu type AtMega328p
Alternative value : m328p
-P COMx
Set communication channel
Must match with actual com channel on the host. See device manager (run devmgmt) on your PC.
-c arduino
Set communication protocol. Compatible with optiboot.
-b 38400
Set 38400 Baud.
-U..
Set programming job.
RotaryEncoder.hex is the name of the file with the firmware.
Board assembly
Start with small components
All resistors and capacitors use SMD 1206. These are big enough to allow manual soldering and still require
relatively small board space. Please note that we selected relatively high value resistors for the LED's. With 10K
you get only 300uA when an LED is on. Modern LED's give plenty of light with such a small current.
These components should be placed first because board space is limited, and the smaller components may be hard to
reach once the other components are present.
Soldering these components should be done with very little solder. You should use a pair of tweezers to hold
the component in place and then apply a tiny bit of solder on one side of the component. Make sure that the
position is correct before soldering the other side. Moving the part is a lot more difficult once both sides
are fixed to the board.
Resistors
All resistors are 10 kΩ. These are marked "103" where the last digit is an exponent, meaning "3 extra zeros".
Polarity is not applicable to these resistors. They can be mounted either way.
Resistors should be mounted on positions marked Rx on the board (x is the number).
Capacitors
A few capacitors are also needed. All capacitors are 100 nF. These have no marking, but they are all the same value.
Polarity is not applicable to these capacitors.
Capacitors should be mounted on positions marked Cx.
Rotary encoders
The board is designed so that it can be mounted directly behind the front panel of a project box. The shaft of the 3
rotary encoders should be mounted through holes in the front panel and suitable knobs can be installed.
We recommend to mount the encoders on the bottom side of the board, opposite to the other components. This results in a flat
surface towards the back side of your front panel and will give you easy access to the connectors, even with
the board installed in a project box.
Leds
The Leds for the status of the encoders can best be mounted on the component side of the board. These will then
only be visible from within the project box. These LED's are not needed for the proper operation of the module and
can be left out if you don't need the status of the encoder pins.
Make sure that de leds are mounted with correct polarity. Leds have an Anode and a Cathode, and the Anode must be connected to +Vcc.
The cathode of an LED is marked. The base of the round led is a little flat near the cathode.
Connectors
You can use header pins for both interface connectors. It is recommended to place those pins at the inside
of your project box, so on the component side of the board. Depending on the space in the box, you can select
between straight pins (with headers perpendicular to the board) or 90 degree angled pins. The later is recommended
especially when you have limited space behind the front panel.
You will need at least one 4-pin header for the I2C bus. And perhaps you also want a second
I2C connector to route the bus to other I2C units.
The 5-pin uart connector is also useful if you have a suitable uart interface module to connect it to you PC.
Microprocessor
It is best to mount the processor in a socket. A 28 pin DIL socket is included. This socket should be soldered
on the board, with the Pin-1 marking at the side of the dent, as indicated on the silkscreen of the board.
The Processor can be inserted in the socket. Make sure that the pin 1 marking is at the correct side.
Mounting
There are 2 mounting holes provided. These are not needed when the rotary encoders are attached to the front panel.
The soldered pins from the encoders will hold the board in place.