Adafruit SHT31-D и Raspberry Pi2 — невозможно прочитать данные с датчика

надеюсь, один из вас может мне помочь!

Я пытаюсь использовать Adafruit SHT31-D (устройство i2c) с моим Pi2. Я ухожу из этот лист данных направлять мои усилия по кодированию. Я использую Wiring Pi (wiringpi.com) для облегчения вещей.

Я могу успешно открыть соединение с устройством, и отправка команд, кажется, работает нормально, но я не могу прочитать данные обратно! Вот маленькая мини-библиотека, которую я собрал. Я надеюсь, что один из вас может иметь некоторый опыт в подобных вещах и сможет помочь мне понять, где я ошибся.

Чтобы исключить любые возможные проблемы с сенсорным оборудованием, я проверил его на Arduino UNO, и он работает без проблем.

Вот мой код C ++:

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;
}

1

Решение

SHT31 использует 16-битное чтение и запись, а не 2-битные записи, лучше использовать 16-битную запись wiringpi. wiringPiI2CWriteReg16 (). То же самое относится и к чтению.

Ниже приведена очень ранняя копия того, что я сделал, чтобы прочитать sht31-d на PI. У него нет зависимостей, кроме i2c-dev. Включение / отключение нагревателя не работает, но softreset, clearstatus, getserial & получить темп / влажность все в порядке.

/*
* Referances
* https://www.kernel.org/doc/Documentation/i2c/dev-interface
* https://github.com/adafruit/Adafruit_SHT31
* https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/Humidity_and_Temperature_Sensors/Sensirion_Humidity_and_Temperature_Sensors_SHT3x_Datasheet_digital.pdf
*
* This depends on i2c dev lib
* sudo apt-get install libi2c-dev
*
* Below is also a good one to have, but be careful i2cdump from the below cause the sht31 interface to become unstable for me
* and requires a hard-reset to recover correctly.
* sudo apt-get install i2c-tools
*
* on PI make sure below 2 commands are in /boot/config.txt
* dtparam=i2c_arm=on
* dtparam=i2c1_baudrate=10000
* I know we are slowing down the baurate from optimal, but it seems to be the most stable setting in my testing.
* add another 0 to the above baudrate for max setting, ie dtparam=i2c1_baudrate=100000
*/

#include <linux/i2c-dev.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <elf.h>
#include <unistd.h>

#define SHT31_INTERFACE_ADDR       1
#define SHT31_DEFAULT_ADDR         0x44
#define SHT31_READ_SERIALNO        0x3780
#define SHT31_MEAS_HIGHREP_STRETCH 0x2C06 // Doesn't work on PI
#define SHT31_MEAS_MEDREP_STRETCH  0x2C0D // Seems to work on PI but shouldn't
#define SHT31_MEAS_LOWREP_STRETCH  0x2C10 // Seems to work on PI but shouldn't
#define SHT31_MEAS_HIGHREP         0x2400 // Doesn't work on PI
#define SHT31_MEAS_MEDREP          0x240B
#define SHT31_MEAS_LOWREP          0x2416
#define SHT31_READSTATUS           0xF32D
#define SHT31_CLEARSTATUS          0x3041
#define SHT31_SOFTRESET            0x30A2
#define SHT31_HEATER_ENABLE        0x306D
#define SHT31_HEATER_DISABLE       0x3066

#define CHECK_BIT(var,pos) (((var)>>(pos)) & 1)

/*
* delay:
*  Wait for some number of milliseconds
*********************************************************************************
*/

void delay (unsigned int howLong)
{
struct timespec sleeper, dummy ;

sleeper.tv_sec  = (time_t)(howLong / 1000) ;
sleeper.tv_nsec = (long)(howLong % 1000) * 1000000 ;

nanosleep (&sleeper, &dummy) ;
}

/*
*
* CRC-8 formula from page 14 of SHT spec pdf
*
* Test data 0xBE, 0xEF should yield 0x92
*
* Initialization data 0xFF
* Polynomial 0x31 (x8 + x5 +x4 +1)
* Final XOR 0x00
*/
uint8_t crc8(const uint8_t *data, int len)
{
const uint8_t POLYNOMIAL = 0x31;
uint8_t crc = 0xFF;
int j;
int i;

for (j = len; j; --j ) {
crc ^= *data++;

for ( i = 8; i; --i ) {
crc = ( crc & 0x80 )
? (crc << 1) ^ POLYNOMIAL
: (crc << 1);
}
}
return crc;
}/*
*
* buffer should return with data read, size defined by readsize
*********************************************************************************
*/

int writeandread(int fd, uint16_t sndword, uint8_t *buffer, int readsize)
{
int rtn;
uint8_t snd[3];
// Split the 16bit word into two 8 bits that are flipped.
snd[0]=(sndword >> 8) & 0xff;
snd[1]=sndword & 0xff;

rtn = write(fd, snd, 2);
if ( rtn != 2 ) {
return 1;
}

if (readsize > 0) {
delay(10);
rtn = read(fd, buffer, readsize);
if ( rtn < readsize) {
return 2;
}
}

return 0;
}

void printserialnum(int file)
{
uint8_t buf[10];
int rtn;

rtn = writeandread(file, SHT31_READ_SERIALNO, buf, 6);
if (rtn != 0)
printf("ERROR:- Get serial i2c %s failed\n",(rtn==1?"write":"read"));
else {
if (buf[2] != crc8(buf, 2) || buf[5] != crc8(buf+3, 2))
printf("WARNING:- Get serial CRC check failed, don't trust result\n");

uint32_t serialNo = ((uint32_t)buf[0] << 24)
| ((uint32_t)buf[1] << 16)
| ((uint32_t)buf[3] << 8)
| (uint32_t)buf[4];
printf("Serial# = %d\n",serialNo);
}
}

void printtempandhumidity(int file)
{
uint8_t buf[10];
int rtn;

rtn = writeandread(file, SHT31_MEAS_MEDREP_STRETCH, buf, 6);

if (rtn != 0)
printf("ERROR:- Get temp/humidity i2c %s failed\n",(rtn==1?"write":"read"));
else {
if ( buf[2] != crc8(buf, 2) || buf[5] != crc8(buf+3, 2))
printf("WARNING:- Get temp/humidity CRC check failed, don't trust results\n");

uint16_t ST, SRH;
ST = buf[0];
ST <<= 8;
ST |= buf[1];

SRH = buf[3];
SRH <<= 8;
SRH |= buf[4];

double stemp = ST;
stemp *= 175;
stemp /= 0xffff;
stemp = -45 + stemp;

double stempf = ST;
stempf *= 315;
stempf /= 0xffff;
stempf = -49 + stempf;

printf("Temperature %.2fc - %.2ff\n",stemp,stempf);

double shum = SRH;
shum *= 100;
shum /= 0xFFFF;

printf("Humidity %.2f%%\n",shum);
}
}

void printBitStatus(uint16_t stat)
{
printf("Status\n");
printf("    Checksum status %d\n", CHECK_BIT(stat,0));
printf("    Last command status %d\n", CHECK_BIT(stat,1));
printf("    Reset detected status %d\n", CHECK_BIT(stat,4));
printf("    'T' tracking alert %d\n", CHECK_BIT(stat,10));
printf("    'RH' tracking alert %d\n", CHECK_BIT(stat,11));
printf("    Heater status %d\n", CHECK_BIT(stat,13));
printf("    Alert pending status %d\n", CHECK_BIT(stat,15));
}

void printstatus(int file)
{
uint8_t buf[10];
int rtn;

rtn = writeandread(file, SHT31_READSTATUS, buf, 3);
if (rtn != 0)
printf("ERROR:- readstatus %s failed\n",(rtn==1?"write":"read"));
else {
if ( buf[2] != crc8(buf, 2))
printf("WARNING:- Get status CRC check failed, don't trust results\n");

uint16_t stat = buf[0];
stat <<= 8;
stat |= buf[1];
printBitStatus(stat);
}
}void clearstatus(int file)
{
if( writeandread(file, SHT31_CLEARSTATUS, NULL, 0) != 0)
printf("ERROR:- sht31 clear status failed\n");
else
printf("Clearing status - ok\n");
}

void softreset(int file)
{
if( writeandread(file, SHT31_SOFTRESET, NULL, 0) != 0)
printf("ERROR:- sht31 soft reset failed\n");
else
printf("Soft reset - ok\n");
}

void enableheater(int file)
{
if( writeandread(file, SHT31_HEATER_ENABLE, NULL, 0) != 0)
printf("ERROR:- sht31 heater enable failed\n");
else
printf("Enabiling heater - ok\n");
}

void disableheater(int file)
{
if( writeandread(file, SHT31_HEATER_DISABLE, NULL, 0) != 0)
printf("ERROR:- sht31 heater enable failed\n");
else
printf("Disableing heater - ok\n");
}

int main()
{

int file;
char filename[20];

snprintf(filename, 19, "/dev/i2c-%d", SHT31_INTERFACE_ADDR);
file = open(filename, O_RDWR);
if (file < 0) {
printf("ERROR:- Can't open %s\n",filename);
exit(1);
}

if (ioctl(file, I2C_SLAVE, SHT31_DEFAULT_ADDR) < 0) {
printf("ERROR:- Connecting to sht31 I2C address 0x%02hhx\n", SHT31_DEFAULT_ADDR);
exit(1);
}

softreset(file);
printtempandhumidity(file);
printstatus(file);

close(file);

return 0;
}
2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]