wangine
 
 
  Joined: 07 Jul 2009 Posts: 98 Location: Curtea de Arges, Romania 
			
			 
			 
			 
			
			
			 
			
			
			
  
		  | 
		
			
				| Read temperature & humidity for SHT25, SHT21 sensor | 
			 
			
				 Posted: Sat Sep 12, 2015 10:12 am     | 
				     | 
			 
			
				
  | 
			 
			
				The code was tested in a real hardware and simulated as well with 4 different sensors SHT21&SHT25 include (Chinese sensors). Code was tested in special chamber around other 3 home made hardware and 2 industrial calibrated devices for comparison. 
 
Code don't have dependence of I2C port, can be use any pins.  Range of OSC where has been tested is 4, 8 and 16MHz. 
 
Single issue of code have a +0.02 error on humidity, example On 40.60 real humidity will show 40.00 humidity, but on 40.50 will show 40.52, that's it not a big deal, the sensor it self don't have that accuracy, but the idea is to don't put more errors in as code. Also i notice, SHT25 is more faster and accurate than SHT75 sensor, even the technical data look almost the same. The data line has tested above 1 meter, with decouple 100n cap on the end.
 
  	  | Code: | 	 		  #include <18F4550.h>
 
#device ADC=16
 
 
#FUSES NOWDT                    //No Watch Dog Timer
 
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
 
#FUSES NOBROWNOUT               //No brownout reset
 
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
 
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
 
 
//#use fast_io(B)
 
//#use delay(internal=8MHz)
 
//#USE RS232
 
//#use standard_io(B)
 
 
#use delay(crystal=8MHz)
 
 
extern void lcd_gotoxy(int8 x, int8 y);
 
extern void lcd_putc(char c); | 	  
 
 
SHT2x driver 
 
 	  | Code: | 	 		  /********************************************************************/ 
 
/*  Writer Tanase Bogdan                                           */ 
 
/*  (c) copyright www.wangine.ro                                   */ 
 
/*  ALL RIGHTS RESERVED                                             */ 
 
/*                                                                 */ 
 
/********************************************************************/ 
 
/* Ver 0.6 release 10/september/2015                                */ 
 
/********************************************************************/
 
/*Code will work with 4,8 and 16MHz oscillator, not tested above 16MHx*/
 
/*require pull up resistor 10k, on SDA/SCL line                    */
 
/********************************************************************/
 
//~~~~~~~~~~~~define I2C custom port~~~~~~~~~~~~~~~~~~~~~
 
#define sda_pin PIN_B0
 
#define scl_pin PIN_B1
 
//IIC
 
/*****************************Macro definition*****************************/
 
#define  SCL_H   output_high(scl_pin)
 
#define  SCL_L   output_low(scl_pin)
 
#define  SDA_H   output_high(sda_pin)
 
#define  SDA_L   output_low(sda_pin)
 
 
#define  SCL_out output_drive(scl_pin)       //Output Clock
 
#define  SDA_in  output_high(sda_pin)        //SDA change the input mode
 
#define  SDA_out output_drive(sda_pin)       //SDA output mode back
 
#define  SDA_val input_state(sda_pin)        //Bit value of SDA
 
 
#define ACK          0   //Reply
 
#define NACK         1   //Non-responders
 
#define SHT21ADDR    0x80
 
 
#define humid_comand 0xF5 // command reading humidity
 
#define temp_comand  0xF3 // command reading temperature
 
 
#define REG_wait     120
 
#define calibration  0.996018f
 
 
float temperature =  0;   // global temp variable
 
float humidity    =  0; // global humid variable
 
/*****************************************************************
 
[Function name] Start
 
[Function] to complete the operation starting condition IIC
 
[Parameters None
 
[Return value None
 
*****************************************************************/
 
void Start(void)
 
{
 
    SCL_out;
 
    SDA_out;
 
 
    SDA_H;
 
    SCL_H;
 
    delay_us(10);
 
    SDA_L;
 
    delay_us(10);
 
    SCL_L;
 
    delay_us(10);
 
}
 
/*****************************************************************
 
[Function name] Stop
 
[Function] to complete the operation termination condition IIC
 
[Parameters None
 
[Return value None
 
*****************************************************************/
 
void Stop(void)
 
{
 
    SCL_out;
 
    SDA_out;
 
    SCL_L;
 
    delay_us(10);
 
    SDA_L;
 
    delay_us(10);
 
    SDA_H;
 
    delay_us(10);
 
    SCL_H;
 
    delay_us(10);
 
 
}
 
 
/*****************************************************************
 
[Function name] Mack
 
[Function] to complete IIC host response operations
 
[Parameters None
 
[Return value None
 
*****************************************************************/
 
void Mack(void)
 
{
 
    SCL_out;
 
    SDA_out;
 
    SDA_L;
 
    delay_us(2);
 
    SCL_H;
 
    delay_us(10);
 
    SCL_L;
 
    delay_us(10);
 
    SDA_H;
 
    delay_us(10);
 
}
 
/*****************************************************************
 
[Function name] MNack
 
[Function] to complete non-response operations IIC hosts
 
[Parameters None
 
[Return value None
 
*****************************************************************/
 
void MNack(void)
 
{
 
    SCL_out;
 
    SDA_out;
 
    SDA_H;
 
    delay_us(2);
 
    SCL_H;
 
    delay_us(10);
 
    SCL_L;
 
    delay_us(2);
 
    SDA_L;
 
    delay_us(10);
 
}
 
/*****************************************************************
 
[Function name] Check
 
[Function] check from the answering machine's operation, 1-- there, no 0--
 
[Parameters None
 
[Return Value] ACK (acknowledge) or NACK (not acknowledge)
 
*****************************************************************/
 
unsigned char Check(void)
 
{
 
   int1 ack_q;
 
 
    SCL_out;
 
    SDA_out;
 
    SDA_H;
 
    delay_us(2);
 
    SCL_H;
 
    delay_us(2);
 
    SDA_in;
 
    delay_us(2);
 
    ack_q = SDA_val;   //??SDA??
 
    SCL_L;
 
    delay_us(10);
 
    SDA_out;
 
    if(ack_q)    return NACK;//1:???
 
    else       return ACK;
 
}
 
/*****************************************************************
 
[Function name] Write1
 
[Function] IIC bus sends a 1
 
[Parameters None
 
[Return value None
 
*****************************************************************/
 
void Write1(void)
 
{
 
    SCL_out;
 
    SDA_out;
 
    SCL_L;
 
    delay_us(10);
 
 
    SDA_H;
 
    delay_us(2);
 
    SCL_H;
 
    delay_us(10);
 
    SCL_L;
 
    delay_us(10);
 
}
 
/*****************************************************************
 
[Function name] Write0
 
[Function] sending a 0 to the IIC bus
 
[Parameters None
 
[Return value None
 
*****************************************************************/
 
void Write0(void)
 
{
 
    SCL_out;
 
    SDA_out;
 
    SCL_L;
 
    delay_us(10);
 
 
    SDA_L;
 
    delay_us(2);
 
    SCL_H;
 
    delay_us(10);
 
    SCL_L;
 
    delay_us(10);
 
}
 
 
/*****************************************************************
 
[Function name] WriteByte
 
[Function] to send a byte to the IIC bus
 
[Parameters] wdata for the data to be written
 
[Return Value] respond to the response signal returned from the machine
 
*****************************************************************/
 
unsigned char WriteByte(unsigned char wdata)
 
{
 
    unsigned char i,respond;
 
    SCL_out;
 
    SDA_out;
 
 
    for(i = 8;i > 0;i--)
 
    {
 
        if(wdata & 0x80)
 
            Write1();
 
        else
 
            Write0();
 
        wdata <<= 1;
 
    }
 
    SDA_H;
 
    delay_us(10);//_NOP();
 
    respond = Check();
 
    return respond;
 
}
 
/*****************************************************************
 
[Function name] ReadByte
 
[Function] to read a byte from the IIC bus
 
[Parameters None
 
[Return Value] rdata to read data
 
*****************************************************************/
 
unsigned char ReadByte(void)
 
{
 
    unsigned char  rdata = 0x01,i;
 
    int1 flag;
 
    SCL_out;
 
    //SDA_out;
 
 
    for(i = 0;i < 8;i++)
 
    {
 
        SDA_H;
 
        delay_us(2);//Delay();
 
        SCL_H;
 
        SDA_in;
 
        delay_us(10);//Delay();
 
        flag = SDA_val;
 
        rdata <<= 1;
 
        if(flag)
 
        {
 
            rdata |= 0x01;
 
        }
 
        SDA_out;
 
        SCL_L;
 
        delay_us(10);//Delay();
 
    }
 
    return rdata;
 
}
 
/*****************************************************************
 
[Function name] Read_temp and Read_humid
 
[Function] Sht21 measurement of temperature and humidity
 
Parameters  0xf3 measured temperature;  0xf5 measuring humidity
 
[Return Value] temperature, humidity
 
*****************************************************************/
 
void read_temp()
 
{
 
    float temp = 0;
 
    float T = 0;
 
    unsigned int8 MSB,LSB;
 
    Start();
 
    if(WriteByte(SHT21ADDR & 0xfe) == ACK)
 
    {
 
 
        if(WriteByte(temp_comand) == ACK)
 
        {
 
            do
 
            {
 
            delay_ms(REG_wait);
 
                Start();
 
            }
 
            while(WriteByte(SHT21ADDR | 0x01) == NACK);
 
            Stop();
 
               MSB = ReadByte();
 
            Mack();//IIC host response operations
 
               LSB = ReadByte();
 
            MNack();//IIC host non-response operation
 
 
            LSB &= 0xfc;// Two status bits, front and rear, LSB is conducting two physical computing must be set to '0'
 
            temp = MSB*256+LSB;
 
 
                T=0.26813*temp-4685;//TH=(175.72)*temp/65536.0-46.85;
 
                temperature = T / 100;
 
        }
 
    }
 
}
 
//********************************************************************
 
void read_humid()
 
{
 
    float temp = 0;
 
    float H = 0;
 
    unsigned int8 MSB,LSB;
 
    Start();
 
    if(WriteByte(SHT21ADDR & 0xfe) == ACK)
 
    {
 
 
        if(WriteByte(humid_comand) == ACK)
 
        {
 
            do
 
            {
 
            delay_ms(REG_wait);
 
                Start();
 
            }
 
            while(WriteByte(SHT21ADDR | 0x01) == NACK);
 
            Stop();
 
               MSB = ReadByte();
 
            Mack();//IIC host response operations
 
               LSB = ReadByte();
 
            MNack();//IIC host non-response operation
 
 
            LSB &= 0xfc;// Two status bits, front and rear, LSB is conducting two physical computing must be set to '0'
 
            temp = MSB*256+LSB;
 
 
                H = temp/65536.0 ;//0xC89F;
 
                humidity = (H * 125) - 6.50f ;   
 
            humidity *= calibration;
 
 //               humidity = (long int)(H*100)/100;//H =0.190735*temp-600;//TH = (temp*125.0)/65536.0-6;
 
        }
 
    }
 
}
 
//***************************************************************************** | 	  
 
and example how to use 
 
 	  | Code: | 	 		  #include <main4550.h>
 
#include <math.h> 
 
#include </src/flex_lcd_20x2.c>
 
#include </src/__SHT21.c>
 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
int1 flag_sht = 1;
 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
#INT_RTCC
 
void  RTCC_isr(void) 
 
{
 
                   WriteByte(0xFE); // in case if comunication is lost 
 
   if(flag_sht == true)
 
      {
 
         read_temp();
 
         flag_sht = false;
 
      }
 
   else
 
      {
 
         read_humid();
 
         flag_sht = true;
 
      }
 
}
 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
void main ()
 
   {   
 
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4);      //262 ms overflow
 
 
   enable_interrupts(INT_RTCC);
 
   enable_interrupts(GLOBAL);
 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
lcd_init();  // Always call this first. 
 
delay_ms(10);   // Minimum 1 ms required after power-up.
 
   
 
   while (true)
 
      {
 
//   read_temp();
 
  lcd_gotoxy(1,1); 
 
  printf(lcd_putc, "temperatura:%3.2f gC ", temperature ); 
 
//   read_humid();
 
  lcd_gotoxy(1,2);
 
  printf(lcd_putc, "umiditate  :%3.2f RH ", humidity );             
 
      }
 
   } | 	 
  | 
			 
		  |