www.mikrocontroller.net

libsht.c

libsht.c
/***********************************************************************************
Sensirion SHTxx Sensor Library 0v1

***********************************************************************************/
/* COpyright Notice
   This library for the SHT temperature and humidity sensors is based on the 
  application datasheet Sample Code humidity sensor SHTxx from Sensirion. 
  (c) Timo Dittmar
    (For now. If I get enough feedback and a positive answer from
    Sensirion I plan to release the code under GPL)
  Use without any warranty
*/


/* History
  Date, Version, Comment 
  2006-07-14  NA    - Initial conversion from Sensirion application note
            - inserted test code
  2006-07-17  NA    - Adjusted timing in measurement
            - changed data transfer in calc_sht; 
  2006-07-20  0v1rc  - Included heating element code 
  2006-08-05  0v1    - Some additional cleanup
            - homogenized function names;
*/

#include <avr/io.h> //Microcontroller specific library, e.g. port definitions
#include <math.h> //
#include <stdlib.h> //
#include <inttypes.h> // 
#include <util/delay.h>
#include "libsht.h"





//----------------------------------------------------------------------------------
unsigned char sht_write_byte(unsigned char sht_value)
//----------------------------------------------------------------------------------
// writes a byte on the Sensibus and checks the acknowledge
{
unsigned char i;
unsigned char error=0;
MAKE_SHT_DATA_PIN_OUTPUT;
asm volatile ("nop"::); // necessary because of the sync circuitry 
for (i=0x80;i>0;i/=2) //shift bit for masking
  {if (i & sht_value) SET_SHT_DATA; //masking value with i , write to SENSI-BUS
   else CLEAR_SHT_DATA;
   SET_SHT_SCK; //clk for SENSI-BUS
   asm volatile ("nop"::);
   asm volatile ("nop"::);
   CLEAR_SHT_SCK;
   asm volatile ("nop"::);
   asm volatile ("nop"::);
  }
SET_SHT_DATA; //release DATA-line
MAKE_SHT_DATA_PIN_INPUT;
asm volatile ("nop"::);
SET_SHT_SCK; //clk #9 for ack
asm volatile ("nop"::);
asm volatile ("nop"::);
if (SHT_DATA) error =1; //check ack (DATA will be pulled down by SHT11)
CLEAR_SHT_SCK;
return error; //error=1 in case of no acknowledge
}



//----------------------------------------------------------------------------------
unsigned char sht_read_byte(unsigned char ack)
//----------------------------------------------------------------------------------
// reads a byte form the Sensibus and gives an acknowledge in case of "ack=1"
{
unsigned char i;
unsigned char val=0;
MAKE_SHT_DATA_PIN_OUTPUT;
asm volatile ("nop"::); // necessary because of the sync circuitry
SET_SHT_DATA; //release DATA-line
MAKE_SHT_DATA_PIN_INPUT;
asm volatile ("nop"::); // necessary because of the sync circuitry
for (i=0x80;i>0;i/=2) //shift bit for masking
  { SET_SHT_SCK; //clk for SENSI-BUS
   asm volatile ("nop"::); 
   asm volatile ("nop"::);
   if (SHT_DATA) val=(val | i); //read bit
   CLEAR_SHT_SCK;
   asm volatile ("nop"::); 
   asm volatile ("nop"::);
  }
MAKE_SHT_DATA_PIN_OUTPUT;
asm volatile ("nop"::); // necessary because of the sync circuitry
if (ack) CLEAR_SHT_DATA; else SET_SHT_DATA; // Sent ack
SET_SHT_SCK; //clk #9 for ack
asm volatile ("nop"::);
asm volatile ("nop"::);
asm volatile ("nop"::);
CLEAR_SHT_SCK;
asm volatile ("nop"::);
asm volatile ("nop"::);
SET_SHT_DATA; //release DATA-line
return val;
}



//----------------------------------------------------------------------------------
void sht_transstart(void)
//----------------------------------------------------------------------------------
// generates a transmission start
{
MAKE_SHT_DATA_PIN_OUTPUT;
asm volatile ("nop"::);
SET_SHT_DATA; CLEAR_SHT_SCK; //Initial state
asm volatile ("nop"::);
asm volatile ("nop"::);
SET_SHT_SCK;
asm volatile ("nop"::);
asm volatile ("nop"::);
CLEAR_SHT_DATA;
asm volatile ("nop"::);
asm volatile ("nop"::);
CLEAR_SHT_SCK;
asm volatile ("nop"::);
asm volatile ("nop"::);
asm volatile ("nop"::);
asm volatile ("nop"::);
asm volatile ("nop"::);
asm volatile ("nop"::);
SET_SHT_SCK;
asm volatile ("nop"::);
asm volatile ("nop"::);
SET_SHT_DATA;
asm volatile ("nop"::);
asm volatile ("nop"::);
CLEAR_SHT_SCK;
}


//----------------------------------------------------------------------------------
void sht_connectionreset(void)
//----------------------------------------------------------------------------------
// communication reset: DATA-line=1 and at least 9 SCK cycles followed by transstart
{
unsigned char i;
MAKE_SHT_DATA_PIN_OUTPUT;
asm volatile ("nop"::);
SET_SHT_DATA; CLEAR_SHT_SCK; //Initial state
for(i=0;i<9;i++) //9 SCK cycles
{ SET_SHT_SCK;
asm volatile ("nop"::);
asm volatile ("nop"::);
CLEAR_SHT_SCK;
asm volatile ("nop"::);
asm volatile ("nop"::);
}
sht_transstart(); //transmission start
}



//----------------------------------------------------------------------------------
unsigned char sht_softreset(void)
//----------------------------------------------------------------------------------
// resets the sensor by a softreset
{
unsigned char error=0;
sht_connectionreset(); //reset communication
error+=sht_write_byte(RESET); //send RESET-command to sensor
return error; //error=1 in case of no response form the sensor
}



//----------------------------------------------------------------------------------
unsigned char sht_read_statusreg(unsigned char *p_sht_value, unsigned char *p_checksum)
//----------------------------------------------------------------------------------
// reads the status register with checksum (8-bit)
{
unsigned char error=0;

sht_transstart(); //transmission start
error=sht_write_byte(STATUS_REG_R); //send command to sensor
*p_sht_value=sht_read_byte(ACK); //read status register (8-bit)
*p_checksum=sht_read_byte(noACK); //read checksum (8-bit)
return error; //error=1 in case of no response form the sensor
}



//----------------------------------------------------------------------------------
unsigned char sht_write_statusreg(unsigned char *p_sht_value)
//----------------------------------------------------------------------------------
// writes the status register with checksum (8-bit)
{
unsigned char error=0;
sht_transstart(); //transmission start
error+=sht_write_byte(STATUS_REG_W);//send command to sensor
error+=sht_write_byte(*p_sht_value); //send value of status register
return error; //error>=1 in case of no response form the sensor
}



//----------------------------------------------------------------------------------
unsigned char sht_measure(sht_value *p_sht_value, unsigned char *p_checksum, unsigned char mode)
//----------------------------------------------------------------------------------
// makes a measurement (humidity/temperature) with checksum
{
unsigned error=0;
unsigned int i;
sht_value sht_value_temp;
/* sht_transstart(); //transmission start */
sht_connectionreset();
switch(mode){ //send command to sensor
case TEMP : error+=sht_write_byte(MEASURE_TEMP); break;
case HUMI : error+=sht_write_byte(MEASURE_HUMI); break;
default : break;
}
for (i=0;i<65535;i++) {
  if(SHT_DATA==0) break; //wait until sensor has finished the measurement
  _delay_us(6);    // neccesary since the AVR is so much faster than the old 8051
          // and the 210ms for 14bit measuremnt are only a rough estimate
  }
if(SHT_DATA) error+=1; // or timeout is reached 
sht_value_temp.i = 256*sht_read_byte(ACK); //read the first byte (MSB)
sht_value_temp.i +=sht_read_byte(ACK); //read the second byte (LSB)
*p_checksum =sht_read_byte(noACK); //read checksum
*(p_sht_value)= sht_value_temp;
return error;
}




//----------------------------------------------------------------------------------------
void sht_raw_to_physical(sht_value *p_humidity ,sht_value *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_lin; // rh_lin: Humidity linear
float rh_true; // rh_true: Temperature compensated humidity
float t_C; // t_C : Temperature [C]

t_C = 0.01*(*p_temperature).i +(SHT_TEMP_OFFSET); //calc. Temperature from ticks to [C]
rh_lin=C3*(*p_humidity).i*(*p_humidity).i + C2*(*p_humidity).i + C1; //calc. Humidity from ticks to [%RH]
rh_true=(t_C-25)*(T1+T2*(*p_humidity).i)+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).f=t_C;  //return temperature [C]
(*p_humidity).f=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;
}

//--------------------------------------------------------------------
void sht_switch_heating_element(unsigned char onoff)
//--------------------------------------------------------------------
// shwitches the internal heating element
// input onoff 0:off 1:on 
{
unsigned char status;
unsigned char checksum;
sht_read_statusreg(&status, &checksum);
if (onoff==0) status &= ~(HEATER_BIT);
  else status |= (HEATER_BIT);
sht_write_statusreg(&status);
}
webmaster@mikrocontroller.netImpressumWerbung auf Mikrocontroller.net