New I2C library available

If anyone is interested, there is a really, really nice I2C library available. IMO, its nicer than wire because its easier to use and, of great concern to me, it can be used inside an interrupt service routine. It works both with Arduino 1.0 and earlier.

Its here:

I will try this ASAP. We are having strange problems that might have something to do with the I2C communication between three arduinos in our robot project. There's so much crazy code mixed, that we can't be sure, but all signs are agains the I2C trafic.

Cheers,
Kari

Performance figures look good, no I2C need at the moment but I had quick look at the code: (some remarks to improve)

Several places:

returnStatus = 0;
returnStatus = start();

The 1st assignment (=0) is overridden by the 2nd assignment, so remove the 1st.

void I2C::setSpeed(uint8_t _fast) why not use bool _fast?

the speed parameter should be part of the begin() which could be rewritten to:

void I2C::begin(uint8_t _fast)
{
  activate(true);
  cbi(TWSR, TWPS0);
  cbi(TWSR, TWPS1);
  setSpeed(_fast);
  // enable twi module and acks
  TWCR = _BV(TWEN) | _BV(TWEA); 
}

The scan() function is very usefull but it uses the Serial port internally. If I wanted to use the Serial for other purposes I have a conflict.

You can solve this by a slightly different scanfunction, that find the first in a range of addresses.

(Not tested, but you should get the idea)

int I2C::scan(uint8_t startAddr, uint8_t stopAddr)
{
  for(int addr = startAddr; addr <= stopAddr; addr++)
  {
    returnStatus = start();
    if (!returnStatus) 
    {
      returnStatus = sendAddress(SLA_W(addr));  
      if (returnStatus == 1) return -1;
      else 
      {
        stop();
        return addr;
      }
    }
  }
  return -1;
}

The firstcall to deviceId = scan(0, 127) returns the first deviceId found or -1 if error. By filling in the found deviceId you can scan further e.g. in a simple myScan function.

void myScan()
{
  int deviceId = 0;
  while ( (deviceId = I2C.scan(deviceId, 127)) > -1)
  {
    Serial.println(deviceId);  //or SoftSerial.print() or LCD.print() whatever I like 
  }
}

This allows me to print all device ID's s on the bus without a call to serial in the lib itself. Furthermore you can control the range of the scan process by making it parameterized.

Finally I think there can a merge of parts of the read/write functions as they have quite similar parts. [too late for me to dive into that one now]

my 3 cents ,

robtillaart:
This allows me to print all device ID's s on the bus without a call to serial in the lib itself. Furthermore you can control the range of the scan process by making it parameterized.

But if you really must to write out messages in a library, require the caller to supply a Stream* parameter. That way, the caller can decide where the messages go.

Iain

Several places:

returnStatus = 0;
returnStatus = start();

The 1st assignment (=0) is overridden by the 2nd assignment, so remove the 1st.

This is one of those palm to forehead moments...I honestly don't know why I did that. I'll fix that up in the next rev.

void I2C::setSpeed(uint8_t _fast) why not use bool _fast?

Initially I was going to have a range of speeds available but ultimately didn't include that option so I just left it as a byte.

The scan function was written to be mostly a diagnostic function and not really meant to be incorporated in the main program. Actually I slipped it into the library because I got tired of opening a separate sketch everytime I wanted to scan the bus. The scan function is actually part of a larger sketch I'm working on to diagnose I2C bus problems. I didn't want to parametrize the function because I wanted to gear it towards the person that doesn't know too much about I2C making it as easy as possible (I'm a firm believer in the KISS principle).

Thanks for the feedback...keep it coming. Always looking for improvement ideas. :slight_smile:

This is one of those palm to forehead moments.

Everyone has those moments :slight_smile:

The scan function was written to be mostly a diagnostic function and not really meant to be incorporated in the main program. Actually I slipped it into the library because I got tired of opening a separate sketch everytime I wanted to scan the bus.

understand, you could have a second Arduino with that scan/diag sketch connected to the I2C bus under scrutiny too?

robtillaart:

This is one of those palm to forehead moments.

Everyone has those moments :slight_smile:

That that it matters, the compiler optimized that away. But yeah, sometimes I look at my code and say "What the F$&# was I smoking when I wrote that!"

This is one of those palm to forehead moments.

or you meant palm in the head => Palm is a very nice Belgian beer :slight_smile: - http://palm.be/ -