This real world example shows how to trigger a RIGOL DS1054Z oscilloscope at a specific point in an i2c communication, and then check signal + data.

The DS1054Z comes with i2c functionality. In the past they were options you bought separately. Since 2019 they are standard.

 

 

Test Setup and Hooking up the Oscilloscope

 

Any i2c setup will do. Just pick whatever design you have that uses the protocol.

I used a very simple design: An Arduino UNO talking to an RGB + ir sensor from RoHM: BH174BH174.

The oscilloscope's channel 1 is connected to the i2c SCI signal. Channel 2 to SDA.

 

You can follow along just as well if you use a LaunchPad, a Pi or a BB with an i2c design. Or a consumer product that you want to probe.

 

Scenario: Trigger on a well defined communication spot

 

I'm assuming here that you want to inspect a particular event in the i2c communication.

In an i2c device, a lot of data can fly around. From and to the controller. Communication with several ICs.

In the example here, I want to check i2c signals specifically when the RoHM sensor in the design is queried for light levels.

 

 

The code that generates that communication is:

 

byte BH1749NUC::get_rawval(unsigned char *data)
{
  byte rc;

  rc = read(BH1749NUC_RED_DATA_LSB, data, GET_BYTE_RED_TO_GREEN2);
  if (rc != 0) {
    Serial.println(F("Can't get BH1749NUC RGB, IR and GREEN2 value"));
  }

  return (rc);
}

 

Our end goal is to trigger exactly when this line of the code is executed to retrieve the data:

  rc = read(BH1749NUC_RED_DATA_LSB, data, GET_BYTE_RED_TO_GREEN2);

 

In i2c lingo, this is the sequence we want to trigger on[write to 0x39] [0x50] .

 

We can use the ICs i2c address to single out the communication with the RoHM IC, and not have any other IC's data captured by accident.

#define BH1749NUC_DEVICE_ADDRESS_39             (0x39)    // 7bit Addrss

 

That's a good begin, let's set the trigger for that.

Press the Trigger Menu button, then select Type I2C.

 

 

In the When menu, select Address. Set AddrBits to 7  - our RoHM sensor has a 7 bit address.

Then dial the Address to the ICs address, 0x39.

 

You may have to play with the Trigger Level a bit, and when that's set right, the scope will stop whenever the address 0X39 is used in i2c communication.

This isn't perfect yet. We get any communication. Not always the part where we want to read the light levels (as seen in the capture above).

 

An additional attribute we can use is the particular command used to get that data.

#define BH1749NUC_RED_DATA_LSB                  (0x50)

 

We can use a different When setting to trigger on an address + data sequence: A & D

Let's define the trigger that way. We already set the address to 0x39.

The data mask becomes visual when selecting the A&D option. You have to set it bit per bit.

The data value we want to filter on is 0x50, 0b01010000.

On the scope, where they use H and L instead of 1 and 0, you set the mask as LHLHLLLL.

 

Once that's done, the scope will trigger when the address is 0x39 and the data starts with 0x50.

In many cases that's exactly what you want. It 'll work most of the time.

But there may be unwanted occurrences: when the IC returns a data value of 0x50 for RED (as seen in the capture above)

In that case, you also get a sequence of 0x39 and 0x50.

 

Here is where we can use a third refinement to only trigger when 0x50 is used in a write sequence. Not in a read sequence.

 

This is a very sturdy setup. The oscilloscope will only trigger when it asks the IC to return RGB + ir levels. All other data sequences are ignored.

 

Decode and Inspect the Data

 

Now that we're able to capture the exact point of interest, let's review the payload.

The i2c decoder is available via the Math button.

 

A little trick to allow you to zoom out from the current capture window is to use the maximum amount of sample memory available.

This is again a standard option when you purchased the scope in 2019 or later.

Press Acquire, then Mem Depth -> 12M.

 

Standard, the math signal shows the data. You can select the formatting. I used HEX. Ascii may also be useful, if text data is exchanged.

There's also a table view, available in the same Math -> Decode menu.

This one gives a better view of the full packet, without the need to enlarge the time base and scroll through the signal.

 

Here is another example, using the same hardware but different firmware.

It's Adafruit's library and sample code for the same IC. It uses higher communication rate.

In this example you see the value of big memory. We also can show a part of the communication before the trigger point.

Spot that the trigger is again exactly at the data point we've set.

 

Another interesting aspect of the captured data is the integrity of the analogue signal.

We're working with an oscilloscope, and that's what it's specialised in - the actual physical signal on the i2c lines.

If you have intermittent communication issues, this view may help you to detect if poor signal integrity is at play.