Shop OBEX P1 Docs P2 Docs Learn Events
SHT75 temp/humidity sensor giving inaccurate value — Parallax Forums

SHT75 temp/humidity sensor giving inaccurate value

laser-vectorlaser-vector Posts: 118
edited 2013-07-10 05:00 in Accessories
I have just written a little Spin routine to try to communicate with this sensor, all seemed to be going well and i was able to read the Humidity value and compare it to another sensor and it looks fine. however, when i attempt to read the temperature it looks ok at room temperature but not what i would expect to see when i blow on it.

when it has stabilized i see a reading of :
Humidity:48.64648% degC:19.37 RawTempBin:01011100010111 RawTempDec:5911 degF:66.86601

but when i breath on it (for about 10 seconds) i get somewhere around:
Humidity:93.04173% degC:79.41001 RawTempBin:10111010000111 RawTempDec:11911 degF:174.938

174.9 degreesF !!! ?????

im not sure what to make of it other than im not understanding what exactly a band:gap PTAT (Proportional To Absolute Temperature) temperature sensor really is..

further more, i have watched the output on a scope to confirm that the "RawTempBin" value is correct. that being said i have taken the RawTempDec value and punched it into the formula (T=d1+d2*SOt) provided in the pdf using the values:
d1 = -39.7
d2 = 0.01
the output was as expected and confirms that the math is correct in Spin.

PDF is here:
http://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/Humidity/Sensirion_Humidity_SHT7x_Datasheet_V5.pdf

my code for communication with the SHT75:
CON
        _clkmode = xtal1 + pll16x                                               'Standard clock mode * crystal frequency = 80 MHz
        _xinfreq = 5_000_000

sclk = 1
data = 0
trigger = 2
var

long address[2]
long command[4]
long compound[4]
  
OBJ

ser : "fullduplexserial"
f   : "FloatMath"
fp  : "FloatString"

DAT

c1  long  -2.0468
c2  long  0.0367
c3  long  -1.5955 * (0.000001)

d1  long  -39.7
d2  long  0.01


SHTAddr byte %000
RHcommand byte %00000101
TEMPcommand byte %00000101

PUB main | tempC, tempRaw

ser.start(31,30,0,115200)
'fp.SetPositiveChr(" ")

dira[trigger]~~

repeat
  waitcnt(clkfreq/1 + cnt)
  ser.str(string("H:")) 
  ser.str(fp.FloatToString(GetRH))
  ser.str(string(" C:"))
  tempC :=  GetTEMP
  ser.str(fp.FloatToString(tempC))
  ser.str(string(" Raw:"))
  tempRaw :=  GetTEMPRaw 
  ser.bin(tempRaw,14)
  ser.str(string(" dec:"))
  ser.dec(tempRaw) 
  ser.str(string(" F:"))   
  ser.str(fp.FloatToString(cvtCtoF(tempC)))
  ser.tx(13)

PRI calc_dp(temp,humidity)

PRI cvtCtoF(celsius)
    return f.FAdd(f.FMul(1.8,celsius),32.0)

PRI calc_rh(RHraw)
    compound[0] := f.FMul(c2, f.FFloat(RHraw))
    compound[1] := f.FMul(c3,f.FFloat(RHraw*RHraw)) 
    compound[2] := f.FAdd(compound[0],compound[1])     
    return f.FAdd(c1,compound[2])    

PRI calc_T(Traw)
    compound[0] := f.FMul(d2, f.FFloat(Traw))
    return f.FAdd(d1, compound[0])

PRI GetRH | RHdata
   InitCom
   SendAddr(SHTAddr)
   SendCmd(RHcommand)
   AckAndWait 
   SendIdleBits   
   RHdata := ReadInData(12)                      
   EndTrans
   return calc_rh(RHdata) 

PRI GetTemp | TEMPdata
   InitCom
   SendAddr(SHTAddr)
   SendCmd(TEMPcommand)
   AckAndWait 
   SendIdleBits 
   TEMPdata := ReadInData(14)                        
   EndTrans
   return calc_T(TEMPdata) 'calc_T(TEMPdata) 

PRI GetTempRaw | TEMPdata
   InitCom
   SendAddr(SHTAddr)
   SendCmd(TEMPcommand)
   AckAndWait 
   SendIdleBits
      outa[Trigger]~~  
   TEMPdata := ReadInData(14)
      outa[Trigger]~                        
   EndTrans
   return TEMPdata

PRI ReadInData(len) | output
  output := 0   
  repeat 4
     outa[sclk]~~
     pause
     output := (output << 1) + ina[data] 
     outa[sclk]~  
     pause   
  repeat while ina[data] == 0
 
  pause  
  dira[data]~~
  outa[data]~  
  pause
  outa[sclk]~~
  pause
  outa[sclk]~  
  pause 
  dira[data]~    
  repeat len-4
    outa[sclk]~~
    pause
    output := (output << 1) + ina[data]  
    outa[sclk]~  
    pause
  return output
  
PRI EndTrans
  dira[data]~~  
  outa[data]~

PRI ACK
  
  outa[sclk]~~
  pause
  outa[sclk]~
  pause
PRI SendIdleBits
   repeat 4 'idle bits
     outa[sclk]~~
     pause
     outa[sclk]~  
     pause

PRI AckAndWait
   outa[sclk]~~ 
   pause
   outa[sclk]~ 
   pause
   dira[data]~  
   repeat while ina[data] == 1
   'long wait here for sensor to take measurement

PRI InitCom
   dira[sclk]~~
   dira[data]~~
   outa[sclk]~
   outa[data]~~
   outa[sclk]~~
   pause
   outa[data]~
   pause
   outa[sclk]~
   pause
   outa[sclk]~~
   pause  
   outa[data]~~
   pause
   outa[sclk]~
   pause
   outa[data]~
   pause
  
PRI SendAddr(adr) | x
   repeat x from 0 to 2
     outa[data] := (adr >> x) & 1  
     outa[sclk]~~
     pause
     outa[sclk]~
     outa[data]~
     pause
     
PRI SendCmd(cmd) | x
   repeat x from 4 to 0
     outa[data] := (cmd >> x) & 1    
     outa[sclk]~~
     pause
     outa[sclk]~
     outa[data]~
     pause

PRI SendRegVal(Value) | x
   repeat x from 7 to 0
     outa[data] := (Value >> x) & 1    
     outa[sclk]~~
     pause
     outa[sclk]~
     outa[data]~
     pause

PUB pause
waitcnt(1000+ cnt)


thank you all for your help

[EDIT]

ok i found a problem, where i specify the commands i accidentally copy-pasted the command %00000101 twice when it should have been %00000011 for temp readings. so i changed it to:
SHTAddr byte %000
RHcommand byte %00000101
TEMPcommand byte %00000011

the readings however are still a little high.

room temperature -
Humidity:49.03014% degC:54.73 RawTempBin:10010011110011 RawTempDec:9459 degF:130.514

breath-
Humidity:90.55299% degC:76.21 RawTempBin:10110010100111 RawTempDec:11431 degF:169.178

hmm... 38.6 degree delta, that's better i suppose.. but still that's almost a 56 degree offset from our cozy 74F room temp.

Comments

  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-07-08 13:26
    Have you tried Tracy Allen's object? I don't recall which object I used, but I know I had my Sensirion sensor working with a Prop. I think I used Tracy's Object. There are several other objects for the sensor in the OBEX.
  • laser-vectorlaser-vector Posts: 118
    edited 2013-07-10 05:00
    Thank you Duane for pointing out Tracy Allen's object as that did work and i was able to use it to confirm my sensor.

    i may use it in the final design of my project but as for now i did figure out why my Spin wasnt showing the correct value. so before i let this thread go id like to post my updated code for anyone who would like it.
    CON
            _clkmode = xtal1 + pll16x                                               'Standard clock mode * crystal frequency = 80 MHz
            _xinfreq = 5_000_000
    
    sclk = 1
    data = 0
    trigger = 2
    
    T_OFFSET_5V0 = 4000
    T_OFFSET_3V3 = 3964
    T_OFFSET_3V0 = 3960
    T_OFFSET = T_OFFSET_3V3  
    
    var
    
    long address[2]
    long command[4]
    long compound[4]
      
    OBJ
    
    ser : "fullduplexserial"
    f   : "Float32"
    fp  : "FloatString"  
    DAT
    
    c1  long  -2.0468
    c2  long  0.0367
    c3  long  -1.5955 * (0.000001)
    
    d1  long  -39.7
    d2  long  0.01
    
    
    SHTAddr byte %000
    RHcommand byte %00000101
    TEMPcommand byte %00000011
    
    PUB main | tempC, tempF, rh, rawHumidity
    
    ser.start(31,30,0,115200)
    'fp.SetPositiveChr(" ")
    f.start
    dira[trigger]~~
    
    repeat
      rawHumidity := GetRH
      tempC :=  GetTEMP
      tempF := cvtCtoF(tempC)
    
      waitcnt(clkfreq/10 + cnt)
      ser.str(string("H:"))
      ser.str(fp.FloatToString(rawHumidity))
      ser.str(string(" C:"))
      ser.str(fp.FloatToString(tempC))
      ser.str(string(" F:"))   
      ser.str(fp.FloatToString(tempF))
      ser.str(string(" DP:"))   
      ser.str(fp.FloatToString(dewpoint(tempF,rawHumidity)))  
      ser.tx(13)
    
    PRI dewpoint(t, rh) | h
      ' h = (log10(rh) - 2.0) / 0.4343 + (17.62 * t) / (243.12 + t)
      h := f.FAdd(f.FDiv(f.FSub(f.log10(rh), 2.0), 0.4343), f.FDiv(f.FMul(17.62, t), f.FAdd(243.12, t))) 
      ' dewpoint = 243.12 * h / (17.62 - h)
      return f.FDiv(f.FMul(243.12, h), f.FSub(17.62, h)) 
    
    PRI cvtCtoF(celsius)
        return f.FAdd(f.FMul(1.8,celsius),32.0)
    
    PRI calc_rh(RHraw)
        compound[0] := f.FMul(c2, f.FFloat(RHraw))
        compound[1] := f.FMul(c3,f.FFloat(RHraw*RHraw)) 
        compound[2] := f.FAdd(compound[0],compound[1])     
        return f.FAdd(c1,compound[2])    
    
    PRI calc_T(Traw)
        compound[0] := f.FMul(d2, f.FFloat(Traw))
        return f.FAdd(d1, compound[0])
    
    PRI GetRH | RHdata
       InitCom
       SendAddr(SHTAddr)
       SendCmd(RHcommand)
       AckAndWait 
    
       RHdata := 0
       RHdata := ReadInData(RHdata)
       AckData
       RHdata := ReadInData(RHdata)                       
       EndTrans
       return calc_rh(RHdata) 
    
    PRI GetTemp | TEMPdata
       InitCom
       SendAddr(SHTAddr)
       SendCmd(TEMPcommand)
       AckAndWait 
       TEMPdata := 0
       TEMPdata := ReadInData(TEMPdata)
       AckData
       TEMPdata := ReadInData(TEMPdata)                        
       EndTrans
       return calc_T(TEMPdata) 'calc_T(TEMPdata) 
    
    PRI AckData
    
      repeat while ina[data] == 0
     
      pause  
      dira[data]~~
      outa[data]~  
      pause
      outa[sclk]~~
      pause
      outa[sclk]~  
      pause 
      dira[data]~ 
    
    PRI ReadInData(output)
      dira[data]~    
      repeat 8
        outa[sclk]~~
        pause
        output := (output << 1) + ina[data]  
        outa[sclk]~  
        pause     
      return output
      
    PRI EndTrans
      dira[data]~~  
      outa[data]~
    
    PRI ACK 
      outa[sclk]~~
      pause
      outa[sclk]~
      pause
    
    PRI AckAndWait
       outa[sclk]~~ 
       pause
       outa[sclk]~ 
       pause
       dira[data]~  
       repeat while ina[data] == 1
       'long wait here for sensor to take measurement
    
    PRI InitCom
       dira[sclk]~~
       dira[data]~~
       outa[sclk]~
       outa[data]~~
       outa[sclk]~~
       pause
       outa[data]~
       pause
       outa[sclk]~
       pause
       outa[sclk]~~
       pause  
       outa[data]~~
       pause
       outa[sclk]~
       pause
       outa[data]~
       pause
      
    PRI SendAddr(adr) | x
       repeat x from 0 to 2
         outa[data] := (adr >> x) & 1  
         outa[sclk]~~
         pause
         outa[sclk]~
         outa[data]~
         pause
         
    PRI SendCmd(cmd) | x
       repeat x from 4 to 0
         outa[data] := (cmd >> x) & 1    
         outa[sclk]~~
         pause
         outa[sclk]~
         outa[data]~
         pause
    
    PRI SendRegVal(Value) | x
       repeat x from 7 to 0
         outa[data] := (Value >> x) & 1    
         outa[sclk]~~
         pause
         outa[sclk]~
         outa[data]~
         pause
    
    PUB pause
    waitcnt(4000 + cnt)
    
    

    unfortunately the dewpoint method does not seem to work correctly, it was pulled out of another object for the SHT11, if anyone is ever able to figure out why i would really love to know! :)
Sign In or Register to comment.