I2C not operating at all, needs help..

Hi all,

I have an Arduino Pro Mini, and a SRF10 ultra sonic range sensor that I'm trying to get running on the I2C. I've connected things according to pinouts (including the A4/A5 instead of 4/5 digital pins), and I have 1.8k resistors as pullups on the SDA and SCL lines.

When I did an analysis of the code (serial printlns to track code progression), I find that the program freezes at Wire.endTransmission(). I'm using the provided sample code for the SRF10.

Could I have connected something wrong? Is there something about the setup that I need to know about?

Thanks for the help in advance.

Cheers, Wingsofpain.

Is it possible that someone changed the I2C address of the sensor? You can try an I2C scanner sketch to determine the addresses of any devices found on the I2C bus.

Hi johnwasser,

Thanks for the reply.

I've tried it, and the I2C scanner found the sensor at the address I expected. From this, I conclude that a) The I2C connection is working as expected b) The address is as expected

Also, I noticed that this code doesn't use the Wire library, but goes straight to the twi library. Is there a reason for this, or does this just allow the programming to quickly run a loop?

There are some operations that require finer control than the Wire library allows. I expect that scanning the bus is one of them.

The fact that the scanner produced results (and the EXPECTED results) means that your device is probably fine and the error is somewhere in the code. Are you using Arduino 1.0? I think there may have been some minor changes to the Wire library. Perhaps the example you are using is based on an older Wire library.

Post (or point to) the example code and maybe someone will be able to suggest how to port it to 1.0.

Hi johnwasser,

For no reason I can think of, the system appears to be working. I made no changes to any code, but I just disconnected and reconnected it. Strange.

In the meantime, this is the code that I’m currently running. If I’m not wrong, comparing the syntax of the Arduino 1.0 and previous versions, this should already be the 1.0 syntax.

// I2C SRF10 or SRF08 Devantech Ultrasonic Ranger Finder 
// by Nicholas Zambetti <http://www.zambetti.com>
// and James Tichenor <http://www.jamestichenor.net> 

// Demonstrates use of the Wire library reading data from the 
// Devantech Utrasonic Rangers SFR08 and SFR10

// Created 29 April 2006

// This example code is in the public domain.


#include <Wire.h>

void setup()
{
  Wire.begin();                // join i2c bus (address optional for master)
  Serial.begin(9600);          // start serial communication at 9600bps
  
  
}

int reading = 0;

void loop()
{
  // step 1: instruct sensor to read echoes
  Wire.beginTransmission(112); // transmit to device #112 (0x70)
                               // the address specified in the datasheet is 224 (0xE0)
                               // but i2c adressing uses the high 7 bits so it's 112
  Wire.write(byte(0x00));      // sets register pointer to the command register (0x00)  
  Wire.write(byte(0x51));      // command sensor to measure in "inches" (0x50) 
                               // use 0x51 for centimeters
                               // use 0x52 for ping microseconds
  Wire.endTransmission();      // stop transmitting

  // step 2: wait for readings to happen
  delay(70);                   // datasheet suggests at least 65 milliseconds

  // step 3: instruct sensor to return a particular echo reading
  Wire.beginTransmission(112); // transmit to device #112
  Wire.write(byte(0x02));      // sets register pointer to echo #1 register (0x02)
  Wire.endTransmission();      // stop transmitting

  // step 4: request reading from sensor
  Wire.requestFrom(112, 2);    // request 2 bytes from slave device #112

  // step 5: receive reading from sensor
  if(2 <= Wire.available())    // if two bytes were received
  {
    reading = Wire.read();  // receive high byte (overwrites previous reading)
    reading = reading << 8;    // shift high byte to be high 8 bits
    reading |= Wire.read(); // receive low byte as lower 8 bits
    Serial.println(reading);   // print the reading
  }

  delay(250);                  // wait a bit since people have to read the output :)
}

It’s literally just the code that was provided with the IDE.

Thanks for the help, johnwasser. It’s nice to know I can talk to someone here :slight_smile:

  Wire.endTransmission();      // stop transmitting

This isn’t strictly correct. Wire.endTransmission does the transmitting, and returns 0 if it succeeded. You might want to check for that. Also, the 1.8K resistors might be slightly low. Try 4.7K if the problem is intermittent.

More details about I2C at:

http://gammon.com.au/i2c

There are some known problems with I2C (particularly the standard libraries) because they wait on interrupts in the requestFrom part. If an interrupt goes astray, you might wait forever. There are some alternate libraries that time-out after a while.

That's true - I read a schematic where someone used 10k resistors instead..

As for Wire.endTransmission(), the code behind it was blocking. I couldn't even get a return value because it was stuck in there.

I believe you. Try this:

http://dsscircuits.com/articles/arduino-i2c-master-library.html

That has an I2C library with time-outs so that shouldn't happen. I haven't tried it but that's what the description says.

[quote author=Nick Gammon link=topic=88011.msg661870#msg661870 date=1327178100] I believe you. Try this:

http://dsscircuits.com/articles/arduino-i2c-master-library.html

That has an I2C library with time-outs so that shouldn't happen. I haven't tried it but that's what the description says. [/quote] ...or if you'd like to help me beta test the latest rev I have here http://dsscircuits.com/images/code/I2C_beta.zip. You can enable an optional timeout period and the beta library does not use interrupts at all and should recover from any lockup condition :cold_sweat: