Help needed with I2C connections

Hello. I'm trying to program a digipot, and I could not figure out how to convert the commands in bits to Arduino code. I looked at some examples and tried to mimic them, but it did not work.

I'm currently using TI's TPL1401, and the update sequence is "Address byte-Command byte-Data byte-Data byte". The data I wanted to input for each section was 74 for the Address byte, 0x21 for the command byte, and 0x09 and 0x40 for the 2 data bytes.

So, this is what I wrote:

#include <Wire.h>

void setup()
{
  Wire.begin(); 
}

void loop()
{
  Wire.beginTransmission(74);
  Wire.write(byte(0x21)); 
  Wire.write(byte(0x09));    
  Wire.write(byte(0x40));
  Wire.endTransmission(); 
}

but it did not work as intended, since the brightness of the LED that was connected did not change. When I checked for the data via requestFrom() and available(), it seemed like no data was written on the chip at all. So, I wonder what did I do wrong in converting the command to Arduino code.

Did you run the i2c_sniffer IDE example?
How did you connect A0?

Here the datasheet for the device.

You may have to re-read a few times in order to figure out the command and how to interpret the data. Most I2C need an Slave address / Device address. and this device have registers. So you have to point them out in order to extract data. Work like the DS1307. Same principle.
The device address is : B01001000 to B01001111. Page 24 of the datasheet. The next page is the register addresses.

Wire.endTransmission() does actually return a value to indicate its success or otherwise.

From that linked manpage:

image

Many years ago I had trouble writing to an I2C EEPROM and it was suggested that I add a delay(5); after the Wire.endTransmission();. It worked for me then, but as I say that was EEPROM; may not be an issue with a pot though. But worth a try?

My suggestion is to try to read the ID's first.

  1. Run a I2C Scanner sketch, show us the output of that.
  2. Try to read the VERSION_ID (0x00) and DEVICE_ID (0x14). They are part of the 16-bit status register. Don't forget the "repeated start" which is mentioned in the datasheet. Show us your sketch.

There is a better option: Buy a digital potentiometer which has already a working and tested library and buy it from a good seller: https://www.adafruit.com/product/4286

I ran the I2C scanner, and it said the address is 0x50 (so I was wrong about it being 74). A0 is connected to the ground.

I2C scanner showed this.


and when I read the VERSION_ID and DEVICE_ID with

  const uint8_t DeviceAddress = 0x50;
  Wire.beginTransmission(DeviceAddress);
  Wire.write(byte(0x00));
  Wire.endTransmission();
  Wire.beginTransmission(DeviceAddress);
  Wire.requestFrom(0x00, 7);
  byte m = Wire.read();
  Serial.print(m);
  Wire.endTransmission();
  delay(5000);

I got 255 for both of them. I also tried to read 0x21 (which is the register I am trying to change), and it also said 255 somehow.

When I use I2C scanner, I got 0x50 as the address. However, this is different from any of the device addresses I see on the datasheet. Do you know why this is happening?

Hmm.
With AO tied to AGND, The three address bits will be 0. Therefore, your address is, per page 24, 01001000, or 48 hex; not sure why you're getting 50, that would imply, possibly, bit3 is appearing as bit4, but it may have something to do with that funky tying of the A0 pin to various active signals.

Based on that, I'd try talking to address 48h. If that works, we may have a case where the device address isn't getting properly read back in the i2c scan code, which would be troubling - but if so, it's more likely an i2c timing violation by your e-pot, rather than an Arduino code issue.
C

Please show a full sketch.
The Wire.requestFrom() should not have Wire.beginTransmission() and Wire.endTransmission() around it. Try requesting 2 bytes instead of 7. Read two bytes instead of one. Implement the repeated start.
afbeelding

This is what I have.

#include <Wire.h>

void setup()
{
  Wire.begin(); 
  Serial.begin(9600);
}
void loop()
{
  const uint8_t DeviceAddress = 0x50; //the address from the I2C scanner
  Wire.requestFrom(0x00, 2);
  byte m = Wire.read();
  Serial.print(m);
  delay(5000);
}

How would I implement repeated start? Sorry, I'm new to I2C and digipots in general.

I tried connecting A0 to a different ground, as well as changing the address to 48h. What is a way for checking i2c timing violation?

Not easy for a beginner(probably need an o'scope, and an authoritative document about I2C, and the source code of the I2C scanner, and other stuff), so I'd advise trying to read something from the device at a range of addresses. E.g.
for(int address = 0x40;address<0x80; address++)
{
read register
print result
}
(obviously, the above is not actually code, you'll have to write something similar though).
and see what you get. It might be garbage, or you might get a consistent value for all but one address; if that happens, then try reading other registers at that address. Sorry, it's brute force.
However, I'm not sure we're chasing the right ghost, so let us know what happens. If you can identify an address at which the device responds, you'll be a lot further ahead.
C

Umm
you declare an address, but it doesn't look like you used it...

The first line should be deleted. DeviceAddress goes into requestFrom(). Why do you request 7 bytes but read only 1?

Receiving 255 (0xFF) means that no slave responded.

Please study the IDE examples for correctly requesting data from a slave.

I have read some other examples involving I2C, and here is what I have now:

#include <Wire.h>

void setup() {
  Wire.begin(); 
  Serial.begin(9600);
}

byte val = 148;
void loop() {
  Wire.beginTransmission(80);//slave address
  Wire.write(byte(0x21));//register address
  Wire.write(val);//write data to register
  Wire.endTransmission(false);//repeated start
  //read sequence
  Wire.requestFrom(80,2);
  byte value1 = Wire.read();
  byte value2 = Wire.read();
  Serial.println(value1);
  Serial.println(value2);
  delay(5000);
}

I have implemented repeated start, and verified that the slave address is 0x50, or 80. Also, since the register is 16-digit binary data, I requested 2 bytes, but both bytes still return 255.

endTransmission() returns a value indicating success / failure of the operation. What did you get when you printed this return value?

Get an inexpensive Logic Analyzer to actually see what's happening on the I2C lines:

I got 0, which I heard means success.