Measuring Relative Humidity using a Honeywell HIH-3610 Sensor

and Dallas DS2438 Battery Monitor

with a PC (Windows) Using Liberty Basic

copyright, Peter H Anderson, Baltimore, MD, Feb, '05


(Feb 25, '05). This is currently being developed.

Introduction.

The Honeywell HIH-3610 is a popular relative humdity to DC voltage sensor. True relative humidity varies as a function of temperature and the Dallas DS2438 battery monitor which is capable of measuring temperature and performing an A/D measurement is an ideal companion to perform relative humidity meeasurements. I offer an assembled arrangement as the RH #166 RH Sender Module. Other similar arrangements are available and are discussed on the web.

The advantage in using the DS2438 is that it is a member of the Dallas 1-W family and thus many may be accommodated on one or two Dallas 1-W networks.

I offer a number of designs which are controlled via an RS232 COM port (or a USB to RS232 adaptor) which may be used to interface with the Dallas DS2438, in addition to other Dallas devices. These include the TM #128, IOM #135E, IOM #136 and IOM #142A modules.

This application note discusses Serial RS232 communication between a PC running Windows and these modules using Liberty Basic to perform relative humidity measurements and calculate the dew point. This is illustrated in the context of the TM #128 temperature module followed by a discussion of how this might be modified for use with the other modules.


Program TM128_2.Bas.

Program TM128_2.Bas initiates a measurement sequence each minute by sending any character to the TM #128. The TM #128 then returns the measurement results. An example is used for a brief explanation;

0
00 10 9DD7 26.12
01 10 BD53 26.12
02 28 3C2C 26.32
03 22 5BFC 26.43
10 10 0C26 27.18
11 10 0AD7 27.25
12 26 09CE 27.18 2.55 5.03
The first line of every response is the state of the TTL input on the TM #128 unit. The subsequent lines are the result of measurements made on the two Dallas 1-wire devices. The first digit of field 1 indicates the run. The second digit is a sequential number which is assigned as each sensor is found. Field 2 is the Dallas device code (10 - DS18S20, 22 - DS1822, 28 - DS18B20, 26 - DS2438). Field 3 is an abbreviation of the unique serial number assigned by Dallas.

If the device is a temperature sensor (codes 10, 22 or 28) field 4 is the temperature in degrees C. If the device is a DS2438 battery monitor, fields 4, 5 and 6 are the temperature, Vad and Vdd.

On initiating the sequence, the program writes the descriptor "DT" to the text file. The program reads the date and time off the PC clock and writes this to the file.

On receiving the state of the TTL input, the descriptor "IN" is written to the file followed by the state, either 0 or 1.

As the result for each Dallas device is sent, the program determines if the device is a temperature sensor, and if so, writes the descriptor "TMP" to the file, followed by the temperature.

If the device is a DS2438, the program calculates the relative humidity and the dew point and writes the descriptor "RH" to the file followed by the temperature, the relative humidity and the dewpoint.

Thus, a sample;

DT 02/23/05 14:16:19
IN 0
TMP 00  10 6A0B 21.31
TMP 01  10 9DD7 21.31
TMP 02  22 5BFC 21.68
RH 03  26 1C01 20.75 35.1914613 9.3989388
(Note that this sequence was not for the same configuration noted above).


TM128_2.Bas

' TM128_2.Bas (Liberty Basic)
'
' Illustrates an interface with temperature module TM #128.
'
' Initiates a measurment sequence each minute.

' Fetches the time and date off the system clock and writes to a text file with a leading
' "DT" (date-time").  Then reads the status of the single input and writes the state to
' the test file with a leading "IN" indicator.
'
' Then reads the Dallas devices on both Dallas runs.
'
' If a device is a DS18S20 / DS18B20  / DS1822 temerature sensor, the value is read and the
' device number, Dallas device code, an abbreviated Dallas serial number and the temperature
' in degress C is writtent to the  text file with the leading "TMP" indicator.
'
' If the device is a DS2438, it is assummed that this is interfaced with a Honeywell HIH-3610.  The
' temperature. Vad and Vdd are read.  The relative humidity and dew point are calculated.  The
' device number, Dallas device code, the abbreviated Dallas serial number, the temperature, relative
' humidity and dewpoint are written to the file with the leading "RH" indicator.
'
' A typical measurement sequence;
'
' DT 02/23/05 14:16:19
' IN 0
' TMP 00  10 6A0B 21.31
' TMP 01  10 9DD7 21.31
' TMP 02  22 5BFC 21.68
' RH 03  26 1C01 20.75 35.1914613 9.3989388
'
' This logging of data continues until a key is pressed.  The file is opened for reading and all data
' is displayed to the terminal.
'
' copyright, Peter H Anderson, Baltimore, MD, Feb, '05

    Com = 16384     ' size of buffer

    ' define a box
    nomainwin

    WindowWidth = 400
    WindowHeight = 300
    texteditor #window.te, 0, 0, 391, 254     'The handle for our texteditor is #window.te
    graphicbox #window.gb, 800, 1, 10, 10
    open "kb" for window as #window           'The handle for our window is #window
    print #window.gb, "when characterInput [getChar]"   'When the user presses a key go to [getChar]
    print #window, "trapclose [quit]"    'When the user closes our terminal window, go to [quit]
    print #window.te, "!autoresize";   'Tell the texteditor to resize with the terminal window
    print #window, "font courier_new 9";

[top]
    oncomerror [closecomm]  ' not sure if this works
    open "com2:9600,n,8,1, cs0, ds0" for random as #commhandle

    call pause 500  ' wait for unit to settle

    open "d:\data.txt" for output as #log ' open the file
    close #log

    T$ = time$()
    Delimiter$ = ":"
    TimeoutMinute = Val(ExtractField$(T$, Delimiter$, 2))


[again]
    TimeoutMinute = TimeoutMinute + 1
    If TimeoutMinute >= 60 Then
        TimeoutMinute = TimeoutMinute - 60
    End If

    d$ = date$("mm/dd/yy")
    t$ = time$()

    open "d:\data.txt" for append as #log   ' date stamp
    print #log, "DT "; d$; " "; t$
    close #log
    print #window.te, "DT "; d$; " "; t$

    print #commhandle, "!"  ' send any character

    x = 0
    while x = 0       ' loop until either a string is received or timeout

       DataLine$ = GetLine$(NumChars) ' NumChars is passed by reference

       select case

          case NumChars = -30000
              print #window.te, "timeout"
              exit while

          case (NumChars = 1)
              if DataLine$ = ">" then
                  print #window.te, DataLine$
                  exit while
              end if

              if (DataLine$ = "0" OR DataLine$ = "1") Then
                  InState = Val(DataLine$)
                  open "d:\data.txt" for append as #log
                  print #log, "IN "; InState       ' and write it to the file
                  close #log
                  print #window.te, "IN "; InState
              else
                  open "d:\data.txt" for append as #log
                  print #log, "?? "; DataLine$
                  close #log
                  print #window.te, "?? "; DataLine$
              end if

          case (NumChars = 1)
              print #window.te, DataLine$
              ' exit while

          case (NumChars > 2)        ' probably a vaild string

              Delimiter$ = Chr$(32)
              DevNum$ = ExtractField$(DataLine$, Delimiter$, 1)
              DevCode$ = ExtractField$(DataLine$, Delimiter$, 2)
              SerNum$ = ExtractField$(DataLine$, Delimiter$, 3)

              If (DevCode$ = "10" OR DevCode$ = "22" OR DevCode$ = "28") Then
                  TCelcius = Val(ExtractField$(DataLine$, Delimiter$, 4))
                  open "d:\data.txt" for append as #log
                  print #log, "TMP"; DevNum$; "  "; DevCode$; " ";
                  print #log, SerNum$; " "; TCelcius
                  close #log

                  print #window.te, "TMP "; DevNum$; "  "; DevCode$; " ";
                  print #window.te, SerNum$; " "; TCelcius
              End If

              If DevCode$ = "26" Then
                  TCelcius = Val(ExtractField$(DataLine$, Delimiter$, 4))
                  Vad = Val(ExtractField$(DataLine$, Delimiter$, 5))
                  Vref = Val(ExtractField$(DataLine$, Delimiter$, 6))
                  RH = CalcRH(TCelcius, Vad, Vref)
                  DewPoint = CalcDewPoint(TCelcius, RH)

                  open "d:\data.txt" for append as #log
                  print #log, "RH "; DevNum$; "  "; DevCode$; " ";
                  print #log, SerNum$; " "; TCelcius; " "; RH; " "; DewPoint
                  close #log
                  print #window.te, "RH "; DevNum$; "  "; DevCode$; " ";
                  print #window.te, SerNum$; " "; TCelcius; " "; RH; " "; DewPoint
              End If

          case else
              print "Unknown error"   ' probably an overkill
              exit while

        end select

    wend
    do
        print #window.gb, "setfocus"
        scan ' used for check if activity from the keyboard
        T$ = time$()
        Delimiter$ = ":"
        CurrentMinute = Val(ExtractField$(T$, Delimiter$, 2))
    loop until (CurrentMinute = TimeoutMinute)

    goto [again]

[display]
    ' now open the file display the data
    open "d:\data.txt" for input as #log

    while eof(#log) = 0
       line input #log, datain$
       print #window.te, datain$
    wend

    close #log

[Done]
    Goto [Done]

[getChar]

    'Whenever the user presses a key, we go here to process it.
    c$ = Inkey$
    ' print #window.te, "at getChar"
    goto [display]

[closecomm]
     print "Error code: ";ComErrorNumber
     close #commhandle
     goto [top]

function GetLine$(ByRef StatusFlag)

    TimeOutTime = time$("milliseconds")
    TimeOutDate = date$("days")

    TimeOutTime = TimeOutTime + 3000 ' three seconds

    if (TimeOutTime >= 86400000) then
        TimeOutDate = TimeOutDate + 1
        TimeOutTime = TimeOutTime - 86400000
    end if


     DataLine$ = ""
     StatusFlag = 0
     NumChars = 0

     x=0
     while x=0
        if lof(#commhandle) <>0 then
           c$ = input$(#commhandle, 1)
           select case
              case  c$ = ">"
                 DataLine$ = c$
                 StatusFlag = 1 ' prompt
                 exit while

              case c$ = chr$(13)
                 StatusFlag = NumChars
                 exit while

              case c$ = chr$(10)    ' ignore it

              case else
                 DataLine$ = DataLine$ + c$
                 NumChars = NumChars + 1

            end select
        else
           CurrentDate = date$("days")
           CurrentTime = time$("milliseconds")
           If (CurrentTime >= TimeOutTime) AND (CurrentDate >= TimeOutDate) Then
              StatusFlag = -30000
              exit while
           end if
        end if
     wend
     GetLine$ = DataLine$
End Function

Function CalcRH(Tc, Vad, Vref)
     RHRaw = 161.29 * Vad / Vref - 25.8
     RHTrue = RHRaw * (1.0 / (1.0546-0.00216 * Tc))
     CalcRH = RHTrue
End Function

Function CalcDewPoint(RH, Tc)
   EW = exp10(0.6607 + 7.5 * Tc / (237.3 + Tc)) * RH / 100.0
   CalcDewPoint = ((0.6607 - log10(EW)) * 237.3) / (log10(EW) - 8.16077)
End Function

Function exp10(x)
   exp10 = exp(2.303 *x)
End Function

Function log10(x)
   log10 = log(x) / 2.303
End Function

function ExtractField$(Var$, Delimiter$, NumField)

    for Num = 1 to NumField
       Index = FindDelimiter(Var$, Delimiter$)
       LeftStr$ = Left$(Var$, Index - 1) ' everything to the left of the space
       Var$ = Mid$(Var$, Index+1)        ' to the right of the space
       If Num = NumField Then
          exit for
       End If
    next

    ExtractField$ = LeftStr$

end function

function FindDelimiter(Var$, Delimiter$)

    for n = 1 to len(Var$)
       ch$ = Mid$(Var$, n, 1)
       If ch$ = Delimiter$ then
          exit for
       End If
       If ch$ = Chr$(13) then
          exit for
       End If
       If ch$ = Chr$(10) then
          exit for
       End If
    next
    FindDelimiter = n

end function

sub pause mil
    tcurrent = time$("milliseconds")
    timeout = tcurrent + mil
    if timeout > 86400000 then  ' roll over at midnight
       timeout = timeout - 86400000
       do
           tcurrent = time$("milliseconds")
       loop until (86400000 - tcurrent) > 1000000
    end if

    do
       tcurrent = time$("milliseconds")
    loop until (tcurrent >= timeout)

    end sub

    end