Shop OBEX P1 Docs P2 Docs Learn Events
Sensirion SHT11 Sensor module (#28018) - Humidity readings > 100%? — Parallax Forums

Sensirion SHT11 Sensor module (#28018) - Humidity readings > 100%?

xanatosxanatos Posts: 1,120
edited 2014-02-14 14:13 in Accessories
This is working well, except that the sensor, when I breathe my high-humidity breath on the unit, reads up to 114% humidity... so it's wetter than water. Now granted, I have had a glass of wine, but would that read as a higher humidity than 100%?

Here's my code, which is basically taken directly from the Parallax download, just had to change some pin numbers and the pin names... again - works good, temp is good... just humidity can exceed 100%, which seems quite wrong. I can think of several ways to "fix" this, but none really take into account WHY it's reading in excess of 100...

Thanks for the feedback.
' =========================================================================
'
'   File....... SHT_Demo_Only.bs2
'   Purpose.... Basic functions for the SHT11
'   E-mail..... xanatos@xanatos.com
'   Updated.... 13 February 2014
'
'   {$STAMP BS2px}
'   {$PBASIC 2.5}
'
' =========================================================================

' -----[ Program Description ]---------------------------------------------
'
' Stuff to figure out the SHT11
'
' -----[ Revision History ]------------------------------------------------
'
' 1.0: Initial release
'
' -----[ I/O Definitions ]-------------------------------------------------

SensD           PIN     3                       ' Sensirion Data pin 1
SensC           PIN     4                       ' Sensirion Clock pin 3
' -----[ Variables ]-------------------------------------------------------

ioByte          VAR     Byte                    ' data from/to SHT11
ackBit          VAR     Bit                     ' ack/nak from/to SHT11
toDelay         VAR     Byte                    ' timeout delay timer
timeOut         VAR     Bit                     ' timeout status
soT             VAR     Word                    ' temp counts from SHT11
tC              VAR     Word                    ' temp - Celcius
tF              VAR     Word                    ' temp - Fahrenheit
soRH            VAR     Word                    ' humidity counts
rhLin           VAR     Word                    ' humidity; linearized
rhTrue          VAR     Word                    ' humidity; compensated
status          VAR     Byte                    ' status byte

' -----[ Constants ]-------------------------------------------------------
#SELECT $STAMP
  #CASE BS2, BS2E, BS2PE
    T2400       CON     396
    T9600       CON     84
    T19K2       CON     32
  #CASE BS2SX, BS2P
    T2400       CON     1021
    T9600       CON     240
    T19K2       CON     110
  #CASE BS2PX
    T1200       CON     3313
    T2400       CON     1646
    T4800       CON     813
    T9600       CON     396
    T19K2       CON     188
    T38K4       CON     84
#ENDSELECT

ShtTemp         CON     %00011  ' read temperature
ShtHumi         CON     %00101  ' read humidity
ShtStatW        CON     %00110  ' status register write
ShtStatR        CON     %00111  ' status register read
ShtReset        CON     %11110  ' soft reset
Ack             CON     0
NoAck           CON     1
No              CON     0
Yes             CON     1
DegSym          CON     186     ' degrees symbol for DEBUG

' -----[ Initialization ]--------------------------------------------------

Init:

  GOSUB SHT_Connection_Reset ' reset device connection
  PAUSE 250 ' let DEBUG window open
  DEBUG CLS,  "SHT11 Sensor Demo", CR, "-----------------", CR

' -----[ Program Code ]----------------------------------------------------

Main:

  DO
    GOSUB SHT_Measure_Temp
    DEBUG CRSRXY, 0, 3,
    "soT...... ", DEC soT, CR,
    "tC....... ", DEC (tC / 10), ".", DEC1 tC, DegSym, " ", CR,
    "tF....... ", DEC (tF / 10), ".", DEC1 tF, DegSym, " "
    GOSUB SHT_Measure_Humidity
    DEBUG CRSRXY, 0, 7,
    "soRH..... ", DEC soRH, CR,
    "rhLin.... ", DEC (rhLin / 10), ".", DEC1 rhLin, "% ", CR,
    "rhTrue... ", DEC (rhTrue / 10), ".", DEC1 rhTrue, "% "
    PAUSE 1000
  LOOP
  END

' -----[ Subroutines ]-----------------------------------------------------

SHT_Connection_Reset:
  SHIFTOUT SensD, SensC, LSBFIRST, [$FFF\9]
  ' generates SHT11 "start" sequence
  ' _____ _____
  ' ShtData |_______|
  ' ___ ___
  ' Clock ___| |___| |___

SHT_Start:
  INPUT SensD ' let pull-up take high
  LOW SensC
  HIGH SensC
  LOW SensD
  LOW SensC
  HIGH SensC
  INPUT SensD
  LOW SensC
  RETURN

SHT_Measure_Temp:
  GOSUB SHT_Start ' alert device
  ioByte = ShtTemp ' temperature command
  GOSUB SHT_Write_Byte ' send command
  GOSUB SHT_Wait ' wait for measurement
  ackBit = Ack ' another read follows
  GOSUB SHT_Read_Byte ' get MSB
  soT.HIGHBYTE = ioByte
  ackBit = NoAck ' last read
  GOSUB SHT_Read_Byte ' get LSB
  soT.LOWBYTE = ioByte
  ' Note: Conversion factors are multiplied by 10 to return the
  ' temperature values in tenths of degrees
  tC = soT ** $1999 - 400 ' convert to tenths C  -- celcius = raw * 0.01 - 40
  tF = soT ** $2E14 - 400 ' convert to tenths F  -- fahrenheit = raw * 0.018 - 40
  RETURN

SHT_Measure_Humidity:
  GOSUB SHT_Start ' alert device
  ioByte = ShtHumi ' humidity command
  GOSUB SHT_Write_Byte ' send command
  GOSUB SHT_Wait ' wait for measurement
  ackBit = Ack ' another read follows
  GOSUB SHT_Read_Byte ' get MSB
  soRH.HIGHBYTE = ioByte
  ackBit = NoAck ' last read
  GOSUB SHT_Read_Byte ' get LSB
  soRH.LOWBYTE = ioByte

  ' linearize humidity
  ' rhLin = (soRH * 0.0405) - (soRH^2 * 0.0000028) - 4

  ' for the BASIC Stamp:
  ' rhLin = (soRH * 0.0405) - (soRH * 0.002 * soRH * 0.0014) - 4

  ' Conversion factors are multiplied by 10 to return tenths

  rhLin = (soRH ** $67AE) - (soRH ** $83 * soRH ** $5B) - 40
  ' temperature compensated humidity
  ' rhTrue = (tc - 25) * (soRH * 0.00008 + 0.01) + rhLin

  ' Conversion factors are multiplied by 10 to return tenths

  rhTrue = (tC - 250) * (soRH ** $34) + rhLin
RETURN

SHT_Write_Status:
  GOSUB SHT_Start ' alert device
  ioByte = ShtStatW ' write to status reg cmd
  GOSUB SHT_Write_Byte ' send command
  ioByte = status
  GOSUB SHT_Write_Byte
  RETURN

SHT_Read_Status:
  GOSUB SHT_Start ' alert device
  ioByte = ShtStatW ' write to status reg cmd
  GOSUB SHT_Read_Byte ' send command
  ackBit = NoAck ' only one byte to read
  GOSUB SHT_Read_Byte
  RETURN

SHT_Write_Byte:
  SHIFTOUT SensD, SensC, MSBFIRST, [ioByte] ' send byte
  SHIFTIN SensD, SensC, LSBPRE, [ackBit\1] ' get ack bit
  RETURN

SHT_Read_Byte:
  SHIFTIN SensD, SensC, MSBPRE, [ioByte] ' get byte
  SHIFTOUT SensD, SensC, LSBFIRST, [ackBit\1] ' send ack bit
  INPUT SensD ' release data line
  RETURN

SHT_Wait:
  INPUT SensD ' data line is input
  timeOut = No ' assume no timeout
  FOR toDelay = 1 TO 250 ' wait ~1/4 second
  IF (SensD = 0) THEN EXIT
  PAUSE 1
  NEXT
  IF (toDelay = 250) THEN timeOut = Yes ' loop completed = timeout
  RETURN

SHT_Soft_Reset:
  GOSUB SHT_Connection_Reset ' reset the connection
  ioByte = ShtReset ' reset command
  ackBit = NoAck ' only one byte to send
  GOSUB SHT_Write_Byte ' send it
  PAUSE 11 ' wait at least 11 ms
  RETURN

  'In HIGH humidity applications, the SHT11 heater can be switched ON briefly TO prevent condensation.
  'Another use of the heater is to test the operation of the sensor: by reading before enabling the heater
  'and immediately after the sensor can be verified by noting a higher temperature and lower humidity.
  'The following subroutines can be used to switch the SHT11 heater on and off.

Heater_On:
  status = %00000100 ' heater bit = On
  GOSUB SHT_Write_Status
  RETURN

Heater_Off:
  status = %00000000 ' heater bit = Off
  GOSUB SHT_Write_Status
  RETURN
' -----[ End of File ]----------------------------------------------------

Comments

  • WBA ConsultingWBA Consulting Posts: 2,933
    edited 2014-02-13 16:50
    Xanatos, If you try the stock formulas from the sample file, does it work?

    In other words, swap out these two lines in your code:
    rhLin = (soRH ** $67AE) - (soRH ** $83 * soRH ** $5B) - 40
    
    
     rhTrue = (tC - 250) * (soRH ** $34) + rhLin
    


    For these 4 lines from the sample code:
    rhLin = (soRH ** 26542)
      rhLin = rhLin - ((soRH ** 3468) * (soRH ** 3468) + 50 / 100)
      rhLin = rhLin - 40
    
    
      rhTrue = ((tC / 10 - 25) * (soRH ** 524 + 1) + (rhLin * 10)) + 5 / 10
    
  • xanatosxanatos Posts: 1,120
    edited 2014-02-13 17:15
    Those work MUCH better! My humid and currently garlic-y breath now reads a maximum of 93%, which I would find far more likely, while the ambient humidity still reads in the 32 to 34% range, which is pretty much identical to the previous codes' output.

    I'll go look at the two sets of calculations and see how that works.

    THANK YOU... very much.

    Dave
  • WBA ConsultingWBA Consulting Posts: 2,933
    edited 2014-02-13 20:27
    Glad that helped. I recall from quite a few years ago when I first played with the Sensirion/Stamp combo that I had tried to make the formulas simpler and ended up finding out that some steps of the formula needed to be left in separate lines of code, even though my code seemed to make sense per PBASIC standards. So, even though I had an idea to help you out, I have no idea why your code doesn't work.....
  • Tracy AllenTracy Allen Posts: 6,658
    edited 2014-02-14 00:20
    It looks to me like this term,

    (soRH ** $83 * soRH ** $5B)

    is low by a factor of 10, and that makes the result come out too high.
    I see that your original formula is found here:
    http://parallax.com/downloads/sensirion-temphumidity-sensor-guide
    and the one that Andrew posted comes from here:
    http://parallax.com/downloads/sensirion-temphumidity-sensor-bs2-example-code

    from the reference:
    [SIZE=1][FONT=courier new]' linearize humidity
    ' rhLin = (soRH * 0.0405) - (soRH^2 * 0.0000028) - 4
    '
    ' for the BASIC Stamp:
    ' rhLin = (soRH * 0.0405) - [COLOR=#ff0000](soRH * 0.002 * soRH * 0.0014)[/COLOR] - 4
    '
    ' Conversion factors are multiplied by 10 to return tenths
    '
    rhLin = (soRH ** $67AE) - (soRH ** $83 * soRH ** $5B) - 40 [/FONT][/SIZE]
    

    Note that 0.002 * 0.0014 = 0.0000028
    0.002 * 65536 = 131 = $83
    0.0014 * 65536 = 91 = $5B
    But with the factor of 10 applied to the second term it should be
    0.014 * 65536 = $396
    rhLin = (soRH ** $67AE) - (soRH ** $83 * soRH ** $396) - 40

    There are so many ways to parse this so that it comes out right. The other method parses the 0.0000028*10 into its square root.
    0.00529 * 65536 = 346.8
    ((soRH ** 3468) * (soRH ** 3468) / 100)

    When I first worked with this chip, I got myself twisted into a pretzel around the math.
  • xanatosxanatos Posts: 1,120
    edited 2014-02-14 14:13
    I'm pretty good at math in general, just my head gets twisted around with trying to make integer math work on what SHOULD be floating point. My programming background was primarily VB, so decimals were fine as were fractions and pretty much anything I could throw in, it would chew on just fine.

    That whole thing of multiplying .002 by 65536 to get the shifted equivalent for multiplying... still confuses the heck out of me. It's one of the very few remaining alcoves in programming for non-floating point chips that I simply don't seem to get without hours of needless brain squeezing :) One of these days I'll have to figure out how to make some visual representation of what 's going on there, and maybe then, if I'm lucky, I'll get it!

    I know there are some amazing tricks that are possible once a brain is successfully wrapped around this understanding. Looking forward to getting there.

    Thanks again for the code substitution. When I work through a few examples line by line it may help me see better what's actually going on at the bit level.

    Dave
Sign In or Register to comment.