I am facing a little problem with the Sensiron SHT11 humidity & temperature sensor. Hoping for some advices and suggestions.
I've search through the forum in mikroElektronika whether mikroC or mikroBasic, etc and of course on google also. And I've found that there are something in common in their codes that is similar to the original sensiron application notes which written by Keil.
I now trying to use Keil's codes by making a little modification to suit my hardware and conditions. However, the values I get from the sensor seem to be wrong.
I am using PIC 16F877A~4MHz, data pin =PortB.5, sck pin =PortC.3.
The values from my sensor:
Temperature~ 613.0699
Humidity ~1e-1
Any approaches or suggestions are welcome.
The following are my codes:
Code: Select all
//Filename : SHT11_testing.c
//Compiled by: Mikro C v8.0.0.0
//PIC 16F877A~4MHz
/*********************************************/
typedef union
{ unsigned int i;
float f;
} value;
//------------------------------------------------------------------------------
// modul-var
//------------------------------------------------------------------------------
//enum {TEMP,HUMI};
#include "initlcd.c"
#define TEMP 0
#define HUMI 1
#define PORT_COND TRISB.F5 //data port condition: input/output
#define DATA PORTB.F5 //SHT11 DATA pin
#define SCK PORTC.F3 //STH11 SCK pin
#define noACK 0
#define ACK 1
//adr command r/w
#define STATUS_REG_W 0x06 //000 0011 0
#define STATUS_REG_R 0x07 //000 0011 1
#define MEASURE_TEMP 0x03 //000 0001 1
#define MEASURE_HUMI 0x05 //000 0010 1
#define RESET 0x1e //000 1111 0
#define MEMORY_ADDRESS 0xA0
//------------------------------------------------------------------------------
char s_write_byte(unsigned char value)
//------------------------------------------------------------------------------
// writes a byte on the Sensibus and checks the acknowledge
{
unsigned char i,error=0;
PORT_COND = 0; //SHT11 WRITE
for (i=0x80;i>0;i/=2) //shift bit for masking
{ if (i & value) DATA=1; //masking value with i , write to SENSI-BUS
else DATA=0;
SCK=1; //clk for SENSI-BUS
Delay_us(5); //pulswith approx. 5 us
SCK=0;
}
DATA=1; //release DATA-line
PORT_COND = 1; //SHT11 READ
Delay_us(1);
SCK=1; //clk #9 for ack
error=DATA; //check ack (DATA will be pulled down by SHT11)
SCK=0;
return error; //error=1 in case of no acknowledge
}
//----------------------------------------------------------------------------------
char s_read_byte(unsigned char ack)
//----------------------------------------------------------------------------------
// reads a byte form the Sensibus and gives an acknowledge in case of "ack=1"
{
unsigned char i,val=0;
PORT_COND = 1; //SHT11 READ
DATA=1; //release DATA-line
for (i=0x80;i>0;i/=2) //shift bit for masking
{ SCK=1; //clk for SENSI-BUS
if (DATA) val=(val | i); //read bit
SCK=0;
}
DATA=!ack; //in case of "ack==1" pull down DATA-Line
SCK=1; //clk #9 for ack
Delay_us(5); //pulswith approx. 5 us
SCK=0;
DATA=1; //release DATA-line
return val;
}
//----------------------------------------------------------------------------------
void s_transstart(void)
//----------------------------------------------------------------------------------
// generates a transmission start
// _____ ________
// DATA: |_______|
// ___ ___
// SCK : ___| |___| |______
{
PORT_COND = 0; //SHT11 WRITE
DATA=1; SCK=0; //Initial state
Delay_us(2);
SCK=1;
Delay_us(2);
DATA=0;
Delay_us(2);
SCK=0;
Delay_us(5);
SCK=1;
Delay_us(2);
DATA=1;
Delay_us(2);
SCK=0;
}
//----------------------------------------------------------------------------------
void s_connectionreset(void)
//----------------------------------------------------------------------------------
// communication reset: DATA-line=1 and at least 9 SCK cycles followed by transstart
// _____________________________________________________ ________
// DATA: |_______|
// _ _ _ _ _ _ _ _ _ ___ ___
// SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______| |___| |______
{
unsigned char i;
PORT_COND = 0; //SHT11 WRITE
DATA=1; SCK=0; //Initial state
for(i=0;i<9;i++) //9 SCK cycles
{ SCK=1;
SCK=0;
}
s_transstart(); //transmission start
}
//----------------------------------------------------------------------------------
char s_softreset(void)
//----------------------------------------------------------------------------------
// resets the sensor by a softreset
{
unsigned char error=0;
s_connectionreset(); //reset communication
error+=s_write_byte(RESET); //send RESET-command to sensor
return error; //error=1 in case of no response form the sensor
}
//----------------------------------------------------------------------------------
char s_read_statusreg(unsigned char *p_value, unsigned char *p_checksum)
//----------------------------------------------------------------------------------
// reads the status register with checksum (8-bit)
{
unsigned char error=0;
s_transstart(); //transmission start
error=s_write_byte(STATUS_REG_R); //send command to sensor
*p_value=s_read_byte(ACK); //read status register (8-bit)
*p_checksum=s_read_byte(noACK); //read checksum (8-bit)
return error; //error=1 in case of no response form the sensor
}
//----------------------------------------------------------------------------------
char s_write_statusreg(unsigned char *p_value)
//----------------------------------------------------------------------------------
// writes the status register with checksum (8-bit)
{
unsigned char error=0;
s_transstart(); //transmission start
error+=s_write_byte(STATUS_REG_W);//send command to sensor
error+=s_write_byte(*p_value); //send value of status register
return error; //error>=1 in case of no response form the sensor
}
//----------------------------------------------------------------------------------
char s_measure(unsigned char *p_value, unsigned char *p_checksum, unsigned char mode)
//----------------------------------------------------------------------------------
// makes a measurement (humidity/temperature) with checksum
{
unsigned error=0;
unsigned int i;
s_transstart(); //transmission start
switch(mode)
{ //send command to sensor
case TEMP : error+=s_write_byte(MEASURE_TEMP); break; //temp
case HUMI : error+=s_write_byte(MEASURE_HUMI); break; //humidity
default : break;
}
PORT_COND = 1; //SHT11 READ
for (i=0;i<65535;i++) if(DATA==0) break; //wait until sensor has finished the measurement
if(DATA) error+=1; // or timeout (~2 sec.) is reached
*(p_value) =s_read_byte(ACK); //read the first byte (MSB)
*(p_value+1)=s_read_byte(ACK); //read the second byte (LSB)
*p_checksum =s_read_byte(noACK); //read checksum
return error;
}
/*
//----------------------------------------------------------------------------------
void init_uart()
//----------------------------------------------------------------------------------
// Initializes the UART so the final data can be sent away, e.g. to a PC
//9600 bps @ 11.059 MHz
{ SCON = 0x52;
TMOD = 0x20;
TCON = 0x69;
TH1 = 0xfd;
}
*/
//----------------------------------------------------------------------------------------
void calc_sth11(float *p_humidity ,float *p_temperature)
//----------------------------------------------------------------------------------------
// calculates temperature [C] and humidity [%RH]
// input : humi [Ticks] (12 bit)
// temp [Ticks] (14 bit)
// output: humi [%RH]
// temp [C]
{ const float C1=-4.0; // for 12 Bit
const float C2= 0.0405; // for 12 Bit
const float C3=-0.0000028; // for 12 Bit
const float T1=0.01; // for 14 Bit @ 5V
const float T2=0.00008; // for 14 Bit @ 5V
float rh=*p_humidity; // rh: Humidity [Ticks] 12 Bit
float t=*p_temperature; // t: Temperature [Ticks] 14 Bit
float rh_lin; // rh_lin: Humidity linear
float rh_true; // rh_true: Temperature compensated humidity
float t_C; // t_C : Temperature [C]
t_C=t*0.01-40; //calc. Temperature from ticks to [C]
rh_lin=C3*rh*rh + C2*rh + C1; //calc. Humidity from ticks to [%RH]
rh_true=(t_C-25)*(T1+T2*rh)+rh_lin; //calc. Temperature compensated humidity [%RH]
if(rh_true>100)rh_true=100; //cut if the value is outside of
if(rh_true<0.1)rh_true=0.1; //the physical possible range
*p_temperature=t_C; //return temperature [C]
*p_humidity=rh_true; //return humidity[%RH]
}
//--------------------------------------------------------------------
float calc_dewpoint(float h,float t)
//--------------------------------------------------------------------
// calculates dew point
// input: humidity [%RH], temperature [C]
// output: dew point [C]
{ float k,dew_point ;
k = (log10(h)-2)/0.4343 + (17.62*t)/(243.12+t);
dew_point = 243.12*k/(17.62-k);
return dew_point;
}
/************************************************************/
//LCD display
char* Out_temp()
{
char str[]="Temp:" absolute MEMORY_ADDRESS;
return str;
}
char* Out_humi()
{
char str[]="Humi:" absolute MEMORY_ADDRESS;
return str;
}
//----------------------------------------------------------------------------------
void main()
//----------------------------------------------------------------------------------
// sample program that shows how to use SHT11 functions
// 1. connection reset
// 2. measure humidity [ticks](12 bit) and temperature [ticks](14 bit)
// 3. calculate humidity [%RH] and temperature [C]
// 4. calculate dew point [C]
// 5. print temperature, humidity, dew point
{ value humi_val,temp_val;
float dew_point;
unsigned char error,checksum;
unsigned int i;
char temp[13];
char humi[13];
Initlcd(); //Initialize LCD
s_connectionreset(); //reset
while(1)
{
error=0;
error+=s_measure((unsigned char*) &humi_val.i,&checksum,HUMI);
//measure humidity
error+=s_measure((unsigned char*) &temp_val.i,&checksum,TEMP);
//measure temperature
if(error!=0) s_connectionreset(); //in case of an error: connection reset
else
{
humi_val.f=(float)humi_val.i; //converts integer to float
temp_val.f=(float)temp_val.i; //converts integer to float
calc_sth11(&humi_val.f,&temp_val.f);
//calculate humidity, temperature
dew_point=calc_dewpoint(humi_val.f,temp_val.f);
//calculate dew point
//send final data to LCD
Lcd8_Out(1,1,Out_temp());
Lcd8_Out(2,1,Out_humi());
FloatToStr(temp_val.f, temp);
Lcd8_Out(1,6,temp);
FloatToStr(humi_val.f, humi);
Lcd8_Out(2,6,humi);
}
//----------wait approx. 0.8s to avoid heating up SHTxx----------------
//for (i=0;i<40000;i++); //(be sure that the compiler doesn¡¯t eliminate this line!)
//-----------------------------------------------------------------------------------
Delay_ms(500);
}
}
/************************************************************/
//Filename : initlcd.c
//Compiled by: Mikro C v8.0.0.0
//Description: Initializations of LCD & Port.
/************************************************************/
void Initlcd(void)
{
PORTA = 0x00; //initialize/clear PORTA
PORTB = 0x00; //initialize PORTB
PORTC = 0x00; //initialize PORTC
PORTD = 0x00; //initialize PORTD
TRISA = 0; //PORTA = output.
TRISB = 0x0D; //0x0D=0b00001101->pin(0,2,3)=input.
TRISC = 0x03; //0x03=0b00000011->pin(0,1)=input.
TRISD = 0; //PORTD = output.
TRISE = 0; //PORTE = output.
Lcd8_Config(&PORTC, &PORTD,7,5,6,7,6,5,4,3,2,1,0);
Lcd8_Cmd(LCD_CLEAR); // Clear display
Lcd8_Cmd(LCD_CURSOR_OFF); // Turn cursor off
}
Your feedbacks are welcome.
Thank you.
Here is the original Application Notes:
Click Here to Download