Bridging OneWire and i2c communication using the DS28E17

Hello,

I'm in the process of trying to use the Maxim DS28E17 chip to communicate with the Sensirion SHT31-D temperature and humidity sensor. I found someone else having trouble getting the DS28E17 to work on this forum and followed their example code but still do not get a reading from the sensor. The code I've written is shown below:

#include <Arduino.h>
#include <OneWire.h>

#define i2c_Address 0x44        // Address of the i2c temp and humidity sensor
#define Write_Data  0x4B        // Command to write data with stop 
#define measurement 0x24000


OneWire oneWire(3);

uint8_t address[8];
uint8_t packet[7];
uint8_t data[6];
float temp, humidity;


void setup() {
  Serial.begin(9600);
  packet[0] = Write_Data;
  packet[1] = i2c_Address;
  packet[2] = 0x02;
  packet[3] = (measurement >> 8);
  packet[4] = (measurement & 0xFF);

  uint16_t CRC16 = oneWire.crc16(&packet[0], 5);
  CRC16 = ~CRC16;
  packet[6] = CRC16 >> 8;                   // Most significant byte of 16 bit CRC
  packet[5] = CRC16 & 0xFF;                 // Least significant byte of 16 bit CRC
}

void loop() {
  oneWire.reset();
  oneWire.select(address);
  oneWire.write_bytes(packet, sizeof(packet), 1);

  while (oneWire.read_bit() == true)        // Wait for not busy
  {
    delay(1);
  }
  for (uint8_t i = 0; i < 6; i++) {
    data[i] = oneWire.read();
  }

// below this is just calculations to turn the received data into meaningful readings
  uint16_t ST, SRH;
  ST = data[0];
  ST <<= 8;
  ST |= data[1];
  SRH = data[3];
  SRH <<= 8;
  SRH |= data[4];

  double stemp = ST;
  stemp *= 175;
  stemp /= 0xffff;
  stemp = -45 + stemp;
  temp = stemp;
  double shum = SRH;
  shum *= 100;
  shum /= 0xFFFF;
  humidity = shum;

  Serial.println(temp);
  Serial.println(humidity);
  delay(5000);
}

The code stops in the while loop waiting for a response from the DS28E17 but does not exit.

Please provide a schemata or drawing of the wiring (the problem might be on the hardware side).

You didn't define the OneWire address for the DS28E17, so the command does not reach it.

After you sent the Write command you read 6 bytes but the command returns just 2 bytes according to the datasheet (status and write-status). To get the sensor reading you have to send a Read command to the DS28E17 (0x87).

Thanks for the help,

I must have deleted the call to grab the address when I was cleaning up my code, I have added the address in and also changed the command to read the two status' an grab the 6 bytes of data.

I am getting a status = 0, and a Write status=0; Which according to the data sheet means that all communication has gone well.

I am still having an issue with reading the data back however. The temperature is read back correctly but the humidity has a constant value of 100. I've ruled out a problem with the SHT31-D sensor by connecting it directly to the arduino i2c communication pins directly and both temp and humididty is read properly.

Below is my revised code and output which works for everything except the humididy:

#include <Arduino.h>
#include <OneWire.h>

OneWire oneWire(3);
uint8_t address[8];
uint8_t packet[8];
uint8_t data[6];
float temp, humidity;

#define Write_Data_Stop         0x4B
#define Write_Data_No_Stop      0x5A
#define Write_Data_Only         0x69
#define Write_Data_Only_Stop    0x78
#define Read_Data_Stop          0x87
#define Write_Read_Data_Stop    0x2D
#define Write_Config            0xD2
#define Read_Config             0xE1
#define Enable_Sleep            0x1E
#define Read_Device_Rev         0xC3
#define i2c_Address             0x88        // Address of the i2c temp and humidity sensor 
#define measurement             0x2400      // Command to take a Measurement

void setup() {
  Serial.begin(9600);
  oneWire.search(address);

  packet[0] = Write_Read_Data_Stop;         // DS28E17 Command
  packet[1] = i2c_Address;                  // 7 bit i2c Address
  packet[2] = 0x02;                         // number of bytes to be written (2)
  packet[3] = (measurement >> 8);           // i2c device command MSB
  packet[4] = (measurement & 0xFF);         //  "     "      "    LSB
  packet[5] = 0x06;                         // Number of bytes to be read
  uint16_t CRC16 = oneWire.crc16(&packet[0], 6);
  CRC16 = ~CRC16;
  packet[7] = CRC16 >> 8;                   // Most significant byte of 16 bit CRC
  packet[6] = CRC16 & 0xFF;                 // Least significant byte of 16 bit CRC
}

void loop() {
  oneWire.reset();
  oneWire.select(address);
  oneWire.write_bytes(packet, sizeof(packet), 1);

  while (oneWire.read_bit() == true)        // Wait for not busy
  {
    delay(1);
  }
  Serial.print("Status =");
  Serial.println(oneWire.read(),BIN);
  Serial.print("Write Status =");
  Serial.println(oneWire.read(),BIN);
  
  for (uint8_t i = 0; i < 6; i++) {
    data[i] = oneWire.read();
  }

  uint16_t ST, SRH;
  ST = data[0];
  ST <<= 8;
  ST |= data[1];
  
  SRH = data[3];
  SRH <<= 8;
  SRH |= data[4];

  double stemp = ST;
  stemp *= 175;
  stemp /= 0xffff;
  stemp = -45 + stemp;
  temp = stemp;
  
  double shum = SRH;
  shum *= 100;
  shum /= 0xFFFF;
  humidity = shum;

  Serial.print("Raw data back: ");
  for (uint8_t i = 0; i < 6; i++) {
    Serial.print(data[i], BIN);
    Serial.print("  ");
  }
  Serial.println();
  Serial.print("temp = ");
  Serial.println(temp);
  Serial.print("humidity = ");
  Serial.println(humidity);
  delay(30000);
}

Which outputs something like this:
Status =0
Write Status =0
Raw data back: 1100100 101001 1011001 11111111 11111111 11111111
temp = 23.47
humidity = 100.00

My guess is that the measurement wasn't made when the result was requested. You send the DS28E17 on command that writes the measurement command to the SHT31-D and immediately after that read the result values while probably the values aren't ready yet (especially not with the highest reproducibility you requested, the datasheet says this needs 15ms). There are several solutions to this.

Probably the easiest will be to us clock stretching as the sensor explicitly has this possibility and the DS28E17 is also capable of it. If this is activated (measurement command will be 0x2C06) the sensor will defer the read command until the results are available.

Another solution will be to send the measurement command with the first DS28E17 packet, wait some time and send then the packet to read the results.