8 Pins is too many? How about just 2 pins? Using the Bourns encoder with I2C

//8 Pins is too many? How about just 2 pins? Using the Bourns encoder with I2C

Bourns EAW I2C

-Bourns EAW encoder-
Reducing the number of pins required 
using the i2C Expander board


All my content is free.

If you feel that my videos are helping and you would like to contribute, you can toss some coins in the Tip Jar via PayPal.

Select amount then click the “Donate” button.

Brainy-Bits Tip Jar Amount

In the previous tutorial we had a look at the ‘Bourns EAW’ absolute contacting encoder.


It’s great in many ways but it does require eight pins on the Arduino and if you’re using the Arduino UNO, just can run out of pins pretty fast!

In this quick tutorial we will see how to connect it using two pins instead of eight.

We can do this by using an I2C Expansion board which will enable us to communicate with the encoder using the I2C protocol which uses only two pins.

I2C Expansion Module

In the next tutorial we will look at how I2C communcation works and more in depth at this little module.

Quick overview

Like I said we will look at the I2C protocol and this I2C expansion module in more details in the next tutorial, but here’s how we will use it today.

The I2C expansion module has eight pins (P0 – P7) that can be use for input or output, kinda like the ones on the Arduino.

I2C Expansion pins

So instead of connecting the eight pins of the encoder directly to the Arduino UNO we will connect them to this I2C expansion module.

The only connections we need to make to the Arduino UNO are the 5V and ground, and the I2C pins (A4-SDA, A5-SCL) to be able to read all eight pins of the encoder through this module.

Connection Diagram


The connections are the same as in the previous tutorial, except that the encoder pins are connected to the I2C expansion module and not to the UNO.

I2C Expansion module connections:
5V and Ground from the Arduino and A4 – A5 to SDA and SCL on the I2C module

LCD Connections:
5v and Ground from the Arduino and A4 – A5 to SDA and SCL of the backpack

EasyDriver Connections:
Pin 10 and 11 of Arduino to DIR and STEP pin of the driver
Ground of Arduino to Ground of driver
The EasyDriver is connected to a 12V power supply

Bourns EAW connections:
P0 to P7 of the I2C module connected to Pin 1 to 8 of the encoder
Ground of Arduino connected to a Common pin of the encoder


We are using the same library as in the previous tutorial, last time we used it with the encoder connected directly to the Arduino, but this library also as the capability to use I2C as a connection.

The code is pretty much the same, but we added the I2C address of the I2C expansion module and the library declaration to use I2C instead of direct connection.

On this I2C module you can select the I2C address with the dip switches from 0x20 to 0x27.  Since we know the I2C LCD backpack uses by default 0x27 we set the I2C expansion module to 0x20 since we can’t have two I2C modules with the same address.

Here’s a table of the possible addresses using the dip switches:

A0  A1  A2
off  off  off      0x20
off  off  on      0x21
off  on  off      0x22
off  on  on      0x23
on  off  off      0x24
on  off  on      0x25
on  on  off      0x26
on  on  on      0x27

/* Control Stepper Motor with I2C 'Bourns EAW' encoder
Created by Yvan / https://Brainy-Bits.com

This code is in the public domain...

You can: copy it, use it, modify it, share it or just plain ignore it!

#include <LiquidCrystal_I2C.h>  // I2C LCD Library by Francisco Malpartida https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home
#include <AccelStepper.h>  // AccelStepper Library https://www.arduinolibraries.info/libraries/accel-stepper

#define lcd_addr 0x27     // I2C address of typical I2C LCD Backpack
#define bourns_addr 0x20  // I2C address of I2C Expander module (A0-A1-A2 dip switch to off position)

// LCD Pins to I2C LCD Backpack - These are default for HD44780 LCD's
#define Rs_pin 0
#define Rw_pin 1
#define En_pin 2
#define D4_pin 4
#define D5_pin 5
#define D6_pin 6
#define D7_pin 7

// Create instance for LCD called: i2c_lcd
LiquidCrystal_I2C i2c_lcd(lcd_addr,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);

const int pinSTEP=11;  // STEP pin of EasyDriver connected to pin 11 of UNO
const int pinDIR=10;  // DIR  pin of EasyDriver connected to pin 10 of UNO

AccelStepper stepper(1, pinSTEP, pinDIR);  // Stepper setup

// Include the Bourns EAW Encoder library and maps
#include <ACE128.h>  // https://github.com/arielnh56/ACE128

#include <ACE128map12345678.h> // mapping for pin order 12345678

ACE128 myACE((uint8_t)bourns_addr, (uint8_t*)encoderMap_12345678); // Using I2C connections
//ACE128 myACE(2,3,4,5,6,7,8,9, (uint8_t*)encoderMap_12345678);    // Using direct connections

int16_t multiturn_encoder_value;  // Variable to hold multiturn value of encoder (-32768 to 32767)

void setup() {
  i2c_lcd.begin (16,2); //  our LCD is a 16x2, change for your LCD if needed
  // LCD Backlight ON
  i2c_lcd.clear(); // Clear the LCD screen

  stepper.setCurrentPosition(0);  // Set current position of stepper at startup to zero
  stepper.setMaxSpeed(1000.0);      // Set Max Speed of stepper
  stepper.setAcceleration(5000.0);  // Acceleration of stepper
  stepper.setSpeed(1000.0);  // Speed of stepper

  myACE.begin();    // initialize the encoder library

void loop() {

  multiturn_encoder_value = myACE.mpos();  // get multiturn value from encoder
  stepper.moveTo(multiturn_encoder_value); // set stepper new position to move to
  while (stepper.distanceToGo() != 0) {  // if stepper hasn't reached new position
    stepper.runSpeedToPosition();  // move the stepper until new position reached

// Display the encoder multiturn and stepper position on LCD
  i2c_lcd.print("Encoder: ");
  i2c_lcd.print("      ");
  i2c_lcd.print("Stepper: ");
  i2c_lcd.print("      ");  

Like before I think this encoder is great for some projects and is pretty cheap for what it can do.

But if you are running out of available pins on your Arduino you might want to use this I2C connection method to use two pins instead of eight.

In my testing I didn’t feel much of a slow down in the response of the encoder when using it, but using I2C does introduce some overhead.

So depending on your project you might still want to use the full eight pin connection, but that would be only in certain cases.

Thank you for stopping by!


Copy and Paste the above code/sketch in your Arduino IDE software.

Link to the libraries used in this tutorial:

By | 2019-02-27T18:02:57-05:00 February 27th, 2019|Tutorials|


  1. Brendan May 13, 2020 at 11:51 am - Reply

    I am trying to use your code which I see is similar to the 0x20 example code form the ACE128 test files. I for some reason keep getting a compile error on this part:

    ACE128 myACE((uint8_t)bourns_addr, (uint8_t*)encoderMap_12345678); // Using I2C connections

    saying: no matching function for call to ‘ACE128::ACE128(int, uint8_t*)’

    Any advice or suggestions on how to get that working?

  2. Tim Rehfeldt January 23, 2020 at 11:27 pm - Reply

    Hi Yvan,

    I’d like to thank you for your tutorial. You helped me build my first Arduino project! I could not have done it without you.

    I was excited to see this new article. The 8 Arduino pins used in the previous article limited what I could add to the project. With the I2C Expansion board, I can modify my project to add the encoder feedback and hopefully read it on the 2nd line of the display and record the last position when the Arduino is reset. I just don’t know how to do it (yet). Can I entice you somehow to build that into your next article? That would be awesome!

  3. Andrey November 17, 2019 at 4:13 pm - Reply

    Hi Yvan, can you make the set and ship the tested set it to Minnesota USA? I’m assembling a pendant to control my large 3d printer, your rotary encoder+ arduino would work for that. Ideally has to be x10 and x100 buttons and a larger display. Can I contact you to discuss?

  4. Darrell June 23, 2019 at 9:39 am - Reply

    Great tutorial but I keep getting an error message on the code.

    no matching function for call to ‘LiquidCrystal_I2C::LiquidCrystal_I2C(int, int, int, int, int, int, int, int)’

    Arduino: 1.8.9 (Windows Store (Windows 10), Board: “Arduino/Genuino Uno”

    I2C_ROTARY_ENCODER_LCD:20:84: error: no matching function for call to ‘LiquidCrystal_I2C::LiquidCrystal_I2C(int, int, int, int, int, int, int, int)’

    LiquidCrystal_I2C i2c_lcd(lcd_addr,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);


    In file included from C:\Users\user\Documents\Arduino\I2C_ROTARY_ENCODER_LCD\I2C_ROTARY_ENCODER_LCD.ino:2:0:

    C:\Users\user\Documents\Arduino\libraries\LiquidCrystal_I2C/LiquidCrystal_I2C.h:57:3: note: candidate: LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t, uint8_t, uint8_t)

    LiquidCrystal_I2C(uint8_t lcd_Addr,uint8_t lcd_cols,uint8_t lcd_rows);


    C:\Users\user\Documents\Arduino\libraries\LiquidCrystal_I2C/LiquidCrystal_I2C.h:57:3: note: candidate expects 3 arguments, 8 provided

    C:\Users\user\Documents\Arduino\libraries\LiquidCrystal_I2C/LiquidCrystal_I2C.h:55:7: note: candidate: constexpr LiquidCrystal_I2C::LiquidCrystal_I2C(const LiquidCrystal_I2C&)

    class LiquidCrystal_I2C : public Print {


    C:\Users\user\Documents\Arduino\libraries\LiquidCrystal_I2C/LiquidCrystal_I2C.h:55:7: note: candidate expects 1 argument, 8 provided

    C:\Users\user\Documents\Arduino\libraries\LiquidCrystal_I2C/LiquidCrystal_I2C.h:55:7: note: candidate: constexpr LiquidCrystal_I2C::LiquidCrystal_I2C(LiquidCrystal_I2C&&)

    C:\Users\user\Documents\Arduino\libraries\LiquidCrystal_I2C/LiquidCrystal_I2C.h:55:7: note: candidate expects 1 argument, 8 provided

    C:\Users\user\Documents\Arduino\I2C_ROTARY_ENCODER_LCD\I2C_ROTARY_ENCODER_LCD.ino: In function ‘void setup()’:

    I2C_ROTARY_ENCODER_LCD:44:11: error: ‘class LiquidCrystal_I2C’ has no member named ‘setBacklightPin’



    I2C_ROTARY_ENCODER_LCD:44:41: error: ‘POSITIVE’ was not declared in this scope



    Multiple libraries were found for “LiquidCrystal_I2C.h”
    Used: C:\Users\user\Documents\Arduino\libraries\LiquidCrystal_I2C
    Not used: C:\Users\user\Documents\Arduino\libraries\LiquidCrystal_I2C.h
    Not used: C:\Users\user\Documents\Arduino\libraries\LiquidCrystal_I2
    Multiple libraries were found for “Wire.h”
    Used: C:\Users\user\Documents\Arduino\libraries\Wire
    Not used: C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.21.0_x86__mdqgnx93n4wtt\hardware\arduino\avr\libraries\Wire
    Multiple libraries were found for “EEPROM.h”
    Used: C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.21.0_x86__mdqgnx93n4wtt\hardware\arduino\avr\libraries\EEPROM
    Not used: C:\Users\user\Documents\Arduino\libraries\E2PROM
    exit status 1
    no matching function for call to ‘LiquidCrystal_I2C::LiquidCrystal_I2C(int, int, int, int, int, int, int, int)’

    This report would have more information with
    “Show verbose output during compilation”
    option enabled in File -> Preferences.

Leave A Comment