I bought a few MCP4651 dual 8 bit I2C pots for a project. After browsing the arduino libraries and finding nothing,"No big deal" I thought to myself ... I've already written I2C libraries for other parts that were much more complicated! (e.g: ADS1219 24 bit ADC)! so just load up the datasheet and watch the memory maps and commands! ok, there are some stuff on page 49 which seem useful! oh boy was I ever wrong! this data sheet looks like nightmare! the worst documentation for any I2C device I've seen so far. The commands I wrote based on that did absolutely nothing!

I found a code for controlling an I2C pot in one of the arduino examples which is something like this:

#include <Wire.h>

void setup() {
  Wire.begin(); // join i2c bus (address optional for master)

byte val = 0;

void loop() {
  Wire.beginTransmission(44); // transmit to device #44 (0x2c)
  // device address is specified in datasheet
  Wire.write(byte(0x00));            // sends instruction byte
  Wire.write(val);             // sends potentiometer value byte
  Wire.endTransmission();     // stop transmitting

  val++;        // increment value
  if (val == 64) { // if reached 64th position (max)
    val = 0;    // start over from lowest value

I decided to just try it and see what happens (changed the address to the correct value) and crazy enough it actually worked! so I hacked this piece of code to get the first pot to work!

void setPot0(int n){
  if (n>256) n=256;
  if (n<0) n=0;
  if (n<256){
  } else{

and somehow this works! I still can't find this pattern in any of the pages on datasheet, but hey! it works so I'm not gonna complain about that? I still haven't managed to make the pot1 to work, only pot0 ... if you can make sense of how the commands and data bytes should be like, please help me. It's so much more clear in T.I datasheets; you just use the command to write to the register you want and they detail what each register does: enter image description here enter image description here

Edit: here is a link to the datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/22096b.pdf

  • what is your actual question? .... the only question in your post is asking something about complaining
    – jsotola
    Mar 2, 2019 at 23:18
  • my question is how on earth should I send the I2C commands to use the pot. as I mentioned the code I wrote works but matches non of the I2C address and data patterns that they mentioned in their data sheet. I'm not sure what the control bytes should be and what's a general call vs a normal call? they just say general calls can change multiple pots (if present)?
    – OM222O
    Mar 2, 2019 at 23:21
  • general call and normal call are actually part of the I2C specification, it has to do with addressing single or multiple I2C devices
    – jsotola
    Mar 2, 2019 at 23:47
  • Does chapter 4 of the datasheet not give you all the information you need? Including the details of the THREE registers (yes, only THREE) for controlling the device?
    – Majenko
    Mar 3, 2019 at 0:18
  • I still can't find this pattern in any of the pages on datasheet -- Not even in Chapter 4, table 4-1 where it lists the registers? Register 0 is pot 0, and register 1 is pot 1. Clearly stated.
    – Majenko
    Mar 3, 2019 at 0:20

1 Answer 1


The registers are listed in table 4-1. Clearly enough.

The command byte format is shown in chapter 6. That command byte includes the operation and the register number, as well as upper bits for registers that expect more than 8 bits of data.

Two bytes are needed to set a register. The first 4 bits are the register number (0000 for wiper 0, 0001 for wiper 1, and 0100 for the TCON register). The next two bits are the operation as shown in figure 7-1. 00 for a simple write. The next two bits are the upper 2 bits of the data. Following that are the lower 8 bits of data.

So to write a pot 0 value of 0x23 you would write:

0x00 0x23

To write a pot 1 value of 0x65 you would write:

0x10 0x65

To write a pot 1 value of 0x13D you would write:

0x11 0x3D

You can make a simpler function to wrap it for you:

void writePot(uint8_t address, uint8_t pot, uint16_t val) {
    Wire.write((pot & 3) << 4 | ((val >> 8) & 3));
    Wire.write(val & 0xFF);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.