Shop OBEX P1 Docs P2 Docs Learn Events
SHT-11 temp&RH sensor readings Needs stabilizer — Parallax Forums

SHT-11 temp&RH sensor readings Needs stabilizer

Igor_RastIgor_Rast Posts: 357
edited 2012-10-31 18:59 in Propeller 1
Hi there fellow form members ,

i am using the sensiron sht-11 demo object found in the OBEX .
modified it a Little so I only get the hi resolution readings,

but I still have a problem , The readings jumps up and down allittle . by say 1 degree .
0.1 is acceptable but not more , back and forth a couple of times.
I am using these readings to display a graph in a webpage served by a wiznet w5200 . ( almost fininshed project)
and here the result is that i have spikes showing up in my graph .

anybody get an idea on how to improve the readings stability , buffer of some kind , but dont realy know how

this s the code im using now
var
  byte status
  
OBJ

  term          : "fullduplexserial"
  sht           : "Sensirion_full"
  fp            : "FloatString"
  f             : "Float32"
  
PUB main | count,tmp,rawTemp, rawHumidity, tempC, rh, dewC, TF_fp, RH_fp

  term.start(31, 30, 0, 115200)
  f.start                                               ' start floating point object
  sht.start(SHT_DATA, SHT_CLOCK)                        ' start sensirion object

  waitcnt(clkfreq*3+cnt)
  sht.config(33,sht#off,sht#yes,sht#hires)              'configure SHT-11
  term.tx(CLS)                                          

  ' read SHT-11 sensor and update (note: need to set baud to 57K if want output data to PLX-DAQ)
  term.Str(String("MSG,Sensirion SHT-11 Demo",13))
  term.Str(String("Temp_raw, RH_raw, TC_float, TF_float, RH_float, DewPtC_float, DewPtF_float, TF_fixpt, RH_fixpt, status_byte",13))
  term.Str(String("CLEARDATA",13))
  repeat
    term.Str(String("DATA,"))
    rawTemp := f.FFloat(sht.readTemperature) 
    term.str(fp.FloatToFormat(rawTemp, 5, 0))
    term.str(string(","))
    rawHumidity := f.FFloat(sht.readHumidity)
    term.str(fp.FloatToFormat(rawHumidity, 5, 0))

    term.str(string(","))
    tempC := celsius(rawTemp)  
    term.str(fp.FloatToFormat(tempC, 5, 1))
    term.str(string(","))
    term.str(fp.FloatToFormat(fahrenheit(tempC), 5, 1))
    term.str(string(","))
     
    rh := humidity(tempC, rawHumidity)
    term.str(fp.FloatToFormat(rh, 5, 1))
    term.str(string("%, "))
     
    dewC := dewpoint(tempC, rh)
    term.str(fp.FloatToFormat(dewC, 5, 1))
    term.str(string(",      "))
    term.str(fp.FloatToFormat(fahrenheit(dewC), 5, 1))
    term.str(string(",    "))

    TF_fp:=sht.getTemperatureF
    term.dec(TF_fp)
    term.str(string(", "))
    RH_fp:=sht.getHumidity
    term.dec(RH_fp)
    term.str(string(",   "))
    status:=sht.readStatus
    term.bin(status,8)
    term.str(string(",  "))
'   status:=sht.checkLowBat
'   term.bin(status,8)
    term.str(string(13))

    {if count//4}                                       'toggle every 4 cycles
      {sht.config(33,sht#off,sht#no,sht#lores)}         '3 fast, loRes measurements
    {else}
      sht.config(33,sht#off,sht#yes,sht#hires)        '1 slow, hiRes measurement
    count++
'   waitcnt (clkfreq*2+cnt)                           'display every 2 seconds
    
     
PUB celsius(t)
  ' from SHT1x/SHT7x datasheet using value for 3.5V supply
  ' celsius = -39.7 + (0.01 * t)
  return f.FAdd(-39.7, f.FMul(0.01, t))  

PUB fahrenheit(t)
  ' fahrenheit = (celsius * 1.8) + 32
  return f.FAdd(f.FMul(t, 1.8), 32.0)
  
PUB humidity(t, rh) | rhLinear
  ' rhLinear = -2.0468 + (0.0367 * rh) + (-1.5955E-6 * rh * rh)
  ' simplifies to: rhLinear = ((-1.5955E-6 * rh) + 0.0367) * rh -2.0468
  rhLinear := f.FAdd(f.FMul(f.FAdd(0.0367, f.FMul(-1.5955E-6, rh)), rh), -2.0468)
  ' rhTrue = (t - 25.0) * (0.01 + 0.00008 * rawRH) + rhLinear
  return f.FAdd(f.FMul(f.FSub(t, 25.0), f.FAdd(0.01, f.FMul(0.00008, rh))), rhLinear)

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

Comments

  • Bill HenningBill Henning Posts: 6,445
    edited 2012-10-31 07:05
    Average the results.

    The simple way is to sum up ten readings, then divide by ten, and use that result.

    A more complicated way is averaging over a sliding window of the last 10 results.
  • Igor_RastIgor_Rast Posts: 357
    edited 2012-10-31 07:25
    avering the result over a slinding windows does sound better :p

    but you have any examples. Only one cog runs to update the reading , othe cog just use the reading , but it has to be available all the time
  • Bill HenningBill Henning Posts: 6,445
    edited 2012-10-31 09:11
    ' was:
    
    rawTemp := f.FFloat(sht.readTemperature)) 
    
    ' now:
    
    rawTemp := f.FFloat(avgTemp)
    
    ' a new function
    
    pub avgTemp|sum
       sum:=0
       repeat 10
           sum+=sht.readTemperature)
       return sum/10
    
    
    Igor_Rast wrote: »
    avering the result over a slinding windows does sound better :p

    but you have any examples. Only one cog runs to update the reading , othe cog just use the reading , but it has to be available all the time
  • Igor_RastIgor_Rast Posts: 357
    edited 2012-10-31 11:57
    Thanks Bill

    Your example works ,
    when it takes the average of 10 readings the awnser is pretty stable, But its taking a bit long
    If i let it take less readings say 5 , then I get a bigger differeance every time .

    So I was tinking about the roling window you were mentioning that the cog continuesly updates the raw reading , and the program calculates the average over the last 10 raw readings every time the reading is asked
    So it knows the last 10 readings , but keeps giving average with every reading added to it .
    but not sure how to make that array


    I figured out something like this , It looks to be working , But maybe im doing something wrong ,. any advice
    pub avgTemp
       
       
       case reading 
           1 : r1 := sht.readTemperature
           2 : r2 := sht.readTemperature   
           3 : r3 := sht.readTemperature
           4 : r4 := sht.readTemperature
           5 : r5 := sht.readTemperature
           6 : r6 := sht.readTemperature
           7 : r7 := sht.readTemperature
           8 : r8 := sht.readTemperature
           9 : r9 := sht.readTemperature
           10: r10 := sht.readTemperature
           
       reading := reading + 1
       
       if reading == 10
          reading := 0
          
       return ((r1+r2+r3+r4+r5+r6+r7+r8+r9+r10)/10)
    
  • Mike GMike G Posts: 2,702
    edited 2012-10-31 13:03
    Use the MOD operator to cycle through the raw value array
    CON
      _clkmode = xtal1 + pll16x     
      _xinfreq = 5_000_000
    
      RAW_ELEMENTS = 10
      
    VAR
      long  raw[RAW_ELEMENTS]
      
    OBJ
      pst           : "Parallax Serial Terminal"
    
    
    PUB Main | i, j
      j := i := 0
      pst.Start(115_200)
      pause(500)
    
      repeat
        raw[i] := j
        pause(1000)
        pst.str(string("Raw_"))
        pst.dec(i)
        pst.str(string(" = "))
        pst.dec(j++)
        pst.char(13)
        i := ++i // (RAW_ELEMENTS) 
    
    
    PRI pause(Duration)  
      waitcnt(((clkfreq / 1_000 * Duration - 3932) #> 381) + cnt)
      return 
    
  • localrogerlocalroger Posts: 3,451
    edited 2012-10-31 13:37
    Another way to do this which is a bit clever is the "exponentially weighted running average." This actually gives a nice responsive display without using the array of old entries.

    1. Pick a "new value factor." F Start with 0.1, but make it selectable; higher values (0.2) will make the display more responsive, lower (0.05) more stable.
    2. Seed your display value D with the first reading.
    3. On each new reading R, D = D * (1 - F) + (R * F)

    This makes readings contribute less and less to the final total as they get older.
  • Igor_RastIgor_Rast Posts: 357
    edited 2012-10-31 13:56
    @ Mike ,
    I do understand de idea so it rotates tru the values that need to be written to , But its not working out completly .
    The i value seems to trick me here orso .

    is the aproch also available to do it like this
    . let a newcog run getting the raw values into the array. repeatetly .
    incorporate a lock , so it doesnt write when we are going to read from the array,.
    and then in the main cog , run only the set of the rutine and get the average over the last 10 readings , ( the other cog has to stop and wait for the main cog to read the value )
    this is what i did but its not realy working
    OBJ
    
      term          : "fullduplexserial"
      sht           : "Sensirion_full"
      fp            : "FloatString"
      f             : "Float32"
       pst           : "Parallax Serial Terminal"
    
    
      
    PUB main | tmp,rawTemp, rawHumidity, tempC, rh, dewC, TF_fp, RH_fp,i
      i := 0
      term.start(31, 30, 0, 115200)
      f.start                                               ' start floating point object
      sht.start(SHT_DATA, SHT_CLOCK)                        ' start sensirion object
    
      waitcnt(clkfreq*3+cnt)
      sht.config(33,sht#off,sht#yes,sht#hires)              'configure SHT-11
      term.tx(CLS)                                          
    
      term.Str(String("MSG,Sensirion SHT-11 Demo",13)) 
      term.Str(String("CLEARDATA",13))
      repeat
        term.Str(String("Reading : "))
        
        rawTemp := f.FFloat(avgTemp)     
        rawHumidity := f.FFloat(sht.readHumidity) 
        
        tempC := celsius(rawTemp)    
        term.str(fp.FloatToFormat(tempC, 5, 1))
        
        term.str(string(","))        
        rh := humidity(tempC, rawHumidity)
        term.str(fp.FloatToFormat(rh, 5, 1))
        term.str(string("%, "))
         
        term.str(string(13))
        
    
    pub avgTemp
    
        raw[i] := sht.readTemperature
        i := ++i // (RAW_ELEMENTS)
          
       return (( raw[0]+raw[1]+raw[2]+raw[3]+raw[4]+raw[5]+raw[6]+raw[7]+raw[8]+raw[9])/10) 
    


    @localroger .
    I do understand a little the theorie behind that approche. I think .bare with me, Im not that a good with the prop starting from scratch , hope you can give a example
    ill definitly work my way around managing once i get something to read/test/ figure out . thanks


    UPDATE

    I put the i in the variabels to be a global variable. and all works out now . nice .
    im still intrested in your theorie roger as to how to implement it with this code
    VAR
         long i
    
  • Igor_RastIgor_Rast Posts: 357
    edited 2012-10-31 18:59
    for the record .
    the tempcontrol method gets lached in a newcog , another cog displays it on the lcd , and the other one serves it at the webpage
    PUB Tempcontrol        
        z := u := 0
        dira[led_5]~~
     
        
        sht.start(SHT_DATA,SHT_CLK)
        f.start
        sht.config(33,sht#off,sht#yes,sht#hires)  
        fil_reading_buffer  
          
      repeat      
        
        repeat
          repeat until not lockset(templock)    
          outa[led_5]~~     
      
          tempC1 := F.FMul(celsius(f.FFloat(avgTemp)),10.0)     {floating point raw measurement temp}
          tempC3 :=f.FTrunc(tempC1)                              { integer to calculate/use  }     
         
          lv1 := humidity(tempC, f.FFloat(avgrv))   {floating poitn ram measurement RH }
          lv3 :=f.FTrunc(lv1) 
        
          lockclr(templock)
          outa[led_5]~      
          
          waitcnt(clkfreq + cnt)
    
    pub avgTemp  
        raw[z] := sht.readTemperature
        z := ++z // (RAW_ELEMENTS)      
        return (( raw[0]+raw[1]+raw[2]+raw[3]+raw[4]+raw[5]+raw[6]+raw[7]+raw[8]+raw[9])/10) 
    
    pub avgrv  
        rawrv[u] := sht.readHumidity
        u := ++u // (RAW_ELEMENTS)      
        return (( rawrv[0]+rawrv[1]+rawrv[2]+rawrv[3]+rawrv[4]+rawrv[5]+rawrv[6]+rawrv[7]+rawrv[8]+rawrv[9])/10)
    
    PUB fil_reading_buffer
    
      repeat 10
        raw[z] := sht.readTemperature
        z := ++z // (RAW_ELEMENTS)
        
      repeat 10 
        rawrv[u] := sht.readHumidity
        u := ++u // (RAW_ELEMENTS) 
    
      z := u := 0
      return
    
    
    Looks like it did the job pretty good , resulting in a lean graph
    44.jpg


    I also ended up removing the locks as this didnt seem to affect the reading/displaying , only slowing the server from responding with the xml
    1024 x 645 - 33K
    44.jpg 33.5K
Sign In or Register to comment.