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 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