SHT-11 temp&RH sensor readings Needs stabilizer
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
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
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.
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
' 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/10Your 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)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) return1. 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.
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 ithe 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 returnLooks like it did the job pretty good , resulting in a lean graphI also ended up removing the locks as this didnt seem to affect the reading/displaying , only slowing the server from responding with the xml