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