//----------------------------------------------------------------------------------
//
// Sensirion SHT1x Humidity Sensor Library
//
//----------------------------------------------------------------------------------
#ifndef __sht_h
#define __sht_h
#include "iom32.h"
#define SHT_POWER_DDR DDRD
#define SHT_POWER_PORT PORTD
#define SHT_POWER_PIN PIND
#define SHT_POWER 8
#define SHT_DDR DDRC // Port with clock and data pins
#define SHT_PORT PORTC // Port with clock and data pins
#define SHT_PIN PINC // Port with clock and data pins
#define SHT_CLOCK 0 // Pin used to output clock to SHT
#define SHT_DATA 1 // Pin used to read/output data from/to SHT
#define SHT_DELAY 150 // uS delay between clock rise/fall
#define SHT_DELAY_POMIAR 5
#define SHT_TEMPERATURE 0x03 // Measure temp - for ShtMeasure
#define SHT_HUMIDITY 0x05 // Measure humidity - for ShtMeasure
#define STATUS_REG_W 0x06 // Command to read status register
#define STATUS_REG_R 0x07 // Command to write status register
#define RESET 0x1E // Command for soft reset (not currently used)
// physical connection:
#define sht_port_off() (PORTD &=~(1<<7))
#define sda_port_off() (PORTC &=~(1<<1))
#define scl_port_off() (PORTC &=~(1<<0))
//#define scl_port_off() (DDRC|=(1<<0))
#define sht_on() (DDRD|=(1<<7))
#define sht_off() (DDRD&=~(1<<7))
#define sda_h() (DDRC&=~(1<<1))
#define sda_l() (DDRC|=(1<<1))
#define scl_h() (DDRC&=~(1<<0))
#define scl_l() (DDRC|=(1<<0))
//#define scl_l() (PORTC&=~(1<<0))
//#define scl_h() (PORTC|=(1<<0))
unsigned char sht_trans_start(void);
unsigned char Init_Sht(void);
unsigned char sht_reset(void);
unsigned char sht_read_byte(void);
unsigned char sht_write_byte(unsigned char value);
unsigned char sht_measure(unsigned char mode,int *p_temperature, int *p_humidity);
void sht_calculate(int *p_temperature, int *p_humidity);
unsigned char sht_read_status(unsigned char *p_value);
unsigned char sht_write_status(unsigned char value);
unsigned char bitswapbyte(unsigned char byte);
unsigned char sht_computeCRC8(unsigned char inData, unsigned char seed);
unsigned char sht_soft_reset(void);
#endif
//----------------------------------------------------------------------------------
//
// Sensirion SHTxx Humidity Sensor Library
//
//----------------------------------------------------------------------------------
#include "iom32.h"
#include "config.h"
#include "Sht.h"
#include "timer.h"
//#include "tgt.h"
//#include "delay.h"
const U8 __flash sht_crc_table[] = {
0, 49, 98, 83, 196, 245, 166, 151, 185, 136, 219, 234, 125, 76, 31, 46, 67, 114, 33, 16,
135, 182, 229, 212, 250, 203, 152, 169, 62, 15, 92, 109, 134, 183, 228, 213, 66, 115, 32, 17,
63, 14, 93, 108, 251, 202, 153, 168, 197, 244, 167, 150, 1, 48, 99, 82, 124, 77, 30, 47,
184, 137, 218, 235, 61, 12, 95, 110, 249, 200, 155, 170, 132, 181, 230, 215, 64, 113, 34, 19,
126, 79, 28, 45, 186, 139, 216, 233, 199, 246, 165, 148, 3, 50, 97, 80, 187, 138, 217, 232,
127, 78, 29, 44, 2, 51, 96, 81, 198, 247, 164, 149, 248, 201, 154, 171, 60, 13, 94, 111,
65, 112, 35, 18, 133, 180, 231, 214, 122, 75, 24, 41, 190, 143, 220, 237, 195, 242, 161, 144,
7, 54, 101, 84, 57, 8, 91, 106, 253, 204, 159, 174, 128, 177, 226, 211, 68, 117, 38, 23,
252, 205, 158, 175, 56, 9, 90, 107, 69, 116, 39, 22, 129, 176, 227, 210, 191, 142, 221, 236,
123, 74, 25, 40, 6, 55, 100, 85, 194, 243, 160, 145, 71, 118, 37, 20, 131, 178, 225, 208,
254, 207, 156, 173, 58, 11, 88, 105, 4, 53, 102, 87, 192, 241, 162, 147, 189, 140, 223, 238,
121, 72, 27, 42, 193, 240, 163, 146, 5, 52, 103, 86, 120, 73, 26, 43, 188, 141, 222, 239,
130, 179, 224, 209, 70, 119, 36, 21, 59, 10, 89, 104, 255, 206, 157, 172 };
static U8 crcValue;
unsigned char crc_state=0;
//----------------------------------------------------------------------------------
// Initialize AVR i/o pins.
//----------------------------------------------------------------------------------
unsigned char Init_Sht(void)
{
sht_port_off();
sda_port_off();
scl_port_off();
sht_off();
scl_h();
sda_h();
sht_on();
delay_us(100);
if (bit_is_set(SHT_PIN,SHT_DATA))
{
if (bit_is_set(SHT_PIN,SHT_CLOCK))
{
return 0;
}
}
sht_off();
return 1;
}
//----------------------------------------------------------------------------------
// generates a transmission start
// _____ ________
// DATA: |_______|
// ___ ___
// SCK : ___| |___| |______
//
//----------------------------------------------------------------------------------
unsigned char sht_trans_start(void)
{
unsigned char err=0;
scl_l();
delay_us(SHT_DELAY);
delay_us(SHT_DELAY);
scl_h();
delay_us(SHT_DELAY);
err = bit_is_clear(SHT_PIN, SHT_CLOCK);
sda_l();
delay_us(SHT_DELAY);
err += bit_is_set(SHT_PIN, SHT_DATA);
scl_l();
delay_us(SHT_DELAY);
delay_us(SHT_DELAY);
scl_h();
delay_us(SHT_DELAY);
err += bit_is_clear(SHT_PIN, SHT_CLOCK);
sda_h();
delay_us(SHT_DELAY);
scl_l();
delay_us(SHT_DELAY);
delay_us(SHT_DELAY);
if(err){return 1;}
else {return 0;}
}
//----------------------------------------------------------------------------------
// communication reset: DATA-line=1 and at least 9 SCK cycles followed by transstart
// _____________________________________________________ ________
// DATA: |_______|
// _ _ _ _ _ _ _ _ _ ___ ___
// SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______| |___| |______
//----------------------------------------------------------------------------------
unsigned char sht_reset(void)
{
unsigned char i;
sda_h();
scl_l();
delay_us(SHT_DELAY);
delay_us(SHT_DELAY);
for(i=0;i<10;i++) //9 SCK cycles
{
scl_h();
delay_us(SHT_DELAY);
delay_us(SHT_DELAY);
scl_l();
delay_us(SHT_DELAY);
delay_us(SHT_DELAY);
}
return sht_trans_start(); //transmission start
}
//----------------------------------------------------------------------------------
// Soft reset
//----------------------------------------------------------------------------------
unsigned char sht_soft_reset(void)
{
U8 err=0;
err=sht_reset();
err+=sht_write_byte(RESET);
return err;
}
//----------------------------------------------------------------------------------
// reads a byte form the Sensibus and gives an acknowledge in case of "ack=1"
//----------------------------------------------------------------------------------
unsigned char sht_read_byte(void)
{
unsigned char i=0x80,val=0,f,f1=0;
while(i)
{
scl_l();
delay_us(SHT_DELAY);
delay_us(SHT_DELAY);
scl_h();
delay_us(SHT_DELAY_POMIAR);
for (f=0;f<7;f++)
{
if (bit_is_set(SHT_PIN, SHT_DATA))
{
f1++;
}
}
if (f1>3)
{
val=(val | i); //read bit
}
f1=0;
delay_us(SHT_DELAY-10);
delay_us(SHT_DELAY);
i=(i>>1);
}
sda_l();
scl_l();
delay_us(SHT_DELAY);
delay_us(SHT_DELAY);
scl_h();
delay_us(SHT_DELAY);
delay_us(SHT_DELAY);
sda_h();
scl_l();
delay_us(SHT_DELAY);
return val;
}
//----------------------------------------------------------------------------------
// Writes a byte on the Sensibus and checks the acknowledge.
// Returns 0 if the successful
//----------------------------------------------------------------------------------
unsigned char sht_write_byte(unsigned char value) //impuls narastajacy czyta
{
unsigned char i=0x80,f,f1=0;
unsigned char err = 0;
// Write each bit one at a time, LSB first
delay_us(SHT_DELAY);
while(i)
{ //shift bit for masking
scl_l();
if (i & value) {
sda_h(); //masking value with i , write to SENSI-BUS
}else{
sda_l();
}
delay_us(SHT_DELAY);
delay_us(SHT_DELAY);
scl_h(); //clk for SENSI-BUS
delay_us(SHT_DELAY);
delay_us(SHT_DELAY);
i=(i>>1);
}
sda_h();
scl_l();
delay_us(SHT_DELAY);
delay_us(SHT_DELAY);
scl_h();
delay_us(5);
f1=0;
for (f=0;f<7;f++)
{
if (bit_is_set(SHT_PIN, SHT_DATA))
{
f1++;
}
}
if (f1>2)
{
err=1;
}
delay_us(SHT_DELAY-10);
delay_us(SHT_DELAY);
scl_l();
return err; //error=1 in case of no acknowledge
}
//----------------------------------------------------------------------------------
// Read humidity or temperature from the sensor.
// Returns the value in ticks. Use sht_calc() to convert to real world units.
// Returns 0xFFFF if the measurment failed
//----------------------------------------------------------------------------------
unsigned char sht_measure(unsigned char mode,int *p_temperature, int *p_humidity)
{
unsigned int temp = 0xFFFF;
unsigned char checksum=0,err=0;
unsigned char c,f1=0;
crcValue=0;
crcValue=sht_crc_table[mode ^ crcValue];
if(sht_trans_start()){return 1;}
// Request measurement
err=sht_write_byte(mode);
if (err) {return 2;}
// Sensor lowers the data line when measurement
// is complete. Wait up to 2 seconds for this.
delay_ms(50);
for (c=0; c<250; c++)
{
if (! bit_is_set(SHT_PIN, SHT_DATA))
{
f1++;
if (f1>3){break;}
}
delay_1ms();
if (c==249){return 3;}
}
if (! bit_is_set(SHT_PIN, SHT_DATA))
{
checksum = sht_read_byte();
crcValue=sht_crc_table[checksum ^ crcValue];
temp=checksum;
temp = temp << 8;
checksum=sht_read_byte();
crcValue=sht_crc_table[checksum ^ crcValue];
temp +=checksum;
checksum=bitswapbyte(sht_read_byte());
}
if (checksum==crcValue)
{
if (mode==SHT_TEMPERATURE)
{*p_temperature=temp;}
else if (mode==SHT_HUMIDITY)
{ *p_humidity=temp;}
return 0;
}
return 4;
}
//----------------------------------------------------------------------------------------
// Calculates tempurature in ^C and humidity in %RH (temperature compensated)
// sht_measure() returns temp and humidity in ticks. Use this function to convert
// to compensated values in real world units.
//
// This function returns integers with 2 assumed decimal places. For example 2550
// means 25.50. This is to avoid including the floating point math library.
//
// input : humi [Ticks] (12 bit)
// temp [Ticks] (14 bit)
// output: humi [%RH] (2 fixed decimals)
// temp [^C] (2 fixed decimals)
//----------------------------------------------------------------------------------------
void sht_calculate(int *p_temperature, int *p_humidity)
{
const long D1x100 = -40.00 * 100; // for 5V power
const long D2x100 = 0.01 * 100; // for 14bit temp
const long C1x100 = -4 * 100; // for 12bit humidity
const long C2x10000 = 0.0405 * 10000; // for 12bit humidity
const long C3x10000000 = -0.0000028 * 10000000; // for 12bit humidity
const long T1x100000 = 0.01 * 100000; // for 12bit humidity
const long T2x100000 = 0.00008 * 100000; // for 12bit humidity
long t = *p_temperature; // temperatere in ticks from sensor
long rh = *p_humidity; // humidity in ticks from sensor
long t_C; // temperature in celcius: 2 fixed decimals
long rh_lin; // relative humidity: 2 fixed decimals
long rh_true; // temp compensated humidity: 2 fixed decimals
t_C = D1x100 + D2x100*t; // calculate tempurature in celcius from ticks
rh_lin = (C3x10000000*rh*rh)/100000 + (C2x10000*rh)/100 + C1x100;
rh_true = ((t_C-(25*100)) * (T1x100000 + T2x100000*rh))/100000 + rh_lin;
if(rh_true>10000){rh_true=10000;} //cut if the value is outside of
if(rh_true<10){rh_true=10;} //the physical possible range
*p_temperature=(int)t_C; //return temperature [^C]
*p_humidity=(int)rh_true; //return humidity[%RH]
}
//----------------------------------------------------------------------------------
// Reads the status register with checksum (8-bit)
//----------------------------------------------------------------------------------
unsigned char sht_read_status(unsigned char *p_value)
{
unsigned char err=0;
unsigned char checksum=0;
sht_trans_start(); //transmission start
err = sht_write_byte(STATUS_REG_R); //send command to sensor
if (err) {return 1;}
*p_value = sht_read_byte(); //read status register (8-bit)
crcValue=sht_crc_table[*p_value ^ 151];
checksum=bitswapbyte(sht_read_byte()); //read checksum (8-bit)
if (checksum==crcValue)
{return 0;}
else
{err+=2;}
return err; //error=1 in case of no response form the sensor
}
//----------------------------------------------------------------------------------
// Writes the status register . Note this library only supports the default
// 14 bit temp and 12 bit humidity readings.
//----------------------------------------------------------------------------------
unsigned char sht_write_status(unsigned char value)
{
unsigned char err=0;
sht_trans_start(); //transmission start
err += sht_write_byte(STATUS_REG_W); //send command to sensor
err += sht_write_byte(value); //send value of status register
return err; //error>=1 in case of no response form the sensor
}
// Compute the CRC8 value of a data set.
//
// This function will compute the CRC8 of inData using seed
// as inital value for the CRC.
//
// This function was copied from Atmel avr318 example files.
// It is more suitable for microcontroller than the code example
// in the sensirion CRC application note.
//
// inData One byte of data to compute CRC from.
//
// seed The starting value of the CRC.
//
// return The CRC8 of inData with seed as initial value.
//
// note Setting seed to 0 computes the crc8 of the inData.
//
// note Constantly passing the return value of this function
// As the seed argument computes the CRC8 value of a
// longer string of data.
//
unsigned char sht_computeCRC8(unsigned char inData, unsigned char seed)
{
unsigned char bitsLeft;
unsigned char tmp;
for (bitsLeft = 8; bitsLeft > 0; bitsLeft--)
{
tmp = ((seed ^ inData) & 0x01);
if (tmp == 0)
{
seed >>= 1;
}else{
seed ^= 0x18;
seed >>= 1;
seed |= 0x80;
}
inData >>= 1;
}
return seed;
}
// sensirion has implemented the CRC the wrong way round. We
// need to swap everything.
// bit-swap a byte (bit7->bit0, bit6->bit1 ...)
unsigned char bitswapbyte(unsigned char byte)
{
unsigned char i=8;
unsigned char result=0;
while(i){
result=(result<<1);
if (1 & byte) {
result=result | 1;
}
i--;
byte=(byte>>1);
} return(result);
}