SHT-11 Isı ve Nem sensörü Okuma Programı

Başlatan ete, 18 Haziran 2005, 22:41:24

ete

Arkadaşlar,

Bir kaç arkadaştan gelen istek üzerine SHT-11 ısı ve nem sönsöründen ısı ve nem ham değerlerinin okunması ve bu değerlerin hesaplanarak sıcaklık ve rutubet değerlerine dönüştürülüp ekrana verilmesi konusunda bir program parçası veriyorum. Sorularınız olur ise yanıtlamaya çalışırım.

ETE

DEFINE LCD_DREG		PORTB	'LCD data bacakları hangi porta bağlı?
DEFINE LCD_DBIT		4		'LCD data bacakları hangi bitten başlıyor?
DEFINE LCD_RSREG	PORTB	'LCD RS Bacağı Hangi Porta bağlı ?
DEFINE LCD_RSBIT	1		'LCD RS bacağı Hangi Bite bağlı ?
define lcd_RWREG    PORTB
define LC_RWBIT     2
DEFINE LCD_EREG		PORTB	'LCD Enable Bacağı Hangi Porta bağlı?
DEFINE LCD_EBIT		3		'LCD Enable Bacağı Hangi bite bağlı ?
DEFINE LCD_BITS		4		'LCD 4 bit mi yoksa 8 bit olarak bağlı?
DEFINE LCD_LINES	2		'LCD Kaç sıra yazabiliyor
OPTION_REG.7=1
@ DEVICE pic16F628
@ DEVICE pic16F628, WDT_ON
@ DEVICE pic16F628, PWRT_ON
@ DEVICE pic16F628, PROTECT_OFF
@ DEVICE pic16F628, MCLR_OFF
@ DEVICE pic16F628, INTRC_OSC_NOCLKOUT
'---------------------------değişkenler------------------------------
    KONTROL VAR     BYTE	   
    ISI1    VAR     BYTE      
    ISI2    VAR     BYTE      
    U1      VAR     BYTE         
    U2      VAR     BYTE
    H0      VAR     HAM.BYTE0
    H1      VAR     HAM.BYTE1
    HAM		VAR	    WORD
    RAW     var     word
    ISI     VAR     WORD 
    P1      VAR     WORD
    P2      VAR     WORD
    P3      VAR     WORD             
    W       VAR     WORD
    CLK     VAR     PORTA.0
    DTA     VAR     PORTA.1  
    ISARET  VAR     BIT   'sensor değeri 0 ise artı, 1 ise eksi
    HATA    var     BIT

  '-----------------------------B A Ş L A N G I Ç ---------------------------    
 
   	CLEAR:TRISA=%00111000:TRISB=0:CMCON=7
     low PortB.2                
    PAUSE 200:ISARET=0
    LCDOUT $FE,$40,$6,$9,$9,$6,$0,$0,$0,$0        'derece işareti dataları    
    LCDOUT $FE,$48,$04,$0e,$0e,$0e,$1f,$04,$04,$0 
    LCDOut $FE,1
    gosub reset :GOSUB T_START
'-------------------------------------------------------------------------------    
BASLA:  
        KONTROL=%00000011:HAM=0   'SICAKLIK ÖLÇME
        GOSUB OLCUMAL
       'HAM=4000 sıfır dereceye tekabül ediyor, HAM=3000 -10 derece oluyor.
        Gosub ISIHESAP:GOSUB EKRAN1
        
        KONTROL=%00000101:HAM=0 'RUTUBET ÖLÇME
        GOSUB OLCUMAL
        'HAM=3710 bu değer %100 rutubete eşdeğerdir.
        GOSUB RUTHESAP:GOSUB EKRAN2
        
'--------BU ARAYA ISI VE RUTUBETE BAĞLI KONTROL RUTİNİ YERLEŞTİRİLECEK--------------------

       
ATLA:   
        SLEEP 1
        GOTO BASLA			
'------------------------------------------------------------------
'---------------------------------------EKRANA YAZ ------------------------------------------------	
EKRAN1:	LCDOut $FE,2       
        if ISARET=1 THEN
          LCDOut "  ISI :-",DEC2 ISI1 , "," , DEC1 ISI2," ",0,"C ":RETURN  
        endIF 
        LCDOut "  ISI : ",DEC2 ISI1 , "," , DEC1 ISI2," ",0,"C ":RETURN
EKRAN2:	LCDOut $FE,$C0:
'        LCDOUT "RAI=",#RAI,"HAM=",#HAM  'deneme için
    	LCDOut "  NEM : ",DEC2 U1 , "," , DEC1 U2,"  % "
		RETURN		
'----------------------------------------------------------------------------------
        
'------------------------------- İŞLEM START ------------------------------------------------------
T_START:
        OUTPUT DTA:OUTPUT CLK
        HIGH DTA
        LOW CLK
        PAUSE 1
        HIGH CLK
        LOW DTA
        PAUSE 1
        LOW CLK
        PAUSE 1
        HIGH CLK
        PAUSE 1
        HIGH DTA
        LOW CLK
        RETURN

'-----------------------------R E S E T -----------------------------------------------------------
RESET:  OUTPUT DTA:OUTPUT CLK':TRISA.0=0:TRISA.1=0'
        high DTA=1
        FOR W=0 TO 9
        HIGH CLK
        pause 1
        LOW CLK
        Next W
        Return
'-----------------------SENSORE KOMUT GÖNDER -----------------------------------
OLCUMAL: GOSUB T_Start
        SHIFTOUT DTA,CLK,1,[KONTROL]
        INPUT DTA
        PULSOUT CLK,10
        HATA=0
        FOR W=0 to 65500
           IF DTA=0 then EXIT
        NEXT W
        HATA=1
EXIT:  IF HATA=1 then 
         gosub SENSORYOK
       endif
       SHIFTIN DTA,CLK,0,[H1]
       OUTPUT DTA
       LOW DTA
       PULSOUT CLK,10
       INPUT DTA
       SHIFTIN DTA,CLK,0,[H0]
       PULSOUT CLK,10
       RETURN
'----------------------ISI HESAP ALT PROGRAMI-----------------------------------      
ISIHESAP:  
           if ham<4000 then 
              ISARET=1 'sıcaklık eksi değerde demek
              ISI1=(4000-HAM)/100
              ISI2=((4000-ham)//100)/10   
              goto ISISON
            endif
           ISI1=(HAM-4000)/100
           ISI2=((HAM-4000)//100)/10
ISISON:    if HAM>16384 then
             ISI1=0:ISI2=0
           endif  
    RETURN
'-------------------------RUTUBET HESAP ALT PROGRAMI-------------------------------------------------
 RUTHESAP:  
           ISI=ISI1*10+ISI2
           p1=(26542-(54722**ham+ham))**ham-40     
           P2=655+(HAM*5)+(HAM**15917)	      
           P3=(P2**(ISI+2480))-(P2**2730)+P1   ' kompanse edilmiş değer
           U1=p3/10:U2=p3//10
           IF ham>3710 THEN
              u1=0:U2=0
              GOTO SENSORYOK
           ENDIF  
           return       
'----------------------------------------------------------------------------------  
       
SENSORYOK: LCDOUT $FE,$02,"   SENSOR YOK   "
           LCDOUT $FE,$C0," LUTFEN TAKINIZ "  
           PAUSE 1000               
           RETURN
        END                     
      
Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

SpeedyX

Selamlar,

Kendi datasheetinde verilen kodlar ile tek fark, sizinkinde hesaplama rutinlerinin olması mı?

mysda var PORTC.6
myscl var PORTC.7
hread con %00000101 ' lecture humiditÈ sur sht11
humid var word
humidchk var byte
h1 var word
h2 var word
h3 var word

sht11_init: ' initialisation du sht11
	Output mysda
	Output myscl
	High mysda
	Low myscl
	For i=1 to 10
		High myscl
		Pause 1
		Low myscl
		Pause 1
	Next i
	Call sht11_ts
	return

sht11_ts: ' transmission start
	High myscl
	Pause 1
	Low mysda
	Pause 1
	Low myscl
	Pause 1
	High myscl
	Pause 1
	High mysda
	Pause 1
	Low myscl
return

sht11_readhumid: ' lecture humiditÈ sur sht11
	Call sht11_ts
	Shiftout mysda,myscl,1,[hread\8] ' sortie commande lire humiditÈ
	Input mysda ' attente ack
	Low myscl
	While mysda=1
	Wend
	Pulsout myscl,10 ' envoi ack
	While mysda=0
	Wend
	While mysda=1 ' attente de la fin de la mesure
	Wend
	Low myscl
	ShiftIn mysda,myscl,0,[humid.highbyte\8]
	Low mysda
	Pulsout myscl,10 ' envoi ack
	ShiftIn mysda,myscl,0,[humid.lowbyte\8]
	Low mysda
	Pulsout myscl,10 ' envoi ack
	ShiftIn mysda,myscl,0,[humidchk\8]
	High mysda
	Pulsout myscl,10 ' envoi ack
	Input mysda
	Input myscl ' retour en haute impÈdance
	return

ete

@speedyx,

Herşeyden önce benim elimdeki datasheet de herhangi bir program kodu verilmiyor. Yalnızca uygulama notları var ve orada verilen programda PC ler için yazılmış pic için uygun değil. Ben SHT sensörü ile ilk tanıştığım zaman Sensirion dan örnek kod istemiş idim Pic için. Olmadığını belirttiler. Daha sonra kendim yazdığım kodları onlara gönderdim ellerinde bulunsun diye.

Bildiğin ve gördüğün gibi bu boardda lisan bilmeyen ancak elektronikle uğraşan pek çok insan var.  Bu insanlar datasheet değerlendiremiyorlar. Ayrıca datasheet de yazanları programa dönüştürebilecek adam sayısıda az. Bu insanlar örneklere bakarak hem bilgilerini artırır hemde program yazarlar. Verdiğim kodlar yalnızca bu arkadaşlara yönelik bir çalışmadır.
Fark aramaya gerek yok isteyen datasheetlerdeki bilgiyi kulnanır isteyen örnek kodları kullanır. Bilgi, bilgidir kullanana yarar sağlar.

ETE
Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

SpeedyX

Tabiki iyi birşey yaptın hocam, sana lafım yok. Yanlış anlaşılmasın, bende de bu kodlar var, ondan sordum acaba datasheette verilenler hatalı mı da bu arkadaş böyle bir kod yazmış diye sordum.
Hazır bulmuşsun gibi birşey demek istemedim. ;)

ete

@Speedyx,

Daha önce araştırmış idim. Piyasada pek çok kod örneği var. Benim elimde en az 4 değişik haberleşme kodu var. Temelde prensip aynı gidiş yolları farklı. Ancak bir kısmı çalışmıyor. Ufak tefek hatalar var.
Bu arada bende kendim data sheete bakarak üç değişik kod yazdım. İlk iki adedi Shiftin ve Shiftout kullanmadan yazdığım kodlar idi. Hepside çalışıyor ancak en iyi çalışanı yayınlamış olduğum kod. Senin verdiğini henüz incelemedim senin lafına bakarak aynı olduğunu anlıyorum. Aynı ise Sonuçta aklın yolu birdir diye bir laf var.
Selam
ETE
Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

Erol YILMAZ

@ete
SHT11'i bugun aldım.
Datasheet te sıcaklık ve bagıl nemin hesabında kullanılmak üzere ifadeler verilmiş. Bunları kullanacagim CCS ile...
12/8 bit çözünürlükte çalışacağım.

Temp= -40+0.04*SOT;
RH_linear = -4+0.648*SORH - 0.00072*(SORH*SORH) ;
RH_true = (Temp-25)*(0.01+0.00128*SORH) + RH_linear;

ifadesini kullanmayı düşünüyorum. Özellikle bahsetmek istediğin birşey var mı???

SpeedyX

@Erol
bende ccs için kodlar var, boşuna kod yazmaya uğraşma, bunlar işini görebilir.
//------------------------------------------------------------------------------
// Module hygrometre-thermometre sensirion sht11
//
// adaptations JYP 2003
//
//------------------------------------------------------------------------------

#include "math.h"

typedef union
{ unsigned int i;
float f;
} value;

enum {TEMP,HUMI};

#define sht_noACK 0
#define sht_ACK 1
//adr command r/w
#define sht_STATUS_REG_W 0x06 //000 0011 0
#define sht_STATUS_REG_R 0x07 //000 0011 1
#define sht_MEASURE_TEMP 0x03 //000 0001 1
#define sht_MEASURE_HUMI 0x05 //000 0010 1
#define sht_RESET 0x1e //000 1111 0

//------------------------------------------------------------------------------
char sht11_write_byte(unsigned char value)
//------------------------------------------------------------------------------
// writes a byte on the Sensibus and checks the acknowledge
{
unsigned char i,error=0;

for (i=0x80;i>0;i/=2) //shift bit for masking
{
if (i & value)
output_high(sht11_data); //masking value with i , write to SENSI-BUS
else
output_low(sht11_data);
output_high(sht11_sck); //clk for SENSI-BUS
delay_us( 5); //pulswith approx. 5 us
output_low(sht11_sck);
}
output_high(sht11_data); //release DATA-line
output_high(sht11_sck); //clk #9 for ack
error=input(sht11_data) ; //check ack (DATA will be pulled down by SHT11)
output_low(sht11_sck);
return error; //error=1 in case of no acknowledge
}

//------------------------------------------------------------------------------
char sht11_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;

output_high(sht11_data); //release DATA-line
for (i=0x80;i>0;i/=2) //shift bit for masking
{
output_high(sht11_sck); //clk for SENSI-BUS
if (input(sht11_data)==1)
val=(val | i); //read bit
output_low(sht11_sck);
}
output_bit(sht11_data,!ack); //in case of "ack==1" pull down DATA-Line
output_high(sht11_sck); //clk #9 for ack
delay_us( 5); //pulswith approx. 5 us
output_low(sht11_sck);
output_high(sht11_data); //release DATA-line
return val;
}

//------------------------------------------------------------------------------
void sht11_transstart(void)
//------------------------------------------------------------------------------
// generates a transmission start
// _____ ________
// DATA: |_______|
// ___ ___
// SCK : ___| |___| |______
{
output_high(sht11_data);
output_low(sht11_sck); //Initial state
delay_us( 1);
output_high(sht11_sck);
delay_us( 1);
output_low(sht11_data);
delay_us( 1);
output_low(sht11_sck);
delay_us( 3);
output_high(sht11_sck);
delay_us( 1);
output_high(sht11_data);
delay_us( 1);
output_low(sht11_sck);
}

//------------------------------------------------------------------------------
void sht11_connectionreset(void)
//------------------------------------------------------------------------------
// communication reset: DATA-line=1 and at least 9 SCK cycles
// followed by transstart
// _____________________________________________________ ________
// DATA: |_______|
// _ _ _ _ _ _ _ _ _ ___ ___
// SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______| |___| |______
{
unsigned char i;
output_high(sht11_data);
output_low(sht11_sck); //Initial state
for(i=0;i<9;i++) //9 SCK cycles
{
output_high(sht11_sck);
output_low(sht11_sck);
}
sht11_transstart(); //transmission start
}

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

//------------------------------------------------------------------------------
char sht11_read_statusreg(unsigned char *p_value, unsigned char *p_checksum)
//------------------------------------------------------------------------------
// reads the status register with checksum (8-bit)
{
unsigned char error=0;
sht11_transstart(); //transmission start
error=sht11_write_byte(sht_STATUS_REG_R); //send command to sensor
*p_value=sht11_read_byte(sht_ACK); //read status register (8-bit)
*p_checksum=sht11_read_byte(sht_noACK); //read checksum (8-bit)
return error; //error=1 in case of no response form the sensor
}

//------------------------------------------------------------------------------
char sht11_write_statusreg(unsigned char *p_value)
//------------------------------------------------------------------------------
// writes the status register with checksum (8-bit)
{
unsigned char error=0;
sht11_transstart(); //transmission start
error+=sht11_write_byte(sht_STATUS_REG_W);//send command to sensor
error+=sht11_write_byte(*p_value); //send value of status register
return error; //error>=1 in case of no response form the sensor
}

//------------------------------------------------------------------------------
char sht11_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;

sht11_transstart(); //transmission start
switch(mode)
{ //send command to sensor
case TEMP : error+=sht11_write_byte(sht_MEASURE_TEMP); break;
case HUMI : error+=sht11_write_byte(sht_MEASURE_HUMI); break;
default : break;
}

for (i=0;i<65535;i++)
if(input(sht11_data)==0)
break; //wait until sensor has finished the measurement
if(input(sht11_data)==1)
error+=1; // or timeout (~2 sec.) is reached

*(p_value+1) =sht11_read_byte(sht_ACK); //read the first byte (MSB)
*(p_value)=sht11_read_byte(sht_ACK); //read the second byte (LSB)
*p_checksum =sht11_read_byte(sht_noACK); //read checksum
return error;
}
char sht11_measure_temp(unsigned char *p_value, unsigned char *p_checksum)
{
return sht11_measure( p_value, p_checksum, TEMP);
}
char sht11_measure_humi(unsigned char *p_value, unsigned char *p_checksum)
{
return sht11_measure( p_value, p_checksum, HUMI);
}

//------------------------------------------------------------------------------
void sth11_calc(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,t,rh_lin,rh_true,t_C;
// rh_lin: Humidity linear
// rh_true: Temperature compensated humidity
// t_C : Temperature [°C]
rh=*p_humidity; // rh: Humidity [Ticks] 12 Bit
t=*p_temperature; // t: Temperature [Ticks] 14 Bit

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]
}

//--------------------------------------------------------------------
int sht11_calc_humid_int( int16 w_humidity)
//--------------------------------------------------------------------
{
// calcul de l'humidite en entier (sans calcul float)

int32 h1,h2;

h1 = ((int32) w_humidity) * ((int32) w_humidity);
h1 = h1 / (int32)1000;
h1 = h1 * (int32)28;
h2 = ((int32) w_humidity) * (int32)405;
h2 = h2 - h1;
h2 = h2 / (int32)1000;
h2 = h2 - (int32)40;
h2 = h2 / (int32)10;
return (h2);
}

//--------------------------------------------------------------------
int sht11_calc_temp_int( int16 w_temperature)
//--------------------------------------------------------------------
{
// calcul de la temperature en entier (sans calcul float)

int16 temp1;

temp1 = w_temperature / (int16)100;
temp1 = temp1 - (int16)40;
return (temp1);
}

//--------------------------------------------------------------------
int sht11_calc_temp_frac10( int16 w_temperature)
//--------------------------------------------------------------------
{
// calcul de la temperature en fractionnaire 0.X (sans calcul float)
// exemple si t=25.367 ° renvoie 3

int16 temp1;

temp1 = w_temperature / (int16)10;
temp1 = w_temperature - (int16)400;
temp1 = abs(temp1) - ((int16)10 * abs(sht11_calc_temp_int(w_temperature)));
return (temp1);
}

//--------------------------------------------------------------------
int sht11_calc_temp_frac100( int16 w_temperature)
//--------------------------------------------------------------------
{
// calcul de la temperature en fractionnaire 0.XX (sans calcul float)
// exemple si t=25.367 ° renvoie 36

int16 temp1;

temp1 = w_temperature - (int16)4000;
temp1 = abs(temp1) - ((int16)100 * abs(sht11_calc_temp_int(w_temperature)));
return (temp1);
}

//--------------------------------------------------------------------
float sht11_calc_dewpoint(float h,float t)
//--------------------------------------------------------------------
// calculates dew point
// input: humidity [%RH], temperature [°C]
// output: dew point [°C]
{
float logEx,dew_point;

logEx=0.66077+7.5*t/(237.3+t)+(log10(h)-2);
dew_point = (logEx - 0.66077)*237.3/(0.66077+7.5-logEx);
return dew_point;
}


Buda başka bir kod
Hola, yo he adaptado el ejemplo de la web al compilador ccs,
http://www.sensirion.com/en/pdf/Sample_Code_SHT11
te lo voy a pegar aqui, pero quiero dejar claro que no lo he probado aún, solo he adaptado el codigo y lo he compilado sin problema, me gustaria probarlo, pero este mes estoy fatal de tiempo a ver si me pongo a probarlo porque tengo el sensor ahora mismo por ahi tirado.....

Me gustaría, que si consigues hacerlo funcionar comentases cual fue tu experiencia, y si no te funciona y consigues retocarlo para que rule, que comentases por aqui los cambios que has realizado para que todos tengamos el codigo.

De todos modos si no quieres usar la libreria que he adaptado, y quieres usar la "tuya", no tienes mas que fijarte en el ejemplo y asi podras adaptar las funciones....

Tambien te recomiendo que te estudies bien el datasheet, para saber muy bien como funciona, ya que puedes elegir las resoluciones de las capturas, puedes usar la funcion calentador, vamos que tiene varias opciones y es recomendable conocerlas...

Buena suerte, y espero comentarios.




Codigo:--------------------------------------------------------------------------------
#include <16F876A.h>
#use delay(clock=4000000)  //Oscilador de 4Mhz
#fuses XT,NOWDT,NOPROTECT


#include <libreria_sht11_trelles.c>  //funciones de escritura y lectura del registro y medida de Tª y humedad en el sht11
#include <lcd.c> //funciones para gestionar el lcd





  //declaracion de variables para la medicion del sht11
typedef union
  {  unsigned int i;
     float f;
  } valor;

///variables globales
valor humedad,temperatura;   //variables de tipo valor para almacenar tº y humedad

void main(void)
{

  unsigned char error,checksum;
  unsigned int i;

 
        //medida sensor digital
        conexion_al_reset();
        while(1)
        {        

        error=0;
        error+=medicion((unsigned char*) &humedad.i,&checksum,HUMI); //si existe algun error sera almacenado
        error+=medicion((unsigned char*) &temperatura.i,&checksum,TEMP);

        if(error!=0)
           conexion_al_reset();
        else
           {
              humedad.f=(float)humedad.i;       //casting de entero a float para la funcion calculos_sht11
              temperatura.f=(float)temperatura.i;
              calculos_sht11(&humedad.f,&temperatura.f);

              lcd_gotoxy(1,1);
              printf(lcd_putc,"Tª2:%5.1fC humi:%5.1f%%\n",temperatura.f,humedad.f);


               delay_ms(600);

           }


        }


}

--------------------------------------------------------------------------------


La liberia


Codigo:--------------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//       FUNCIONES PARA EL CALCULO DE HUMEDAD Y TEMPERATURA DEL SHT11
//
//       Adaptacion de Oshow del codigo de ejemplo del sensor
//          SHT11 de sensirion, realizado con el compilador KEIL para
//          un microcontrolador 8051.
//
//                   Adaptado para compilador PCW de CCS
//
//
//
//
////////////////////////////////////////////////////////////////////////////////


#bit DATOS = 0x05.2        //definicion de los bits del sht11 datos en RA2
#bit SCK = 0x05.1          //sck en RA1


//Estos defines se pueden simplificar en lugar de tener 3 parejas de defines

#define noACK 0
#define ACK 1
/*
#define CALENTADOR_ON 1
#define CALENTADOR_OFF 0

#define RESOLUCION_14_12_BITS 0
#define RESOLUCION_12_8_BITS 1
*/


//       PROTOTIPOS DE LAS FUNCIONES

char escribir_byte(unsigned char valor);
char leer_byte(unsigned char ack);
void inicializacion(void);
char reset(void);
void conexion_al_reset(void);
char leer_registro_de_estado(unsigned char *p_valor, unsigned char *p_checksum);
char escribir_registro_de_estado(unsigned char *p_valor);
char medicion(unsigned char *p_valor, unsigned char *p_checksum, unsigned char modo);
void calculos_sht11(float *p_humedad ,float *p_temperatura);
//float calculo_rocio(float h,float t);
//char calentador_sht11(byte onoff);
//char resolucion_de_capturas(byte res);


////////////////////////////////////////////////////////////////////////////////
//    Direcciones hexadecimales para escribir y leer en el sensor.
////////////////////////////////////////////////////////////////////////////////

#define STATUS_REG_W 0x06
#define STATUS_REG_R 0x07
#define MEASURE_TEMP 0x03
#define MEASURE_HUMI 0x05
#define RESET 0x1E

enum {TEMP,HUMI}; //tambien podemos hacer defines


////////////////////////////////////////////////////////////////////////////////
//    Escribe un byte en el sensor y chequear si es reconocido
////////////////////////////////////////////////////////////////////////////////
char escribir_byte(unsigned char valor)
{
  unsigned char i,error=0;

     for (i=0x80;i>0;i/=2)
        {
           if (i & valor)
             DATOS=1;
           else
              DATOS=0;
              SCK=1;

           delay_us(5);

           SCK=0;
        }

     DATOS=1;
     SCK=1;
     error=DATOS;
     SCK=0;

  return error;
}


////////////////////////////////////////////////////////////////////////////////
//    Lee un byte en el sensor y da el reconocimeinto si ack es igual a 1
////////////////////////////////////////////////////////////////////////////////
char leer_byte(unsigned char ack)
{
     unsigned char i,valor=0;

        DATOS=1;

        for (i=0x80;i>0;i/=2)
           {
              SCK=1;

              if (DATOS)
                 valor=(valor | i);
                 SCK=0;
             }

        DATOS=!ack;
        SCK=1;

        delay_us(5);

        SCK=0;
        DATOS=1;

  return valor;
}

////////////////////////////////////////////////////////////////////////////////
//Rutina de inicializacion del sensor, utilizar despues del reset.
////////////////////////////////////////////////////////////////////////////////
// Genera un comienzo de trasmision.
//       ______         _______
// DATOS:      |_______|
//            ___     ___
// SCK :  ___|   |___|   |_____
////////////////////////////////////////////////////////////////////////////////

void inicializacion(void)
{
  DATOS=1;
  SCK=0;

  delay_us(2);

  SCK=1;

  delay_us(2);

  DATOS=0;

  delay_us(2);

  SCK=0;

  delay_us(5);

  SCK=1;

  delay_us(2);

  DATOS=1;

  delay_us(2);

  SCK=0;
}

////////////////////////////////////////////////////////////////////////////////
//Reseteo del sensor; linea de datos a 1 seguido de 9 ciclos de reloj y de
//  la funcion inicializacion()
////////////////////////////////////////////////////////////////////////////////
//
//        _____________________________________________________           ________
// DATA:                                                       |_________|
//          _    _    _    _    _    _    _    _    _        _____     _____
// SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______|     |___|     |___
//
////////////////////////////////////////////////////////////////////////////////

void conexion_al_reset(void)
{
  unsigned char i;

  DATOS=1;
  SCK=0;

     for(i=0;i<9;i++)
        {
           SCK=1;
           delay_us(2);
           SCK=0;
           delay_us(2);
        }

  inicializacion();
}

////////////////////////////////////////////////////////////////////////////////
//       Resetea el sensor
////////////////////////////////////////////////////////////////////////////////
char soft_reset (void)
{
     unsigned char error=0;

        conexion_al_reset();
        error+=escribir_byte(RESET);

     return error;
}

////////////////////////////////////////////////////////////////////////////////
//       Lectura del registro de estado con checksum de 8 bits
////////////////////////////////////////////////////////////////////////////////

char leer_registro_de_estado(unsigned char *p_valor, unsigned char *p_checksum)
{

  unsigned char error=0;

     inicializacion();
     error=escribir_byte(STATUS_REG_R);
     *p_valor=leer_byte(ACK);
     *p_checksum=leer_byte(noACK);


  return error;
}

////////////////////////////////////////////////////////////////////////////////
//Escribimos en el registro de estado con un checksum de 8 bits
////////////////////////////////////////////////////////////////////////////////

char escribir_registro_de_estado(unsigned char *p_valor)
{
  unsigned char error=0;


        inicializacion();

        error+=escribir_byte(STATUS_REG_W);
        error+=escribir_byte(*p_valor);

  return error;
}

////////////////////////////////////////////////////////////////////////////////
// Realiza la medicion de temperatura y humedad con checksum incluido
//    Todavia no es la medicion real, se debe hacer la compensacion
////////////////////////////////////////////////////////////////////////////////

char medicion(unsigned char *p_valor, unsigned char *p_checksum, unsigned char modo)
{
  unsigned error=0;
  unsigned long i;


     inicializacion(); //transmission start


        switch(modo)
        {
           case TEMP : error+=escribir_byte(MEASURE_TEMP); break;
           case HUMI : error+=escribir_byte(MEASURE_HUMI); break;
           default : break;
        }

        for (i=0;i<65535;i++)
           if(DATOS==0)
              break;

           if(DATOS) error+=1;

           *(p_valor) =leer_byte(ACK);
           *(p_valor+1)=leer_byte(ACK);
           *p_checksum =leer_byte(noACK);


  return error;
}

////////////////////////////////////////////////////////////////////////////////
//    Calculo de la temperatura en ºC y humedad en %
//       Entrada proviniente del sensor:
//          Humedad - 12 bits (por defecto)
//          Temperatura - 14 bits (por defecto)
//       Salida hacia el LCD:
//          Humedad - RH%
//          Temperatura - ºC
////////////////////////////////////////////////////////////////////////////////

void calculos_sht11(float *p_humedad ,float *p_temperatura)
{
  const float C1=-4.0;
  const float C2= 0.0405;
  const float C3=-0.0000028;
  const float T1=0.01;
  const float T2=0.00008;
  float rh;
  float t;
  float rh_lin;
  float rh_true;
  float t_C;

  rh=*p_humedad;
  t=*p_temperatura;


     t_C=t*0.01 - 40;
     rh_lin=C3*rh*rh + C2*rh + C1;
     rh_true=(t_C-25)*(T1+T2*rh)+rh_lin;

        if(rh_true>100)
           rh_true=100;

        if(rh_true<0.1)
           rh_true=0.1;

     *p_temperatura=t_C;
     *p_humedad=rh_true;
}



/////////////REVISAR ESTAS FUNCIONES, OJO!!!!ESTAN SIN REVISAR//////////////////
////////////////////////////////////////////////////////////////////////////////
//       Funciones que se pueden utilizar a deseo del usuario
//          Para utilizarlas, quitar los comentarios.
////////////////////////////////////////////////////////////////////////////////
//Funcion para el calculo del rocio. Para utilizarla, incluir libreria matematica
// #include <math.h> debido a que se usa un logaritmo
////////////////////////////////////////////////////////////////////////////////

/*float calculo_rocio(float h,float t)
{
  float logEx,punto_rocio;


     logEx=0.66077+7.5*t/(237.3+t)+(log10(h)-2);
     punto_rocio = (logEx - 0.66077)*237.3/(0.66077+7.5-logEx);

  return punto_rocio;
}


////////////////////////////////////////////////////////////////////////////////
//       Funcion para activar el calentador del sht11
//    Esta funcion activa el calentador del sensor, el sensor
//       se "autocalienta" unos 5ºC
////////////////////////////////////////////////////////////////////////////////

char calentador_sht11(byte onoff)
{
  byte valor, checksum,
  char error=0;


  conexion_al_reset();
  error += leer_registro_de_estado(&valor, &checksum);
  conexion_al_reset();

  if (!error && (((valor>>2) & 0x01) != onoff))
  {
    onoff?bit_set(valor,2):bit_clear(valor,2);
    error += escribir_registro_de_estado(&valor);
  }

  return error;
}

////////////////////////////////////////////////////////////////////////////////
//             Eleccion de resolucion en las medidas
//                Por defecto: 14 bits temepratura y 12 bits humedad
//                   Opcion:  12 bits temperatura y 8 bits humedad
////////////////////////////////////////////////////////////////////////////////

char resolucion_de_capturas(byte res)
{  //eleccion de resolucion

  byte valor, checksum;
  char error=0;

  conexion_al_reset();
  error += escribir_registro_de_estado(&valor, &checksum);
  conexion_al_reset();

  if (!error && ((valor & 0x01) != res))
  {
    res?bit_set(valor,0):bit_clear(valor,0);
    error += escribir_registro_de_estado(&valor);
  }

  return error;
}
*/

--------------------------------------------------------------------------------


Biraz uzun oldu ama kusura bakmayın, aslında sitede ufak dosyaları upload etmek için bir özellik olsaydı daha iyi olurdu. c dosyalarını yüklerdik. Sayfalarca kod görünmezdi.

ete

@Erol,

Her şeyden önce benim taktik işe yaradı sensörü almak için değilmi?.

Verdiğin ifadeleri ben program örneğinde kullandım. Hesabın başka yolu yok zaten. Dene bakalım. Bu arada Speedyx program örneklerini yığmış zaten düşünmeye gerek yok her şey hazır sanırım.

Kolay Gelsin.
ETE
Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

Petek

Alıntı yapılan: "Erol"@ete
SHT11'i bugun aldım.
Datasheet te sıcaklık ve bagıl nemin hesabında kullanılmak üzere ifadeler verilmiş. Bunları kullanacagim CCS ile...
12/8 bit çözünürlükte çalışacağım.

Temp= -40+0.04*SOT;
RH_linear = -4+0.648*SORH - 0.00072*(SORH*SORH) ;
RH_true = (Temp-25)*(0.01+0.00128*SORH) + RH_linear;

ifadesini kullanmayı düşünüyorum. Özellikle bahsetmek istediğin birşey var mı???

SHT11 web sayfasındaki örnek kod Keil C için ve CCS ye çok kolay uyarlanabiliyor. Benim CCSyi öğrenirken ilk yaptığım bu uyarlama idi. Speedyx in gönderdiği ile neredeyse aynı. Yalnız programı derlediğimde 628'e sığmayacak kadar büyük kod üretmişti. 877 için ise yanlış hatırlamıyor isem CCS 3.9 kb lık bir kod üretmişti. (CCS burada Keil C ye kıyasla daha küçük kod üretti).

CCS de biraz optimizasyon yaparak 628'e sığdırılabilir diye düşünüyorum. Sorun 32 bitlik aritmetik işlemlerin çok yer tutması. Bu konuda integer aritmetiği kullanılırsa daha kompak kod üretilebilir. Benzer bir uygulama (sondaki hesaplama * yada sizin belirrtiğiniz işlemler *  hariç) Jal ile 1.5 kb civarında kod üretilerek yapılmıştı. Integer tabalı (sadece integer değişkenler ile) FP aritmetiği yapmak biraz zahmetli ama kod alanınız sınırlı ise denemeye değer. Jallist files alanında "Eur's file" altında kaynak kodları bulabilirsiniz.

Kolay gelsin.
“Önyargıları yıkmak atomu parçalamaktan zordur” A.Einstein

SpeedyX

Kodların içinde gereksiz fonksiyonlar da var (özel kullanım için sanırım.), onlarıda silince 3kb gibi abartı bir kod ortaya çıkmaz sanıyorum. Deneyin, bizide bilgilendirin. SHT11'im olsa keşke, bende denerdim. ;)
Saygılar.

Erol YILMAZ

Yapmak istedigim sadece okumak değil ayni zamanda kontrol oldugu icin  fonksiyonlardan faydalanabilirim. Onun icin en kucuk noktasina kadar bilmem gerekiyor.

Kontrola iliskin ifadelerin de matematiksel olarak yer tutacagini tahmin edip devremi 40 pinli PIC baglantisina gore yapiyorum. 16F877 veya 18F452 calisacagim.

Program alani ve hesap zamani konusunda SIKINTIM yok. Float islem yaptiracagim. (Israf olmaz değil mi? :) )

bir dolabin isitma, sogutma, buhar kaynagi isitma, buhar ufleme fani kontrolu olacak sonunda, Yani sonucta NEM kontrolu :)

Bu arada SHT11 in Turkiye de en uygun fiyati nedir ?
Piyasada bulunmayip, ise yarayan birsey old. kesfeden uyaniklar istedigi fiyati vermeye calisiyor. Yurtici fiyatlari belirtelim lutfen...

Hepinize teşekkürler...

Petek

Erol,
877 kullanacaksan, CCS için verilmiş olan programı aynen kullan.

SHT11 ile ilgili benim bir sorunum var idi. Eminim aynı sorun sizin de karşınıza çıkacaktır. Zira nem kontrolü de yapacağınızı belirtiyorsunuz. SHT11 üzerinde su yoğunlaşması olunca bu durumda ölçeceği sıcaklık değeri doğru olmayacaktır. Bunu gidermek için adamlar içerisine çok küçük bir ısıtma direnci eklemişler. SHT11 tarifnamesinde (datasheet) Isıtma süresince örnekleme sayısı saniyede 3 ü geçmesin deniyor.

Sorun 1: Isıtıcının çalıştırılmasını gerektirecek şartın tespit edilmesi,
Sorun 2: (ben oda sıcaklığında bunu yaptığım için belki yanlış yorumluyor olabilirim) Isıtıcı çalıştığı sürece okunan sıcaklık değeri sürekli artış gösteriyor.
Sorun 3: Isıtıcının durdurulması şartı neye göre tespit edilecek.

Bu konuda tecrübesi olan varsa birlikte kafa yoralım ve sağlıklı bir ölçüm algoritması geliştirelim.
“Önyargıları yıkmak atomu parçalamaktan zordur” A.Einstein

ete

Arkadaşlar,

Aynı konu üzerinde daha önce epeyce kafa yorduğum için bildiklerimi aktarayım istedim.
Konu direkt olarak havanın nem alma kaabiliyeti ile alakalı.
Ortalama 40 derece sıcaklıktaki 1 m3 hava yaklaşık 50 gr. su veya subuharını absorbe edebilmektedir. Kapalı ortamda bu sıcaklıktaki 1m3 havaya daha fazla su veremezsiniz. Sıcaklığı 70 dereceye çıkartırsanız absorbe edilecek su miktarı 200 gr seviyesine yükselir. İşte burası çok önemli. Hava miktarı değişmedi sadece sıcaklık arttı. Şimdi 70 derece sıcaklıktan tekrar 40 derece sıcaklıklara düşerseniz hava içindeki 200 gr sudan 150 gr mı mutlaka yoğunlaşacaktır. Zira bu sıcaklıkta 1m3 hava ancak 50 gr su tutabilmektedir. Normal şartlarda çalıştığınız ortam şayet maksimum rutubet derecelerine yakın değerler taşımıyor ise (%95-%100 arası) ve ortamda sıcaklık yükseliş ve azalışı çok farklı değerler taşımıyor ise sensörde su yoğunlaşması olmaz. Bu yüzden Sensirion fevkalade durumlar için sensöre bir ısıstıcı yerleştirmiştir. Fevkalade durum da aşırı sıcaklık düşüşlerinin yaşandığı durumlarda ortaya çıkmaktadır.
Ben önceden ağaç papel kurutma fırınlarında rutubete göre otomatik baca kontrölü yapan bir sistem geliştimiştim. Bu çalışmayı o zaman yaptım. Konuyla ilgili bazı hesap örnekleri ve en önemlisi havanın nem alma kaabiliyetini sıcaklıklara göre gösteren bir tablo hazırladım. Aslında söz konusu tablo galiba adı Bollman olan birisi tarafından 0-100 derece arası sıcaklıklar için yapılmış ben bu tabloyu 0-180 derece arası için yeniden yaptım. Belki işinize yarar diye aşağıdaki linke upload ettim bu dosyayı.
http://rapidshare.de/files/2540009/ISI-NEM.rar.html

Benim düşünceme göre, ortamda çok fazla sıcaklık düşüşü yaşanır ise ve rutubet seviyesi %90 ların üzerinde ise sensör ısıtıcısını çalıştırmak gerekir. Süre olarak yaklaşık 500 ms lik sürelerle deneme yapılmalı gerekirse süre uzatılmalıdır. Tabiiki sensör ısıtılınca hali ile yaklaşık 5 derecelik artışlar olacaktır. Bu durumda sensör ısıtıcısının çalıştırıldığı ve durdurulduğu andan hemen sonra yapılacak ısı ölçümlerinden 5 derece çıkartılmalı veya yeterince beklendikten sonra ölçüm yapılmalıdır.


Kolay Gelsin
ete
Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

Petek

Ete mesajını görmemişim. Forumun "son girişinizden bu yana gönderilenler" linkinde bir sorun var galiba.

Gönderdiğiniz yazıyı ve linkteki dokümanı okudum. Güzel bir analiz yapmışsınız.

Termodinamikten bildiğim kadarıyla yoğunlaşan su buharlaştırılırken sıcaklık buharlaşma bitinceye kadar sabit kalır (aktarılacak ısı: (su kütlesi)*hfg) . Aynı şekilde yoğuşma sırasında da sıcaklık sabit kalır. Sizin bahsettiğiniz şey bizim klasik termo uygulamalarımızdan biraz farklı. Model değişik çünkü. Ulaşılması zor bir pozisyonda görev yapan Meteoroloji mühendisi bir arkadaşım var. Ona da bir danışayım. Yoğuşma ve buharlaştırmadaki modelleme nasıl. Eğer sıcaklık değişmiyorsa algoritmayı kolay kurabiliriz.


Sizin kurutma fırını ile ilgili bir yorum getireyim. Nem oranı yükselmiş havayı doğrudan bacadan tahliye etmek yerine içerdiği ısıyı geri kazanmak için bir hava eşanjöründen geçirerek tahliye etseniz içeri giren havayı da ısıtmış olursunuz. Yada fırın içerisindeki nemi almak için yine eşanjör kullanarak havanın bir miktarını soğutup (bu arada yoğunlaşan suyu dışarı alarak) soğuyan (kurutulmuş) havayı tekrar fırına gönderebilirsiniz. Kullanacağınız eşanjörde akış ters yönlü olacak. [çok soğuk bölgelerde yaşayan uzun bacaklı kuşların bacakları buz gibi suyun içerisindedir ancak bacaklara kan taşıyan ve bacaklardan kanı geri vücudataşıyan damarlar bitişik ve ters akıştan dolayı kuşların vücut ısıları kaybolmuyor.]
“Önyargıları yıkmak atomu parçalamaktan zordur” A.Einstein

ete

@Petek,

Fırınlarda bahsini ettiğin uygulama yapılıyor. Ancak yatırım maliyeti yüksek olduğu için ve kazanda yakıt olarak artıklar yakıldığı için çok fazla tercih edilmiyor. Anlayacağın yakıt bedava olduğu için sürekli dışarıdan kuru hava üretmek daha ucuza mal oluyor.

ETE
Bilgi hazinedir paylaştıkça büyür.            http://etepic.com