Sensirion SHT11 Sensor module (#28018) - Humidity readings > 100%?
xanatos
Posts: 1,120
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.
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
In other words, swap out these two lines in your code:
For these 4 lines from the sample code:
I'll go look at the two sets of calculations and see how that works.
THANK YOU... very much.
Dave
(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:
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.
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
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