gpt4 book ai didi

c++ - Adafruit SHT31-D 和 Raspberry Pi2 -- 无法从传感器读取数据

转载 作者:行者123 更新时间:2023-11-30 03:44:27 25 4
gpt4 key购买 nike

希望你们中的任何一个能帮助我!

我正在尝试使用 Adafruit SHT31-D (一个 i2c 设备)板和我的 Pi2。我要离开 this datasheet指导我的编码工作。我正在使用 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;
}

最佳答案

SHT31 使用 16bit 读写,而不是使用 2 个 8bit 写入,您最好使用 wiringpi 的 16bit 写入。 wiringPiI2CWriteReg16().同样的事情也适用于阅读。

下面是我在 PI 上阅读 sht31-d 所做的早期拷贝。除了 i2c-dev,它没有依赖项。加热器启用/禁用不起作用,但软复位、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;
}

关于c++ - Adafruit SHT31-D 和 Raspberry Pi2 -- 无法从传感器读取数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35461155/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com