3
\$\begingroup\$

I'm trying to interface the OMRON D6F-PH0025AD2, BME280, and a 2004 Display (with an I2C driver) with an ESP32.

Without the D6F on the I2C lines, the others peripherals work perfectly.

Following the datasheet and the application note/manual, I've soldered up the sensor wires to the ESP32 directly (to keep the distance short) for debugging. I used 2 kΩ pullups (these are the ones I had at hand) to 3.3 V.

What I'm observing using CRO is that (only) the SCL is always pulled low at around 0.9 V. The sensor is not getting hot nor is it drawing too much current.

I've added a few println statements and set the clock to 100 kHz to the demo code given by OMRON. What I'm seeing is wire.available() is always zero in the i2c_read_reg8 although I should be getting two bytes.

#include <Wire.h>

/* defines */
#define D6F_ADDR 0x6C  // D6F-PH I2C client address at 7bit expression


uint8_t conv16_u8_h(int16_t a) {
  return (uint8_t)(a >> 8);
}

uint8_t conv16_u8_l(int16_t a) {
  return (uint8_t)(a & 0xFF);
}

uint16_t conv8us_u16_be(uint8_t* buf) {
  return (uint16_t)(((uint32_t)buf[0] << 8) | (uint32_t)buf[1]);
}


/** <!-- i2c_write_reg16 {{{1 --> I2C write bytes with a 16bit register.
*/
bool i2c_write_reg16(uint8_t slave_addr, uint16_t register_addr,
                     uint8_t *write_buff, uint8_t len) {
  Wire.setClock(100000);
  Wire.beginTransmission(slave_addr);

  Wire.write(conv16_u8_h(register_addr));
  Wire.write(conv16_u8_l(register_addr));

  if (len != 0) {
    for (uint8_t i = 0; i < len; i++) {
      Wire.write(write_buff[i]);
    }
  }
  Wire.endTransmission();
  return false;
}


/** <!-- i2c_read_reg8 {{{1 --> I2C read bytes with a 8bit register.
*/
bool i2c_read_reg8(uint8_t slave_addr, uint8_t register_addr,
                   uint8_t *read_buff, uint8_t len) {
  Serial.println("step i2c read reg8 started");
  Wire.setClock(100000);
  Wire.beginTransmission(slave_addr);
  Wire.write(register_addr);
  Wire.endTransmission();
  Serial.println("now requesting data");
  Wire.requestFrom(slave_addr, len);

  while (Wire.available() != len) {
    Serial.println("Wire.avail != len");
    Serial.println(Wire.available(), DEC);
    // return true;
  }

  for (uint16_t i = 0; i < len; i++) {
    read_buff[i] = Wire.read();
  }
  return false;
}

/** <!-- setup {{{1 -->
   1. initialize a Serial port for output.
   2. initialize an I2C peripheral.
   3. setup sensor settings.
*/
void setup() {
  Serial.begin(115200);
  Serial.println("peripherals: I2C");
  Wire.begin();  // i2c master

  Serial.println("sensor: Differential pressure Sensor");
  delay(32);

  // 1. Initialize sensor (0Bh, 00h)
  i2c_write_reg16(D6F_ADDR, 0x0B00, NULL, 0);
  Serial.println("step 1 done");
}

/** <!-- loop - Differential pressure sensor {{{1 -->
   1. read and convert sensor.
   2. output results, format is: [Pa]
*/
void loop() {
  delay(900);
  Serial.println("Entered loop");
  // 2. Trigger getting data (00h, D0h, 40h, 18h, 06h)
  uint8_t send0[] = {0x40, 0x18, 0x06};
  i2c_write_reg16(D6F_ADDR, 0x00D0, send0, 3);

  delay(50);  // wait 50ms
  Serial.println("step 2 done");

  // 3. Read data (00h, D0h, 51h, 2Ch) (07h)
  uint8_t send1[] = {0x51, 0x2C};
  i2c_write_reg16(D6F_ADDR, 0x00D0, send1, 2);
  uint8_t rbuf[2];
  if (i2c_read_reg8(D6F_ADDR, 0x07, rbuf, 2)) {  // read from [07h]
    return;
  }
  uint16_t rd_flow = conv8us_u16_be(rbuf);
  float flow_rate;

  Serial.println("step 3 done");
  // calculation for 0-250[Pa] range
  flow_rate = ((float)rd_flow - 1024.0) * 250 / 60000.0;

  Serial.print(flow_rate, 2);  // print converted flow rate
  Serial.println(" [Pa]");
}

I assumed that the sensor was faulty, so I replaced it with a brand new sensor. It has no effect. Both sensors are brand new and I bought them just a few months back from Mouser.

Update

Thanks to everyone helping me till now and sorry for the delay.

To isolate the problem and transferred the sensor and microcontroller to a new protoboard. I soldered the connector directly to the PCB added and added new 2 kΩ pullups. I've replaced the MCU from the ESP32 with an ESP8266 (Wemos D1 Mini). Rest everything remains the same. The wire length is reduced to 100 mm (~4") I've two soldered two pin headers on SDA, SCL, and GND for easy measurement.

For while I got the same waveform, CRO Wave form -1 on both SDA and SCL even they were not short. Today I cleaned everthing again, and I'm getting the following waveforms.

SDA: SDA waveform

SCL: SCL waveform

Both: Both waveforms together

The SDA waveform seems to me like normal. The SCL seems off. Although, earlier it was it didn't have spikes. It was continuously at 0.9 V.

A Picture of my new wiring setup. Setup

A top-down picture to understand the placement of components. enter image description here

noch ein Update

I was following the pinout given in the manual. Apparently, different header versions have different pinouts. Thanks to @DamienD correct pointing it out!

\$\endgroup\$
25
  • 1
    \$\begingroup\$ Are you sure you haven't just swapped the clock & data lines? \$\endgroup\$
    – jayben
    Mar 7, 2022 at 13:44
  • 1
    \$\begingroup\$ The links you provided are for the Omron D6F sensor, not the D6H part you specified, so maybe you have the wrong part, or the wrong data. \$\endgroup\$
    – jayben
    Mar 7, 2022 at 19:00
  • 1
    \$\begingroup\$ @RohanRege - Hi, I've added some analysis as a (partial-only) answer, to help you. As already commented, oscilloscope traces will be helpful. A schematic diagram would help for confirmation. I also want to see photos of your hardware, please, including evidence that the wiring (especially power supply to the sensor) is correct. Thanks. \$\endgroup\$
    – SamGibson
    Mar 8, 2022 at 3:52
  • 1
    \$\begingroup\$ @Rohan - Hi, Just a brief comment from me (which I will delete after you've had a chance to read it). Thanks very much for coming back with updates & giving the conclusion (some people don't do that). I see that my concern over the sensor's wiring turned out to be correct! Although I was busy in the last few days, I'm glad that you got help from another site member who could pinpoint the details of that wiring issue. (Soldering direct to pins intended for a connector is another concern.) Anyway, good luck with your project! \$\endgroup\$
    – SamGibson
    Mar 14, 2022 at 14:34
  • 1
    \$\begingroup\$ @SamGibson Thank you, I understand how frustrating it is when the person you're trying to help randomly ghosts. Also, working on the wiring now and going to make a better PCB for the next iteration. \$\endgroup\$
    – Rohan
    Mar 15, 2022 at 9:41

3 Answers 3

3
\$\begingroup\$

Looking again at the datasheet, I found that the order of pins is, quite surprisingly, different between the header version and the connector version. So, your sensor is connected the wrong way, and quite possibly damaged.

enter image description here enter image description here

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Yes, thank you! This is it. I was following the pinout from the manual. I never assumed different port configs would have different pinouts. \$\endgroup\$
    – Rohan
    Mar 14, 2022 at 10:29
  • 2
    \$\begingroup\$ It is working now! \$\endgroup\$
    – Rohan
    Mar 14, 2022 at 10:35
4
\$\begingroup\$

There are currently some unanswered clarifications below the question, but I can add some value and since anything "that gets the asker going in the right direction" is an answer, even just a partial one, here is some analysis:

Summary: While it was a sensible thing to consider, the described behaviour is not I2C clock stretching.

  • The stated sensor behaviour (sensor pulling SCL low immediately at power-on) is not an example of I2C clock stretching (as described in section 3.1.9 on page 12 of the current 7.0 revision of the I2C specification - link here goes to whatever the current version is).

    Clock stretching is only done by an I2C target (previously known as a "slave") after it has been addressed by the I2C controller (previously known as a "master"). Otherwise that target behaviour would affect all other devices on the I2C bus, especially if a target pulled SCL low when it was not the target currently being addressed.

  • We can never assume that datasheets / user manuals etc. are accurate. However these are the documents that we have. The user manual linked in the question has this diagram in section 6.2 (with my added circles):

    Fig. 6 Electrical connection method of D6F-PH by Omrom

    The two arrows on the SDA signal, marked with red circles, indicate that the signal can be driven by both the controller (master) and target (slave). That is normal for all I2C targets, since they at least drive SDA to ACK when addressed, even if they don't return any other data (although typically sensors would also, of course, send data to the I2C controller after being addressed as well).

    However notice how the SCL signal has only one arrow, marked with a blue circle, pointing at the sensor. That indicates that the SCL signal is only an input for the sensor - not an output from the sensor i.e. it's not driven by the sensor. If that diagram in the sensor user manual is correct, it means that the sensor does not drive the SCL signal i.e. it does not perform clock stretching.

So we have 2 pieces of evidence that the sensor's behaviour is not explained as clock stretching.


Summary: The problem is not with your code (program), as your code cannot send any I2C commands with the described sensor behaviour.

  • Very simply, with the SCL signal stuck low as soon as power to the sensor is applied, it is impossible for an I2C controller to send any commends to that I2C target (or any other I2C target on that I2C bus). Therefore none of the I2C commands in that code are having any effect.

    That sensor does require specific initialisation (and specific timing between commands) as explained in the user manual. However, none of that can happen with SCL stuck low.


Finally, the stated SCL voltage at power-on is strange at 0.9 V. That is barely a logic low assuming 3.3 V supply, and assuming typical CMOS logic level thresholds of 0.3 x Vdd and 0.7 x Vdd (0.9 V = 0.27 x Vdd).

If the only load on SCL is a 2 kΩ pull-up resistor, then the current is only 1.65 mA (assuming supply voltage of 3.3 V). I would expect any normal I2C device to be able to pull SCL much closer to 0 V for such a low current. This again indicates that the situation is not as simple as the sensor is pulling SCL low in a normal way.


Overall: The stated behaviour of pulling SCL low at power-on is so catastrophic for normal operation (as explained in the question, it prevents any communication on that I2C bus) that it cannot be intentional. The cause (which occurs with both sensors of that type) must be due to some other cause which has not yet been described. You can stop spending further time wondering if this is intentional I2C clock stretching, for the reasons above.

Despite the stated belief in the comments that the wiring to the sensor is correct, that needs to be re-checked - not whether SDA and SCL are swapped, but whether is power applied to the correct pins etc.

\$\endgroup\$
0
\$\begingroup\$

Besides the wiring issue (see my more recent answer), I found the following statement on page 41 of the datasheet:

Use the applicable connectors. Direct soldering to the connection terminals will cause product failure (except for the D6F-PH).

I think the datasheet is inaccurate and the exception does NOT apply to your sensor. I think it applies only to the variant with PCB headers that stick out and not to your variant with a recessed connector.

There are also many ominous noises in the datasheet about applying more than 100 grams-force to the pins and ESD precautions.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.