hopefully one of you out there can help me!
I am trying to use the Adafruit SHT31-D (an i2c device) board with my Pi2. I am going off of this datasheet to guide my coding efforts. I am using Wiring Pi (wiringpi.com) to facilitate things.
I am able to successfully open a connection to the device, and sending commands seems to work fine, but I am unable to read data back! Here is the little mini library I have put together. I am hoping that one of you might have some experience with this sort of thing and be able to help me see where I've gone wrong.
To rule out any possible issues with the sensor hardware, I have tested it with my Arduino UNO and it works without issues.
Here is my C++ code:
SHT3x.h
#pragma once
/* Sensor Commands */
#define DEFAULT_SHT_ADDR 0x44
#define MEAS_HREP_STRETCH 0x2C06
#define MEAS_MREP_STRETCH 0x2C0D
#define MEAS_LREP_STRETCH 0x2C10
#define MEAS_HREP 0x2400
#define MEAS_MREP 0x240B
#define MEAS_LREP 0x2416
#include <cstdint>
class SHT3x {
public:
SHT3x(const uint8_t& i2cAddr);
float readHumidity(const uint16_t& command) const;
float readTempC(const uint16_t& command) const;
float readTempF(const uint16_t& command) const;
private:
int8_t _fd;
uint8_t _header;
uint32_t getMeasurement(const uint16_t& command) const;
void sendCommand(const uint16_t& command) const;
uint32_t receiveData(void) const;
};
SHT3x.cpp
#include <stdexcept>
#include <wiringPi.h>
#include <wiringPiI2C.h>
#include "SHT3x.h"
SHT3x::SHT3x(const uint8_t& i2cAddr) {
_fd = wiringPiI2CSetup(i2cAddr);
_header = i2cAddr << 1;
if (_fd < 0) {
throw std::runtime_error("Unable to connect");
}
}
float SHT3x::readHumidity(const uint16_t& command) const {
uint32_t raw_data = getMeasurement(command);
if (!raw_data) {
throw std::runtime_error("Bad Reading.");
}
uint16_t raw_humidity = raw_data & 0xFFFF;
float humidity = 100.0 * ((float) raw_humidity / (float) 0xFFFF);
return humidity;
}
float SHT3x::readTempC(const uint16_t& command) const {
uint32_t raw_data = getMeasurement(command);
if (!raw_data) {
throw std::runtime_error("Bad Reading.");
}
uint16_t raw_temp = raw_data >> 16;
float tempC = -45.0 + (175.0 * ((float) raw_temp / (float) 0xFFFF));
return tempC;
}
float SHT3x::readTempF(const uint16_t& command) const {
uint32_t raw_data = getMeasurement(command);
if (!raw_data) {
throw std::runtime_error("Bad Reading.");
}
uint16_t raw_temp = raw_data >> 16;
float tempF = -49.0 + (315.0 * ((float) raw_temp / (float) 0xFFFF));
return tempF;
}
uint32_t SHT3x::getMeasurement(const uint16_t& command) const {
try {
sendCommand(command);
} catch (std::runtime_error& e) {
throw;
}
return receiveData();
}
void SHT3x::sendCommand(const uint16_t& command) const {
// break command into bytes
uint8_t MSB = command >> 8;
uint8_t LSB = command & 0xFF;
// send header
int8_t ack = wiringPiI2CWrite(_fd, _header);
// send command
ack &= wiringPiI2CWrite(_fd, MSB);
ack &= wiringPiI2CWrite(_fd, LSB);
// handle errors
if (ack) {
throw std::runtime_error("Sending command failed.");
}
}
uint32_t SHT3x::receiveData(void) const {
uint32_t data;
// send header
uint8_t read_header = _header | 0x01;
int8_t ack = wiringPiI2CWrite(_fd, read_header);
// handle errors
if (ack) throw std::runtime_error("Unable to read data.");
// read data
data = wiringPiI2CRead(_fd);
for (size_t i = 0; i < 4; i++) {
printf("Data: %d\n", data);
data <<= 8;
if (i != 1) {
data |= wiringPiI2CRead(_fd);
} else {
wiringPiI2CRead(_fd); // skip checksum
}
}
wiringPiI2CRead(_fd); // second checksum
return data;
}
The SHT31 uses 16bit read and write, rather than using 2 8bit writes you might be better off using wiringpi's 16bit write. wiringPiI2CWriteReg16(). Same thing applies to the read.
Below is a very early copy of what I've done to read the sht31-d on a PI. It has no dependencies except i2c-dev. Heater enable/disable is not working, but softreset, clearstatus, getserial & get temp/humid are all fine.