Debugging i2c issues associated with multiple addresses

I am playing around with a 12-bit DAC IC (Texas Instruments DAC121C085) on a Particle Photon and have been running into some weird i2c issues with the addressing. One of the perks of this IC is you can set 8 different addresses; my project will require 5 DAC lines so this is great!

I have wired it up with 10k pull-ups on SDA and SCL and am running a simple i2c scanner script to detect all i2c slaves on the system. The function below is run once every 5 seconds:

void scanI2C() {
  Serial.println("\tScanning for i2c devices...");

  byte i, e;
  int n_devices = 0;

  if (!Wire.isEnabled()) {
    Wire.begin();
  }

  for (i=1; i< 127; i++) {
    Wire.beginTransmission(i);
    e = Wire.endTransmission();

    if (e == 0) {
      Serial.print("\tI2C device found at 0x");

      if (i < 16) {
        Serial.print("0");
      }

      Serial.println(i, HEX);

      n_devices++;
    }
  }

  if (n_devices == 0) {
    Serial.println("\tFound 0 i2c devices.");
  }
}

When I first run the script, it finds two addresses (0x09, 0x48) where only 0x09 should be present. After the first iteration of the script, it goes dark and no longer see’s any devices. I have a Saleae Logic Analyzer, but it hasn’t really showed anything at all…

In addition, when no devices are found, the scan takes a little longer than 5 seconds which seems really odd. When devices are found, it’s very fast (< 500 ms).

How could I go about debugging this? I don’t think I know enough about the i2c protocol to really know where to start.

@hagandh, as per the datasheet, 0x48 is the broadcast address for the DAC:

In addition to the selectable slave address, there is also a broadcast address (1001000) for all DAC121C081’s and DAC121C085’s on the 2-wire bus. When the bus is addressed by the broadcast address, all the DAC121C081’s and DAC121C085’s will respond and update synchronously

I suspect that “poking” the broadcast address puts the device into a “wait for byte” state:

8.3.6 Simultaneous Reset
The broadcast address allows the I2C master to write a single word to multiple DACs simultaneously. Provided that all of the DACs exist on a single I2C bus, every DAC updates when the broadcast address is used to address the bus. This feature allows the master to reset all of the DACs on a shared I2C bus to a specific digital code. For instance, if the master writes a power-down code to the bus with the broadcast address, all of the DACs powers down simultaneously.

So, avoid scanning at address 0x48 and it will probably work fine! :wink:

2 Likes

You were absolutely right! Not sure how I missed that, but thanks! It’s unfortunate that 0x48 is the broadcast address since that’s one of TI’s 4 addresses for their ADS1115 ADC! Oh well!

2 Likes

One last question since I think it may be specific to the Photon/Electron: I tried skipping over the address using a loop like this:

for (i=1; i<127; i++){
    if (i != 48){
        Wire.beginTransmission(i);
        e = Wire.endTransmission();

        if (e == 0) {
            Serial.print("I2C device found at 0x");
            if (i < 16){
                Serial.print("0");
            }
            Serial.println(i, HEX);
        }
    }
}

This approach failed to eliminate the issues with 0x48 for some reason, though if I re-write the loop in a way that essentially runs two consecutive loops (the first between 1-47 and the second between 49-127), it works as expected. Any insight into why this approach would still ping 0x48 and put the DAC’s into this “wait for byte” state?

@hagandh, I believe you are confusingHEX 0x48 with DECIMAL 48. Simply change the 48 to 0x48 (decimal 72) in your if statement. I’m not sure why two loops worked however! :wink:

Ahh I see what you’re saying. I declared the iterative variable (i) as a byte. Would that not do the trick? I tried skipping over 72 (and adding a print statement to make sure it was never executing), and it says that 0x48/72 never executes, but the result is the same: after one run, 0x09 is no longer seen implying that the DAC has still entered the “wait for byte” mode.

This is strange. Even if I scan just between 1-71 and then 80-127, it still effectively pings 0x48 :confused:

@hagandh, I am stumped. I would add a Serial.println(e, HEX); line after the e = Wire.endTransmission(); line to see what is returned.

It looks like a mixture of 1’s (data too long to fit in transmit buffer) and 3’s (received NACK on transmit of data). I may just hook up a logic analyzer and see if I can peek.

1 Like

So I must be doing something wrong (or there is something I really don’t understand about Wire/i2c). Here is a screenshot of the logic analyzer. It appears I am writing every other address and 0x48 is definitely being hit…

Hi @hagandh

i2c uses a 7-bit address with the LSB on the wire used to indicate read or write. Some tools and chip datasheet pretend that is an 8-bit address with two address used for each register (one for reading and one for writing).

Looking at the datasheet for your DAC, it clearly gives 7-bit addresses which is also what the Particle i2c firmware expects. All good there.

Your scope picture labels that as 0x48 but the bit pattern is '01001000` which is 0x48 hex interpreted as 8-bits but is really a read to 7-bit address 36. or 0x24.

Hope this helps.

1 Like

Ahh thanks! I switched the settings on the Saleae and it looks good now. At this point, the data in the logic analyzer output looks great the first iteration (doesn’t ever ping 0x48), but still fails the second time around. Any thoughts on why this would happen?

Before:

Actually, after several iterations, the Saleae Logic Analyzer doesn’t pick up anything on the SCL/SDA lines at all!

I saw your other post about this DAC and library–can we mark this issue solved now?

Hey @bko. Yes, it can probably be marked solved as the original issue is solved. I’m still a bit confused as to why the DAC goes into “wait for byte” mode when the broadcast address isn’t hit, but that is probably something completely different.

@hagandh, the “wait for byte” is my interpretation of what happens when you hit address 0x48 and may not necessary be correct. What confuses me is that you said that everything worked when you wrote two loops, avoid decimal address 48 which is incorrect!