High Resolution Absolute Encoder - Arduino & Pi

Bourns ACE-128 Absolute Contacting Encoder - 128 positions - with I2C interface - Arduino & Raspberry Pi libraries

Similar projects worth following
Starting from
arielnh56 has 471 orders / 17reviews
Ships from United States of America
This is a an I2C backpack and Arduino library for the Bourns ACE-128 Absolute Contacting Encoder

In layman's terms, it's a digital control knob that has 8 data pins which will give you 128 unique results around a full circle. It is designed as a control panel knob, but can be adopted for other uses. It is, as far as I know, the smallest and cheapest gray code absolute encoder available today. The product listed here combines this with an I2C backpack and library code so you can add several of these to your Arduino or Raspberry Pi project.

I sell on Tindie

What is it?

A digital control knob providing 128 unique results evenly spaced around a full circle. It is designed as a control panel knob and includes a nut and washer, but can be adopted for other uses. The module communicates via the I2C bus with 16 addresses available.

This is an alternative to using a potentiometer and analog pin, allowing full-turn and multi-turn operation, and is not impacted by temperature variations. The library includes optional automatic saving of logical zero and multiturn offset to EEPROM so that the system will remember these settings after power down or reset.

Now also supported on the Raspberry Pi.

It differs from the more common incremental rotary encoder which has only two or four values in a rotation and is designed to measure full rotations and direction. This measures angles.

From the datasheet

Until now, the choice of an absolute encoder meant an expensive, and larger sized product. Through the use of combinatorial mathematics, the absolute code pattern of the Bourns® Absolute Contacting Encoder (ACE™) is placed on a single track for a very economical, energy efficient and compact product. Bourns® ACE™ provides an absolute digital output that will also retain its last position in the event of a power failure. An intelligent alternative to incremental encoders and potentiometers, the Bourns® ACE™ is ideally suited for many industrial, automotive, medical and consumer product applications.

It is, as far as I know, the smallest and cheapest gray code absolute encoder available today.

Why did you make it?

I used these to build a head-following mechanism for my Dalek dome and eye, using hand-made pcbs. I found the sensor online and say it could provide the rotational position sensing I needed, but there was no Arduino support, so I developed the code to support that.

Two were used to convert wiper motors into high powered servos

wiper motor servo

A third was used to detect the operator's head rotation in a motion control headset

enter image description here

A fourth is now installed in a control module and is used to enter PID tuning variables.

To support the ACE128 I wrote an arduino library to handle the I2C communications and gray code translation. The device itself generates gray code which has to be converted to normal numbers before use, and that takes some binary math - especially if you connect the pins in a different order from the datasheet.

My hobby is progressing to manufactured PCBs and SMD soldering, so I pulled this design out and made some up. To my delight, the first batch all work!

What makes it special?

The ACE-128 is the smallest and cheapest absolute encoder available today. It uses some really ingenious mathematics in its design. This library and package are a unique solution for easily including digital knobs into Arduino projects.

You may prefer this to using a potentiometer and analog pin in applications where:

  • temperature sensitivity of the potentiometer is causing the value to drift. As the device uses mechanical contacts it is not susceptible to environmental variations and will retain its value when powered down.
  • you need full turn angular measurement
  • you need multiple turns for a wider range
  • you need precise control - with approx 3 degrees between positions and a very slight tactile feedback you can get the number you want without overshoot.

You may prefer this to using a rotary encoder where:

  • absolute position is important (rotary encoders sense relative movement - typically full rotations and direction only)
  • you need the system to remember the relative zero when powered down
  • finer resolution than incremental rotary encoders (most measure 90 degree increments)

What's this doing on Hackaday?

I'm selling these on Tindie and Hackaday seems like the right place to put support documentation. I haven't used Hackaday before so we'll see how it goes.

I sell on Tindie

  • QWIIC Edition now fully stocked

    Alastair Young10/28/2019 at 15:58 0 comments

    The QWIIC edition is now fully stocked with all permutations of address, assembly and EEPROM.

    Now available in red! (purple ones ship first, picture updates will happen)

  • OSHWA Certification

    Alastair Young10/21/2019 at 23:01 0 comments

    This project is now OSHWA Certified - Open Source Hardware Association

  • QWIIC Edition

    Alastair Young09/26/2019 at 17:51 0 comments

    A new addition to the range - the QWIIC Edition. This has two Sparkfun QWIIC connectors in place of the 0.1" header and Grove..

    Currently in OshPark purple, and 3 available. Red boards are in the mail.

    I have reached out to Sparkfun to see if I can sell them through their site, but have not heard back. So they will be on Tindie at least for now at

  • v2.0.0 library update and EEPROM modules

    Alastair Young06/23/2019 at 20:31 0 comments

    v2.0.0 is checked in and should appear in the library manager soon.

    Release notes:

    The code has all been combined into the ACE128.h file so we can use #defines in there to turn on and off bits of unused code for different projects. So when I say uncomment #define below I mean in the ACE128.h library file itself. These don't work from your .ino file beacuse of the way the Arduino IDE compiles stuff.

    This is a major release upgrade due to the following two non backward compatible changes introduced to remove little used code and save FLASH.

    1. MCP23008 support is no longer enabled by default. Uncomment #define ACE128_MCP23008 to turn it back on.
    2. Direct pin attachment is no longer enabled by default. Uncomment #define ACE128_ARDUINO_PINS to turn it back on. This will turn off I2C pin expander code - I figure nobody uses both. If you do, let me know.

    New Features

    1. Support for SAM controllers e.g. MKR series Arduinos. This is actually just not calling the EEPROM stuff for these units, as they don't have EEPROM. This means that by default they cannot save state, which brings us to:
    2. Support for I2C EEPROM to save state. Enable this by uncommenting #define ACE128_EEPROM_I2C. It will use a chip at address 0x50 by default.
    3. Support for disabling the EEPROM code altogether to save flash. Uncomment #define ACE128_EEPROM_NONE for this. This is the default for the SAM units and removes the EEPROM constructors.
    4. New board revision 3.1. Supports an I2C EEPROM chip. Rounded corners to be easier on the ziploc bags.
    5. Reworked ACE128test.ino with lots of comments - this is now the primary usage instructions. Also now supports serial display by default with I2C LCD as an option. Direct connect LCD support removed.
    6. added two examples ace128_0x20 and ace128_0x38 for module customers to test their units out of the box.

  • Updated board design

    Alastair Young11/27/2018 at 05:49 0 comments

    Prototype v3.0 boards in the works at

    Main change is the addition of a footprint for a Microchip SOT-23-5 I2C EEPROM

    This will theoretically provide EEPROM storage to retain state on microcontrollers without internal EEPROM.

    Other footprints unchanged so I can use the old stencil when this is not populated.

    Other tweaks:

    • Fiducials for cnc pick and place
    • Filled in circles on the address silk screen
    • Rounded corners to make it less poky on the packaging

    This is not checked in yet.

  • SAMD21 Arduino Zero/MKR support

    Alastair Young11/15/2018 at 18:15 1 comment

    A customer plugged a module into their Arduino MKR WiFI 1010 and discovered the code did not compile.

    The current library code uses EEPROM to remember the zero position and multi-turn offset between power cycles. 

    Some of the new Arduino boards such as the Zero and the MKR use the SAMD21 chip which has no EEPROM memory, and therefore the current library code is not compatible with these boards. 

    I welcome input from customers and observers as to how to work around this problem. Repeatedly writing to the SAMD21 flash instead via EEPROM emulation is generally not recommended due to the limited write cycles on that memory.

    A couple of ideas:

    • I am considering tweaking the next version of the board to optionally have an I2C EEPROM or FRAM chip. 
    • Another idea I was working on was a design using an ATTiny841 instead of the pin expander, which would run all the code on-board. I got carried away and wrote the code for this including using a spare pin and memory to drive synchronized neopixel rings. That idea has been on the shelf for a while. (looking at that code, I know I wrote more. Hope I still have it, will check in what I have)

  • The Ace128 moduleis now suported on the Raspberry PI

    Alastair Young06/09/2017 at 08:28 0 comments

    I just checked in the code port for python on the Raspberry Pi

    I uses a file in place of the EEPROM for state saving, and the constructor builds the encoder map on the fly. Apart from that the functionality is the same as the Arduino library.

  • New board revision

    Alastair Young04/23/2017 at 04:01 0 comments


    • Board is now 1.2" square. This provides full support to all four corners of the sensor making soldering it on straight a non-fiddly process.
    • It also adds some space to put sensibly sized solder jumpers for addressing
    • The addition of a 10k resistor array for address pulldowns makes addressing easier and provides the unit with a default address - one less thing to do prior to testing.
    • stainless steel stencil and reflow oven used this time. Much tidier result. All units tested good with no rework needed.

  • Example of multiturn functions

    Alastair Young03/25/2017 at 20:31 0 comments

View all 9 project logs

  • 1
    Step 1

    These instruction videos are bit old at this point. The comments in the ace128test example in the arduino library are more complete and up to date. Also see the readme on github. 

    For basic testing of your module use the ace128_0x20 or ace128_0x38 sketches.

    How to run the ACE128test sketch to verify your device is good and the software it set up right.

  • 2
    Step 2

    Overview of the I2C backpack available on Tindie

  • 3
    Step 3

    Making a custom encoder map (only for wiring your own encoder circuits)

View all 4 instructions

Enjoy this project?



Aditya Mehrotra wrote 02/12/2020 at 20:51 point

Hello! Are there instructions somewhere on how to use this in true absolute encoder sense? In that If pos is at 128 or something, I turn it off and then back on, and let's say I moved the encoder in this time-frame now it's at position 200 or something, it will read 200? Is this a true absolute encoder in that sense or is it an incremental encoder that saves its last state?

To clarify - I mean move the encoder while it is off.

  Are you sure? yes | no

Alastair Young wrote 04/20/2021 at 18:31 point

Sorry about delayed response, I didn't see this. If you use the constructors with the third parameter for EEPROM location it will save your logical zero and multiturn offset to EEPROM and read it back on startup. The position is calculated from the physical location of the device, the logical zero and the multiturn offset. If you are using multiturn it should come back with the right value provided you have not turned it more than half a turn. For the single turn position (signed and unsigned) it should always come back with the correct value.

to your specific question of moving from 128 to 200 while off is a move of +72 which is more than half a turn, so it will assume you moved it less than half a turn the other way (-56), so it would read 72. 

It is a true 7-bit (0-127) absolute encoder. The extension to multiturn capability (16-bit) is done in software and relies on the controller being powered up to see the "rollovers" in real time so it can tell if they are "up" or  "down" and how many.

  Are you sure? yes | no

jasontuntland wrote 01/27/2020 at 15:04 point

I received my encoder exactly as described. Sample Arduino script works great. I can see in the serial monitor the values climb and fall as it rotates. My question is I have not seen how I can configure this as a "position sensor" I need to take advantage of the hardware's unique 128 positions and have it output to a variable the direction that it's pointing to. Having it retain accuracy after a power cycle is crucial.  Thanks!

  Are you sure? yes | no

Alastair Young wrote 04/20/2021 at 18:23 point

Sorry about delayed response, I didn't see this. If you use the constructors with the third parameter for EEPROM location it will save your logical zero and multiturn offset to EEPROM and read it back on startup. The position is calculated from the physical location of the device, the logical zero and the multiturn offset. If you are using multiturn it should come back with the right value provided you have not turned it more than half a turn. For the single turn position (signed and unsigned) it should always come back with the correct value.

  Are you sure? yes | no

Username_nt_available wrote 01/09/2020 at 04:43 point

Hey there, Iam using this rotary encoder but I dont have the I2C backpack. 

Iam planning to get this I2C backpack from the #tindie link you have mentioned.

So Can I get only the backpack or do I need to get the whole encoder module??

And also after the getting the whole module, Can u explain the pin confguration of module i.e., (encoder + I2C backpack) to communicate with the micro controller and also the set of resistors and other components that needs to be connected to micro controller

Thanks in advance......

  Are you sure? yes | no

Alastair Young wrote 01/15/2020 at 00:46 point

Code link is on the project page - "arduino library"
and RPI module

detailed instructions are at the arduino library page. 

Backpacks are available separately with or without 2K EEPROM chips. See the option dropdowns on the tindie page. Also I now have them available with the Sparkfun QWIIC connectors.

This is an I2C device and uses standard I2C connectivity. There are many tutorials on I2C for the arduino - here's a good one that doesn't dive too deep before telling you where to plug it in

Essentially 4 wires and two resistors (4.7k is a good starting value) and you are done. Some tutorials say you don't need the resistors because the arduino has internal pullups - don't believe them, the internal pullups are too weak for reliable operation. One set of resistors per I2C bus - up to 128 devices per bus (in theory)

On the other hand, I think the new MKR arduino boards have proper I2C pullups - check the documentation for your board.

  Are you sure? yes | no

Isaac Wingfield wrote 06/24/2019 at 03:11 point

There are a number of monostrophic codes (i.e. only one bit changes at the time). Only one of them is the Gray code (named after a person, so should be capitalized).

  Are you sure? yes | no

Alastair Young wrote 10/22/2019 at 15:57 point

Thank you for your erudite pedantry. I stand corrected. 

  Are you sure? yes | no

Jamie B wrote 01/24/2018 at 21:41 point

Hi, thanks and I eagerly await arrival of my units.  You comment in the Arduino code that the initial steps to, i think, initialize the IO extender is "required".  This seems to basically look for pin changes and displays "looking for pins".  Is this the case outside of your project's use case also (that this step is required)?  For my project (a child's toy) I would prefer *not* to have to physically spin the encoder several steps before it clears/establishes what position it's in and can react.  My encoder (project) will have an established/unchanging physical "zero" position.  I will have 2 of these; they'll simulate a hot and cold water handle and each be wired to colored LEDs (for bar graphs) and speakers. 

  Are you sure? yes | no

Alastair Young wrote 10/22/2019 at 15:56 point

Sorry for the belated response. The "looking for pins" in the example code is part of my benchmark test for new modules to ensure all the traces have good continuity and identify those that do not. It is absolutely not required in your code. The only thing you need in your setup() is the begin() function which (on the PCF8574(A) modules) just initializes the I2C bus,  sets the pin-expander pins high and pulls the logical zero offset from EEPROM. The physical position of the sensor is a mechanical thing, no twiddling is needed.

  Are you sure? yes | no

Alastair Young wrote 06/06/2017 at 19:05 point

Sorry for the late response - I'm not used to folks actually commenting on my stuff! :-)

The original through-hole design files for the MCP23008 prototype got lost somewhere  - I made those back on 2011. The latest board revision for SMD with PCF8574 are up to date at

I've stuck the OSH symbol on it and the MIT license so have at it. 

  Are you sure? yes | no

anna wrote 04/20/2017 at 18:10 point

Thank you so much! Your documentation and library have been very helpful. Do you have an EAGLE file that uses the ACE128 encoder? The files attached on github won't download properly. I've found a library that includes the I2C chip, but cannot find the encoder. 

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates