/*********************************************************************************** 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 //Microcontroller specific library, e.g. port definitions #include // #include // #include // #include #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); }