I2C Rotary encoder
Version : I2C-ROT-003 V01.00
Click picture to enlarge


I2C Rotary Encoder

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.

Master Display Rotary encoder SW1 SW2 SW3 I2C SDA I2C SCL }

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.5Volt
Supply current 12mA
Rotary sample speed 5000 Samples per second
Rotary speed 120Cycles per second
I2C clock frequency 500kHz
I2C pullup resistors 10

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

Click picture to enlarge
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.

Click picture to enlarge

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


Board layout


Rotary Encoder PEC11R-4215F-S0024

Dimensions of the rotary encoder :
( See Bourns Datasheet )


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.

Address byte, written by the I2C master:

A7 A6 A5 A4 A3 A2 A1 R/W Ack

Address

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.

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.

The following options are available:

MsgIdOptionDescription
0x1n DirectionSet 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.

0x2nAccelerationSet acceleration. I.E. higher values for fast rotations.
    Values:
  • 0x00 : No acceleration.
  • 0x01 : Enable acceleration.
0xAnSelectTo 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.
0xBnGet ButtonTo 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.
0xCnGet-RotationTo 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.
0xF0Set AddressTo change the I2C slave address.
  • The new address is written in EEProm and is effective immediately.
  • Value range: 0x08 to 0xFE.
0xF1Get NameTo read the firmware Name.
  • Returned as ASCII string in the next read request.
  • Value : 'I2C-ROT-003'
0xF2Get VersionTo read the firmware Version.
  • Returned as ASCII string in the next read request.
  • Value : 'V 01.00'
0xF3Get ReleaseTo 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.

A typical rotary status event consists of 3 bytes:

Switch Valuemsb Valuelsb
Switch
Switch status byte:
b7b6b5b4b3b2b1b0
000B2B1SBA
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

The button status is a single byte.

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.