/*********************************************************************************
|
* Copyright: (C) 2018 LingYun IoT System Studio
|
* All rights reserved.
|
*
|
* Filename: sht20.c
|
* Description: This file is temperature and relative humidity sensor SHT20 code
|
*
|
* Version: 1.0.0(2018/10/14)
|
* Author: Guo Wenxue <guowenxue@gmail.com>
|
* ChangeLog: 1, Release initial version on "2018/10/14 12:13:26"
|
*
|
********************************************************************************/
|
|
#include <stdio.h>
|
#include <fcntl.h>
|
#include <unistd.h>
|
#include <sys/ioctl.h>
|
#include <linux/types.h>
|
#include <sys/stat.h>
|
#include <linux/i2c.h>
|
#include <linux/i2c-dev.h>
|
#include <stdio.h>
|
#include <stdlib.h>
|
#include <sys/types.h>
|
#include <string.h>
|
#include <stdint.h>
|
#include <time.h>
|
#include <errno.h>
|
#include <string.h>
|
|
#include "sht20.h"
|
#include "logger.h"
|
#include "util_proc.h"
|
|
static int s_sht2x_fd = -1;
|
|
void sht2x_term(void)
|
{
|
close(s_sht2x_fd);
|
s_sht2x_fd = -1;
|
log_warn("Terminate SHT2X\n");
|
}
|
|
static inline void dump_buf(const char *prompt, uint8_t *buf, int size)
|
{
|
int i;
|
|
if( !buf )
|
{
|
return ;
|
}
|
|
if( prompt )
|
{
|
printf("%s ", prompt);
|
}
|
|
for(i=0; i<size; i++)
|
{
|
printf("%02x ", buf[i]);
|
}
|
printf("\n");
|
|
return ;
|
}
|
|
#ifdef I2C_API_RDWR /* Use I2C userspace driver read/write API */
|
|
int sht2x_softreset(int fd)
|
{
|
uint8_t buf[4];
|
|
if( fd<0 )
|
{
|
log_error("Invalid input arguments\n");
|
return -1;
|
}
|
|
/* software reset SHT2x */
|
memset(buf, 0, sizeof(buf));
|
|
buf[0] = SOFTRESET;
|
write(fd, buf, 1);
|
|
msleep(50);
|
|
return 0;
|
}
|
|
int sht2x_init(void)
|
{
|
|
if( (s_sht2x_fd=open("/dev/i2c-1", O_RDWR)) < 0)
|
{
|
log_error("i2c device open failed: %s\n", strerror(errno));
|
return -1;
|
}
|
|
/* set I2C mode and SHT2x slave address */
|
ioctl(s_sht2x_fd, I2C_TENBIT, 0); /* Not 10-bit but 7-bit mode */
|
ioctl(s_sht2x_fd, I2C_SLAVE, 0x40); /* set SHT2x slava address 0x40*/
|
|
if( sht2x_softreset(s_sht2x_fd) < 0 )
|
{
|
log_error("SHT2x softreset failure\n");
|
sht2x_term();
|
return -2;
|
}
|
|
log_debug("SHT2X initialise ok, s_sht2x_fd=%d\n", s_sht2x_fd);
|
return s_sht2x_fd;
|
}
|
|
int sht2x_get_temp_humidity(float *temp, float *rh)
|
{
|
uint8_t buf[4];
|
|
if( !temp || !rh )
|
{
|
log_error("Invalid input arguments\n");
|
return -1;
|
}
|
|
if( s_sht2x_fd < 0 )
|
{
|
if( sht2x_init() < 0)
|
{
|
log_error("SHT2x initialise failure\n");
|
return -2;
|
}
|
}
|
|
/* send trigger temperature measure command and read the data */
|
memset(buf, 0, sizeof(buf));
|
buf[0]=TRIGGER_TEMPERATURE_NO_HOLD;
|
write(s_sht2x_fd, buf, 1);
|
|
msleep(85); /* datasheet: typ=66, max=85 */
|
|
memset(buf, 0, sizeof(buf));
|
read(s_sht2x_fd, buf, 3);
|
//dump_buf("Temperature sample data: ", buf, 3);
|
*temp = 175.72 * (((((int) buf[0]) << 8) + buf[1]) / 65536.0) - 46.85;
|
|
/* send trigger humidity measure command and read the data */
|
memset(buf, 0, sizeof(buf));
|
buf[0] = TRIGGER_HUMIDITY_NO_HOLD;
|
write(s_sht2x_fd, buf, 1);
|
|
msleep(29); /* datasheet: typ=22, max=29 */
|
memset(buf, 0, sizeof(buf));
|
|
read(s_sht2x_fd, buf, 3);
|
//dump_buf("Relative humidity sample data: ", buf, 3);
|
*rh = 125 * (((((int) buf[0]) << 8) + buf[1]) / 65536.0) - 6;
|
|
return 0;
|
}
|
|
int sht2x_get_serialnumber(uint8_t *serialnumber, int size)
|
{
|
uint8_t buf[4];
|
|
if( !serialnumber || size!=8 )
|
{
|
log_error("Invalid input arguments\n");
|
return -1;
|
}
|
|
if( s_sht2x_fd < 0 )
|
{
|
if( sht2x_init() < 0)
|
{
|
log_error("SHT2x initialise failure\n");
|
return -2;
|
}
|
}
|
|
/* Read SerialNumber from Location 1 */
|
memset(buf, 0, sizeof(buf));
|
buf[0] = 0xfa; /* command for readout on-chip memory */
|
buf[1] = 0x0f; /* on-chip memory address */
|
write(s_sht2x_fd, buf, 2);
|
|
memset(buf, 0, sizeof(buf));
|
read(s_sht2x_fd, buf, 4);
|
|
serialnumber[5]=buf[0]; /* Read SNB_3 */
|
serialnumber[4]=buf[1]; /* Read SNB_2 */
|
serialnumber[3]=buf[2]; /* Read SNB_1 */
|
serialnumber[2]=buf[3]; /* Read SNB_0 */
|
|
/* Read SerialNumber from Location 2 */
|
memset(buf, 0, sizeof(buf) );
|
buf[0]=0xfc; /* command for readout on-chip memory */
|
buf[1]=0xc9; /* on-chip memory address */
|
write(s_sht2x_fd, buf, 2);
|
|
memset(buf, 0, sizeof(buf) );
|
read(s_sht2x_fd, buf, 4);
|
|
serialnumber[1]=buf[0]; /* Read SNC_1 */
|
serialnumber[0]=buf[1]; /* Read SNC_0 */
|
serialnumber[7]=buf[2]; /* Read SNA_1 */
|
serialnumber[6]=buf[3]; /* Read SNA_0 */
|
|
//dump_buf("SHT2x Serial number: ", serialnumber, 8);
|
|
return 0;
|
}
|
|
#elif (defined I2C_API_IOCTL) /* Use I2C userspace driver read/write API */
|
|
int sht2x_softreset(int fd)
|
{
|
struct i2c_msg msg;
|
struct i2c_rdwr_ioctl_data sht2x_data;
|
uint8_t buf[2];
|
|
if( fd<0 )
|
{
|
log_error("Invalid input arguments\n");
|
return -1;
|
}
|
|
msg.addr= 0x40;
|
msg.flags=0; //write
|
msg.len= 1;
|
msg.buf= buf;
|
msg.buf[0]=SOFTRESET;
|
|
sht2x_data.nmsgs= 1;
|
sht2x_data.msgs= &msg;
|
|
if( ioctl(fd, I2C_RDWR, &sht2x_data) < 0 )
|
{
|
log_error("sht2x I2C_RDWR ioctl failure: %s\n", strerror(errno));
|
sht2x_term();
|
return -2;
|
}
|
|
msleep(50);
|
|
return 0;
|
}
|
|
|
int sht2x_init(void)
|
{
|
if( (s_sht2x_fd=open("/dev/i2c-1", O_RDWR)) < 0)
|
{
|
log_error("i2c device open failed: %s\n", strerror(errno));
|
return -1;
|
}
|
|
if( sht2x_softreset(s_sht2x_fd) < 0 )
|
{
|
log_error("SHT2x softreset failure\n");
|
sht2x_term();
|
return -2;
|
}
|
|
log_debug("SHT2X initialise ok, s_sht2x_fd=%d\n", s_sht2x_fd);
|
return 0;
|
}
|
|
int sht2x_get_serialnumber(uint8_t *serialnumber, int size)
|
{
|
struct i2c_msg msgs[2];
|
struct i2c_rdwr_ioctl_data sht2x_data;
|
uint8_t sbuf[2];
|
uint8_t rbuf[4];
|
|
if( !serialnumber || size!=8 )
|
{
|
log_error("Invalid input arguments\n");
|
return -1;
|
}
|
|
if( s_sht2x_fd < 0 )
|
{
|
if( sht2x_init() < 0)
|
{
|
log_error("SHT2x initialise failure\n");
|
return -2;
|
}
|
}
|
|
/*+------------------------------------------+
|
*| Read SerialNumber from Location 1 |
|
*+------------------------------------------+*/
|
|
msgs[0].addr= 0x40;
|
msgs[0].flags=0; //write
|
msgs[0].len= 2;
|
msgs[0].buf= sbuf;
|
msgs[0].buf[0]=0xfa; /* command for readout on-chip memory */
|
msgs[0].buf[1]=0x0f; /* on-chip memory address */
|
|
msgs[1].addr=0x40;
|
msgs[1].flags=I2C_M_RD; //write
|
msgs[1].len= 4;
|
msgs[1].buf= rbuf;
|
|
sht2x_data.nmsgs= 2;
|
sht2x_data.msgs= msgs;
|
|
if( ioctl(s_sht2x_fd, I2C_RDWR, &sht2x_data) < 0 )
|
{
|
log_error("sht2x I2C_RDWR ioctl failure: %s\n", strerror(errno));
|
sht2x_term();
|
return -2;
|
}
|
|
serialnumber[5]=rbuf[0]; /* Read SNB_3 */
|
serialnumber[4]=rbuf[1]; /* Read SNB_2 */
|
serialnumber[3]=rbuf[2]; /* Read SNB_1 */
|
serialnumber[2]=rbuf[3]; /* Read SNB_0 */
|
|
|
/*+------------------------------------------+
|
*| Read SerialNumber from Location 2 |
|
*+------------------------------------------+*/
|
|
msgs[0].addr= 0x40;
|
msgs[0].flags=0; //write
|
msgs[0].len= 2;
|
msgs[0].buf= sbuf;
|
msgs[0].buf[0]=0xfc; /* command for readout on-chip memory */
|
msgs[0].buf[1]=0xc9; /* on-chip memory address */
|
|
msgs[1].addr=0x40;
|
msgs[1].flags=I2C_M_RD; //write
|
msgs[1].len= 4;
|
msgs[1].buf= rbuf;
|
|
sht2x_data.nmsgs= 2;
|
sht2x_data.msgs= msgs;
|
|
if( ioctl(s_sht2x_fd, I2C_RDWR, &sht2x_data) < 0 )
|
{
|
log_error("sht2x I2C_RDWR ioctl failure: %s\n", strerror(errno));
|
sht2x_term();
|
return -2;
|
}
|
|
serialnumber[1]=rbuf[0]; /* Read SNC_1 */
|
serialnumber[0]=rbuf[1]; /* Read SNC_0 */
|
serialnumber[7]=rbuf[2]; /* Read SNA_1 */
|
serialnumber[6]=rbuf[3]; /* Read SNA_0 */
|
|
//dump_buf("SHT2x Serial number: ", serialnumber, 8);
|
|
return 0;
|
}
|
|
|
int sht2x_get_temp_humidity(float *temp, float *rh)
|
{
|
struct i2c_msg msg;
|
struct i2c_rdwr_ioctl_data sht2x_data;
|
uint8_t buf[4];
|
|
if( !temp || !rh )
|
{
|
log_error("Invalid input arguments\n");
|
return -1;
|
}
|
|
if( s_sht2x_fd < 0 )
|
{
|
if( sht2x_init() < 0)
|
{
|
log_error("SHT2x initialise failure\n");
|
return -2;
|
}
|
}
|
|
/*+------------------------------------------+
|
*| measure and get temperature |
|
*+------------------------------------------+*/
|
|
msg.addr= 0x40;
|
msg.flags=0; //write
|
msg.len= 1;
|
msg.buf= buf;
|
msg.buf[0]=TRIGGER_TEMPERATURE_NO_HOLD; /* trigger temperature without hold I2C bus */
|
|
sht2x_data.nmsgs= 1;
|
sht2x_data.msgs= &msg;
|
|
if( ioctl(s_sht2x_fd, I2C_RDWR, &sht2x_data) < 0 )
|
{
|
log_error("sht2x I2C_RDWR ioctl failure: %s\n", strerror(errno));
|
sht2x_term();
|
return -2;
|
}
|
|
msleep(85);
|
|
memset(buf, 0, sizeof(buf));
|
msg.addr=0x40;
|
msg.flags=I2C_M_RD; //write
|
msg.len= 3;
|
msg.buf= buf;
|
|
sht2x_data.nmsgs= 1;
|
sht2x_data.msgs= &msg;
|
|
if( ioctl(s_sht2x_fd, I2C_RDWR, &sht2x_data) < 0 )
|
{
|
log_error("sht2x I2C_RDWR ioctl failure: %s\n", strerror(errno));
|
sht2x_term();
|
return -2;
|
}
|
|
//dump_buf("Temperature sample data: ", buf, 3);
|
*temp = 175.72 * (((((int) buf[0]) << 8) + buf[1]) / 65536.0) - 46.85;
|
|
|
/*+------------------------------------------+
|
*| measure and get relative humidity |
|
*+------------------------------------------+*/
|
|
msg.addr= 0x40;
|
msg.flags=0; //write
|
msg.len= 1;
|
msg.buf= buf;
|
msg.buf[0]=TRIGGER_HUMIDITY_NO_HOLD; /* trigger humidity without hold I2C bus */
|
|
sht2x_data.nmsgs= 1;
|
sht2x_data.msgs= &msg;
|
|
if( ioctl(s_sht2x_fd, I2C_RDWR, &sht2x_data) < 0 )
|
{
|
log_error("sht2x I2C_RDWR ioctl failure: %s\n", strerror(errno));
|
sht2x_term();
|
return -2;
|
}
|
|
msleep(29);
|
|
memset(buf, 0, sizeof(buf));
|
msg.addr=0x40;
|
msg.flags=I2C_M_RD; //write
|
msg.len= 3;
|
msg.buf= buf;
|
|
sht2x_data.nmsgs= 1;
|
sht2x_data.msgs= &msg;
|
|
if( ioctl(s_sht2x_fd, I2C_RDWR, &sht2x_data) < 0 )
|
{
|
log_error("sht2x I2C_RDWR ioctl failure: %s\n", strerror(errno));
|
sht2x_term();
|
return -2;
|
}
|
|
//dump_buf("Relative humidity sample data: ", buf, 3);
|
*rh = 125 * (((((int) buf[0]) << 8) + buf[1]) / 65536.0) - 6;
|
|
return 0;
|
}
|
|
#endif
|