Trouble using I2C

I’m trying to interface with a dual digital potentiometer using a wixel, in order to implement a remote volume control. If anyone is interested, the digital pot is a Dallas chip, DS1881, which is very nice because it has built in NV ram, so that it can recall its last setting on power up. It also uses an I2C interface. Again if anyone is interested, the data sheet is here…

datasheets.maximintegrated.com/en/ds/DS1881.pdf

But I’m obviously doing something very basically wrong in my use of the I2C library, because I have been scoping the output of the pins on the wixel I’m using for my I2C clock and data (SCL and SDA) lines, and I’m not seeing anything when I make my I2C calls. So naturally the I2C calls are returning timeouts, and I never get an ACK when i do an i2cWriteByte(). So here are some things I’m doing which I’m wondering about.

  1. Because it will make an easier layout, I decided to use P0_0 and P0_1 for my SCL and SDA lines, and so have placed the following in my code, which I think corresponds to the pin definition numbers in GPIO.H…
i2cPinScl = 0;         // defining clock pin P0_0
i2cPinSda = 1;        // defining data pin P0_1
  1. I am assuming that when using the I2C library, I should not initialize these pins in any way. So I’m not setting port 0 to be pulled high or low, nor am I setting the individual pins as digital inputs or outputs.
  2. The Dallas chip’s digital input can be anywhere from 2.5 to 5 V, and I’m feeding it from the wixel 3.3V output. Based on the manufacturer’s data sheet, I’m also pulling the chips SCL and SDA lines high, to that same 3.3V supply , via 4.7K resistors.
  3. The chip data sheet requests I set I2C start condition, send my data bytes, and then send an I2C stop condition. I assume that when I make these calls in my code, I can do them successively, and leave the timing to the library.

Problem solved.

Its always the stupidest thing. In an attempt to avoid soldering on headers to the wixel, I had opted for these solderless headers from sparkfun (sparkfun.com/products/10527). Unfortunately they are way too tight, and so you end up crunching their ends with pliers to make them fit. But then they make lousy contact with the plate through holes! As soon as I touched my scope probe to the actual clock pin (P0_0 for me) on the board i could see the signal. A little twist of the solder-less header and the connection was good, and everything worked fine.

Anyway, the I2C library works as advertised, This is part of an evolving project whose goal is to provide a small panel that can stick on to any electric guitar, so that you can can control multiple effects as well as amplifier volume remotely. If this is of interest to anyone else, keep in touch and I’ll post more as the project develops.

Even though I solved my main issue, I’d still like to know whether it is necessary to have pull up resistors on an I2C slave device, when the Wixel is being used as a master. I note that the default SCK and SDA lines used by the wixel I2C library are P1_0 and P1_1, which can not be configured for pull up / pull down. But I’m using P0_0 and P0_1, which can be configured for a pull up via setPort0PullType(HIGH); But I don’t know if the I2C library would even respect or override this call, or weather the wixel pullup is adequate for I2C communication over a short distance. It does seem to work without it, but that doesn’t really prove anything. I’d still like to know the recommended electrical arrangement.

Hello.

The call to “setPort0PullType(HIGH);” doesn’t actually enable any pull-up resistors. The pull-up resistors are enabled pin-by-pin using the setDigitalInput function.

Also, I just noticed that the Wixel’s I2C library does indeed disable the pull-up resistors on those pins. Here is a snippet from the library:

BIT i2cReadScl(void)
{
    setDigitalInput(i2cPinScl, HIGH_IMPEDANCE);
    return isPinHigh(i2cPinScl);
}

BIT i2cReadSda(void)
{
    setDigitalInput(i2cPinSda, HIGH_IMPEDANCE);
    return isPinHigh(i2cPinSda);
}

I’m not sure if that was intentional; I’ll have to check with someone else. You could easily try changing it by editing the library and changing HIGH_IMPEDANCE to PULLED. The library will be automatically recompiled by the Wixel SDK’s Makefile when you build your app.

–David

OK Thanks Dave. So it looks like the library attempts to make the behavior consistent regardless of what pins are used. Probably for the best. The slave chip I’m driving has open collector logic inputs, which in needs to drive low when it does an I2C ACK. So the 4.7K pullups make sense. Just trying to keep my parts count low. Fortunately it seems I can drive several chips using just one pair of pullups.

By the way, this is a Dallas/Maxim DS1881 chip I’m driving, and the engineer I spoke to at Dallas/Maxim had never heard of the Wixel and was very impressed when I told him all that the little bugger can do, and asked I send him a link. I think I may have found you a new customer! :slight_smile:

The I2C bus is specified with exactly one set of pull-up resistors, and all signalling on the bus is done with (typically) open-drain outputs. This actually allows multiple masters, and arbitrating the bus while trying to access it without corrupting any packets, as long as signalling delay is lower than half clock cycle.

Btw: Depending on how fast you want to run the bus, and how many devices you want on the bus, you may want to use 2.2 kOhm pull-ups to make it rise faster. Also, you can typically interface between 3.3V and 5.0V devices without a voltage level converter by pulling “up” to 3.3V, which the 5.0V device typically still sees as a logic “1.”

It’s really a quite nifty bus! The only problem with it is that it’s kind-of slow compared to SPI.

OK thanks for that clarification! Yeah it does seem like a well designed and simple bus, and its been around so long I’m honestly embarrassed how little I knew about the low level details. Well the digital side of the chip I’m driving has a pretty wide voltage range, so I’ll just pull up to 3.3 for now since I’m feeding it directly from the wixel’s regulator anyway. My plan is to allow for a few more of these chips to be added to the board as an option, so I’ll just but my resistors at the end of the chain. I’m already driving one at 200kHz and I’m not seeing any evidence of errors, and that’s on an ugly white board. But I can always change the resistors or slow down my clock a little if a fully populated board gives me grief.