From Swordfish Wiki

SwordfishUser: SensirionSHTxxSensor

New module available for Sensirion (temperature / humidity) sensor, SHTxx family.

Test board : BIGPIC4, MCU PIC18F8520, LCD 2X16, SHT11 sensor connected on PORTC. 4.7 K pull up resistor on Data Pin is necessary.

Available functions

Sub Sensirion_Init(ByRef Port.(Data_Pin) As Bit, ByRef Port.(Clock_Pin) As Bit)
Sub Sensirion_Init_(ByRef Port As Byte, Data_Pin, Clock_Pin As Byte)
Function Sensirion_Get_Temp_Hum(ByRef temperature, humidity As Float) As Boolean
Function Sensirion_Get_Temp_Hum_Dec(ByRef temp_d, hum_d As Integer) As Boolean // result will be multiplied by 100
Function Sensirion_Get_Dew_Point(ByRef temperature, humidity As Float) As Float

For initialization you can choice between Sensirion_Init or Sensirion_Init_

You can download source code from : http://www.microelemente.ro/Swordfish/Sensirion.zip

Example Code

Device = 18F8520
Clock = 40
Config OSC = HSPLL

// some LCD options...
#option LCD_DATA = PORTH.4
#option LCD_RS = PORTH.2
#option LCD_EN = PORTH.3

// import LCD library...
Include "LCD.bas" 
Include "Sensirion"
Include "convert.bas"

Dim NoError As Boolean
Dim temperature, humidity, dew_point As Float
Dim TempA, TempB As Byte
Dim buf As Integer

ADCON0 = 0
CMCON  = $07                    // turn off comparators
ADCON1 = $0F                    // turn off analog inputs
MEMCON.7 = 1                    // disable external memory bus

Cls
//Sensirion.Sensirion_Init(PORTC.1, PORTC.2)  
                                          // Sensirion.Sensirion_Init(Port.(Data Pin), Port.(Clock pin))
                                          // Data an Clock Pin must be at the same Port
                                          // This is a wrong configuration : 
                                          // Sensirion.Sensirion_Init(PORTB.1, PORTD.2) 
Sensirion.Sensirion_Init_(PORTC, 0, 1)    // Sensirion.Sensirion_Init(Port, Data Pin, Clock Pin)
While true
    NoError = Sensirion.Sensirion_Get_Temp_Hum(temperature, humidity)
    If NoError Then
        buf = temperature * 100
        TempA = buf / 100
        TempB = buf Mod 100
        LCD.WriteAt(1,1, " TS = ",DecToStr(TempA,2),".",DecToStr(TempB,2)," ", 223, "C  ")
        buf = humidity * 100
        TempA = buf / 100
        TempB = buf Mod 100
        LCD.WriteAt(2,1, " Rh = ",DecToStr(TempA,2),".",DecToStr(TempB,2)," "," %  ")
        dew_point = Sensirion.Sensirion_Get_Dew_Point(temperature, humidity)       
    Else 
        LCD.WriteAt(1,1, " Error detected ")
        LCD.WriteAt(2,1, " Error detected ")        
    End If
    DelayMS(2000)
Wend

Module Code

{
******************************************************************************
*  Name    : Sensirion.BAS                                                   *
*  Author  : Medrea Florin Andrei                                            *
*  Notice  : Copyright (c) 2007 -YO2LIO-                                     *
*          : All Rights Reserved                                             *
*  Date    : 9/26/2007                                                       *
*                                                                            *
*  Copyright Notice                                                          *
*                                                                            *
*  This library For the SHT temperature And humidity sensors is based on the *
*  application datasheet Sample Code humidity sensor SHTxx from Sensirion.   *
******************************************************************************
}
Module Sensirion

Include "math"
Include "system"

Const NoACK As Byte = 1,
      ACK As Byte = 0,
      CMD_STATUS_REG_W As Byte = $06,
      CMD_STATUS_REG_R As Byte = $07,
      CMD_TEMP As Byte = $03,
      CMD_HUMIDITY As Byte = $05,
      CMD_RESET As Byte = $1E

Structure TPin
   Pin As Byte
   PinMask As Byte
End Structure

Structure TPort
   AddrPort As Word
   AddrTRIS As Word
End Structure

Dim SData,SClock As TPin
Dim SPort As TPort
Dim data_h,data_l,data_cksum As Byte

Public Sub Sensirion_Init(ByRef pData As Bit, ByRef pClock As Bit)
    ClrWDT
    DelayMS(100)
    ClrWDT
    SPort.AddrPort = AddressOf(pData)       // get pin address
    SPort.AddrTRIS = SPort.AddrPort + 18    // get pin TRIS address
    SData.Pin = BitOf(pData)                // get pin number
    SData.PinMask = Not SData.Pin           // create pin number mask
    SClock.Pin = BitOf(pClock)              // get pin number
    SClock.PinMask = Not SClock.Pin         // create pin number mask  
    FSR2 = SPort.AddrPort
    INDF2 = INDF2 Or SData.Pin              // set pin
    DelayUS(10)
    INDF2 = INDF2 And SClock.PinMask        // clear pin
    DelayUS(10)
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 And SData.PinMask         // make output SData
    DelayUS(10)
    INDF2 = INDF2 And SClock.PinMask        // make output SClock 
End Sub

Public Sub Sensirion_Init_(ByRef pPort As Byte, pData, pClock As Byte)
    ClrWDT
    DelayMS(100)
    ClrWDT
    SPort.AddrPort = AddressOf(pPort)       // get port address
    SPort.AddrTRIS = SPort.AddrPort + 18    // get port TRIS address
    SData.Pin = 1 << pData                  // get pin number
    SData.PinMask = Not SData.Pin           // create pin number mask
    SClock.Pin = 1 << pClock                // get pin number
    SClock.PinMask = Not SClock.Pin         // create pin number mask  
    FSR2 = SPort.AddrPort
    INDF2 = INDF2 Or SData.Pin              // set pin
    DelayUS(10)
    INDF2 = INDF2 And SClock.PinMask        // clear pin
    DelayUS(10)    
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 And SData.PinMask         // make output SData
    DelayUS(10)
    INDF2 = INDF2 And SClock.PinMask        // make output SClock 
End Sub

Sub Sensirion_Start()
    FSR2 = SPort.AddrPort
    INDF2 = INDF2 Or SData.Pin              // set pin SData
    DelayUS(10)
    INDF2 = INDF2 And SClock.PinMask        // clear pin SClock
    DelayUS(10)
    INDF2 = INDF2 Or SClock.Pin             // set pin SClock
    DelayUS(10)
    INDF2 = INDF2 And SData.PinMask         // clear pin SData
    DelayUS(10)
    INDF2 = INDF2 And SClock.PinMask        // clear pin SClock
    DelayUS(10)    
    INDF2 = INDF2 Or SClock.Pin             // set pin SClock
    DelayUS(10)    
    INDF2 = INDF2 Or SData.Pin              // set pin SData
    DelayUS(10)
    INDF2 = INDF2 And SClock.PinMask        // clear pin SClock    
    DelayUS(10)
End Sub

Function Sensirion_Get_Byte(ack_ As Byte) As Byte
Dim i,buf As Byte
    buf = 0
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 Or SData.Pin              // make input SData
    DelayUS(10)
    FSR2 = SPort.AddrPort
    i = 0
    While i < 8
        INDF2 = INDF2 Or SClock.Pin         // set pin SClock
        DelayUS(10)        
        If (INDF2 And SData.Pin) > 0 Then
            buf = buf Or 1
        End If
        INDF2 = INDF2 And SClock.PinMask    // clear pin SClock
        DelayUS(10)
        Inc(i)
        If i < 8 Then buf = buf << 1 End If
    Wend
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 And SData.PinMask         // make output SData
    DelayUS(10)
    FSR2 = SPort.AddrPort
    If ack_ = 0 Then 
        INDF2 = INDF2 And SData.PinMask     // clear pin SData
    Else
        INDF2 = INDF2 Or SData.Pin          // Set pin SData            
    End If
    DelayUS(10)    
    INDF2 = INDF2 Or SClock.Pin             // set pin SClock
    DelayUS(10)        
    INDF2 = INDF2 And SClock.PinMask        // clear pin SClock
    DelayUS(10)  
    result = buf
End Function

Function Sensirion_Put_Byte(data As Byte) As Boolean
Dim i As Byte
    result = false
    FSR2 = SPort.AddrPort
    i = 0
    While i < 8 
        If (data And 128) > 0 Then
            INDF2 = INDF2 Or SData.Pin      // Set pin SData
        Else
            INDF2 = INDF2 And SData.PinMask // clear pin SData     
        End If
        DelayUS(10)
        INDF2 = INDF2 Or SClock.Pin         // set pin SClock
        DelayUS(10)        
        INDF2 = INDF2 And SClock.PinMask    // clear pin SClock
        DelayUS(10)
        Inc(i)
        If i < 8 Then data = data << 1 End If        
    Wend
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 Or SData.Pin              // make input SData
    DelayUS(10)
    FSR2 = SPort.AddrPort
    INDF2 = INDF2 Or SClock.Pin             // set pin SClock
    DelayUS(10)        
    If (INDF2 And SData.Pin) = 0 Then
        result = true
    End If
    INDF2 = INDF2 And SClock.PinMask        // clear pin SClock
    DelayUS(10)
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 And SData.PinMask         // make output SData
    DelayUS(10)
    FSR2 = SPort.AddrPort   
    INDF2 = INDF2 And SData.PinMask         // clear pin SData
End Function

Sub Sensirion_Reset()
Dim i As Byte
    FSR2 = SPort.AddrPort
    INDF2 = INDF2 Or SData.Pin              // set pin SData
    DelayUS(10)
    INDF2 = INDF2 And SClock.PinMask        // clear pin SClock
    DelayUS(10)
    i = 0
    While i < 9
        INDF2 = INDF2 Or SClock.Pin         // set pin SClock
        DelayUS(10)        
        INDF2 = INDF2 And SClock.PinMask    // clear pin SClock
        DelayUS(10)
        Inc(i)
    Wend    
    Sensirion_Start
End Sub

Function Sensirion_Soft_Reset() As Boolean
    Sensirion_Reset
    result = Sensirion_Put_Byte(CMD_RESET)
End Function

Function Sensirion_Read_Status(ByRef sensirion_status, sensirion_cksum As Byte) As Boolean
    Sensirion_Reset
    result = Sensirion_Put_Byte(CMD_STATUS_REG_R)
    sensirion_status = Sensirion_Get_Byte(ACK)
    sensirion_cksum = Sensirion_Get_Byte(NoACK)
End Function

Function Sensirion_Write_Status(data As Byte) As Boolean
Dim result1 As Boolean
    Sensirion_Reset
    result1 = Sensirion_Put_Byte(CMD_STATUS_REG_W)
    result = result1 And Sensirion_Put_Byte(data)
End Function

Function Sensirion_Get(data As Byte, ByRef result_h,result_l,sensirion_cksum As Byte) As Boolean
Dim i As Word
    result = false
    Sensirion_Reset
    Select data 
        Case CMD_TEMP result = Sensirion_Put_Byte(CMD_TEMP)
        Case CMD_HUMIDITY result = Sensirion_Put_Byte(CMD_HUMIDITY)
    Else Exit
    End Select
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 Or SData.Pin              // make input SData
    DelayUS(10)
    FSR2 = SPort.AddrPort
    i = 0
    Repeat
        ClrWDT        
        If (INDF2 And SData.Pin) = 0 Then
            Break
        End If
        Inc(i)
        DelayMS(1)        
    Until i > 500
    If i > 500 Then
        result = false
        Exit
    End If    
    FSR2 = SPort.AddrTRIS
    INDF2 = INDF2 And SData.PinMask         // make output SData
    DelayUS(10)
    FSR2 = SPort.AddrPort   
    INDF2 = INDF2 And SData.PinMask         // clear pin SData
    DelayUS(10)
    result_h = Sensirion_Get_Byte(ACK)
    result_l = Sensirion_Get_Byte(ACK)
    sensirion_cksum = Sensirion_Get_Byte(NoACK)
End Function

Public Function Sensirion_Get_Temp_Hum(ByRef temp, hum As Float) As Boolean
Const T1 As Float = 0.01,
      T2 As Float = 0.00008,
      C1 As Float = -4.0,
      C2 As Float = 0.0405,
      C3 As Float = -0.0000028
Dim rh_lin, rh_true As Float
Dim result1 As Boolean
Dim buf As Word
    result1 = Sensirion_Get(CMD_TEMP, data_h, data_l, data_cksum)
    buf.Byte0 = data_l
    buf.Byte1 = data_h    
    temp = (buf * 0.01) - 40.0
    result = result1 And Sensirion_Get(CMD_HUMIDITY, data_h, data_l, data_cksum)
    If result = false Then
        temp = 0
        hum = 0
        Exit
    End If
    buf.Byte0 = data_l
    buf.Byte1 = data_h      
    rh_lin = (C3 * buf * buf) + (C2 * buf) + C1
    rh_true = ((temp - 25.0) * (T1 + T2 * buf)) + rh_lin
    If rh_true > 99.9 Then rh_true = 99.9 End If
    If rh_true < 0.0 Then rh_true = 0.0 End If
    hum = rh_true
End Function

Public Function Sensirion_Get_Temp_Hum_Dec(ByRef temp_d, hum_d As Integer) As Boolean
Const C1d As LongInt = -40000,
      C2d As LongInt = 405,
      C3d As LongInt = -28
Dim rh_lin, rh_true As LongInt
Dim result1 As Boolean
Dim buf As Word
  result1 = Sensirion_Get(CMD_TEMP, data_h, data_l, data_cksum)
  temp_d.Byte0 = data_l
  temp_d.Byte1 = data_h 
  temp_d = temp_d - 4000
  result = result1 And Sensirion_Get(CMD_HUMIDITY, data_h, data_l, data_cksum)
  If result = false Then
    temp_d = 0
    hum_d = 0
    Exit
  End If
  buf.Byte0 = data_l
  buf.Byte1 = data_h 
  rh_lin = (((C3d * buf * buf) / 1000) + (C2d * buf) + C1d) / 100
  rh_true = (((temp_d - 2500) * buf) / 12500) + rh_lin
  If rh_true > 9999 Then rh_true = 9999 End If
  If rh_true < 0 Then rh_true = 0 End If
  hum_d = Integer(rh_true)
End Function

Public Function Sensirion_Get_Dew_Point(ByRef temp, hum As Float) As Float
Dim k As Float
    k = ((log10(hum) - 2.0) / 0.4343) + ((17.62 * temp) / (243.12 + temp))
    result = (243.12 * k) / (17.62 - k)
End Function
Retrieved from https://www.sfcompiler.co.uk/wiki/pmwiki.php?n=SwordfishUser.SensirionSHTxxSensor
Page last modified on November 05, 2007, at 02:26 PM