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).
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.