I2C fails to work with level shifter and sensor

I have an ov7670 module and it communicates using a very similar protocol to i2c.
I've been trying to communicate with it using this code (obviously wire.begin and serial.begin are in setup)...

Wire.beginTransmission(0x21);
//delay(3000);
Wire.requestFrom(0x21,1); readvalue=Wire.read();
delay(300);
Serial.write(readvalue);
Wire.endTransmission();

And a bi-directional level shifter (the sensor uses 3v3 i2c whereas the arduino i2c is 5v).
I have connected the camera correctly, and given it a clock signal, however it still fails to respond to any communication. I have found that I can communicate between boards through the level shifter, so I know the level shifter is set up correctly.

Does anyone know what might be the problem? Do I need to disable the internal pull-up resistors, or will this make no difference if I'm using a level shifter?

have you checked if the device is visible on the I2C bus?

e.g. with this I2C scanner - MultiSpeed I2C Scanner - 50,100,200,400 KHz. - Libraries - Arduino Forum -

did you connect GND's ?

If the level shifter is connected as it should (high side to 5V, low side to 3.3V) then it should work.

Your code is not okay. The requestFrom() should not be encapsulated with begin() and end(). Only Wire.write() should be encapsulated with those.

Run the i2c_scanner and then this:

  Wire.beginTransmission(0x21);
  Serial.write( ... <something> ...);       // write the address of a register ?
  Wire.endTransmission();

  Wire.requestFrom(0x21, 1);   // request one byte
  readvalue=Wire.read();     // read the byte

ChromeBit:
I have an ov7670 module and it communicates using a very similar protocol to i2c.
I've been trying to communicate with it using this code (obviously wire.begin and serial.begin are in setup)...

Wire.beginTransmission(0x21);
//delay(3000);
Wire.requestFrom(0x21,1); readvalue=Wire.read();
delay(300);
Serial.write(readvalue);
Wire.endTransmission();

And a bi-directional level shifter (the sensor uses 3v3 i2c whereas the arduino i2c is 5v).
I have connected the camera correctly, and given it a clock signal, however it still fails to respond to any communication. I have found that I can communicate between boards through the level shifter, so I know the level shifter is set up correctly.

Does anyone know what might be the problem? Do I need to disable the internal pull-up resistors, or will this make no difference if I'm using a level shifter?

You are mixing a Transmit and a receive call to WIRE.

  Wire.beginTransmission(0x21);
  //delay(3000);
  Wire.requestFrom(0x21,1);   readvalue=Wire.read();
  delay(300);
  Serial.write(readvalue);
  Wire.endTransmission();

the following is a Wire transmit and a WIRE receive.

// WIRE.write example

WIRE.beginTransmission(0x21); // start a WRITE transaction to I2C device with Slave ID of 0x21
WIRE.write((uint8_t) 25);  // add a single byte value (25 decimal) to the WIRE TX_buffer.
WIRE.endTransmission(true); // Actually send the TX_buffer to the Slave. Send an I2C STOP condition,
  // releasing the I2C bus to allow other I2C Master's to use the bus, 

WIRE.beginTransmission(0x21); // start a WRITE transaction to I2C device with Slave ID of 0x21
WIRE.write((uint8_t) 25);  // add a single byte value (25 decimal) to the WIRE TX_buffer.
WIRE.endTransmission(false); // Actually send the TX_buffer to the Slave. DO NOT Send an I2C STOP condition,
  // RETAIN control of the I2C bus, The next I2C operation will start with a REPEATED START condition. 
  // Some I2C device need a two part command to read a specific register.
  //   First you Write a register address, then you use a RepeatStart to Read the Register contents. 

// Read Example

WIRE.requestFrom(0x21,1); // Request a single byte from slave 0x21
uint8_t readValue =WIRE.read();//

WIRE.beginTransmission(), WIRE.endTransmission() are only used to transmit to a slave device

WIRE.requestFrom() is only used to receive from a slave device.

Chuck.


Check out my Kickstarter Project Memory Panes an expansion RAM Shield for Mega2560's. It adds 1MB of RAM for those projects where 8KB is not enough.

Thank you for your replies, I managed to get the device to appear a couple of times on the i2c scanner with the correct address, but most of the time it wasn't detected. Does anyone know what might cause this?
I couldn't get the code to work, but I think this is probably because of the sensor not always being found.

The i2c_scanner should be able to run for hours without a miss.

Do you have a drawing or schematic ? Can you make a photo of it ? Are you sure there are no bad breadboard contacts ?

I believe you will still need pull up resistors, since an I2C network does not provide them by default. Your level shifter may be having trouble reading open collectors without a pullup resistor. Just a thought.