Gå til innhold
  • Bli medlem
SK951

Kalibrere temperatursensor

Anbefalte innlegg

Hei, 

 

har diverse RF og Z-wave sensorer i leiligheten (bla. Fibaro, Multisensor 6 og en rekke Clas/biltema RF-sensorer). Problemet er at disse viser ulike temperaturer, og nå vet jeg egentlig ikke helt hvilke jeg skal stole på. Har prøvd å legge alle ved hverandre og valgte deretter en tilfeldig sensor som referanse (som da ble Multisensor). Differansen mellom dem øker dog nokså mye utover døgnet. Nå har jeg til eks. 18.4, 18.1 og 14.7 i samme rom (noe ulik høyde på disse, men ikke nok til å forsvare differansen på nesten 4 grader). 

 

Forslag til termometer jeg kan bruke til referanse? Hvordan har dere løst dette? Hva med posisjonen på sensoren?

Del dette innlegget


Lenke til innlegg
Del på andre sider

Jeg styrte med det samme for en tid siden. 

Mitt inntrykk er at temperatursensorene er nokså unøyaktige. 

 

Jeg satte flere multisensorer, phillips hue sensorer og diverse 433mhz sensorer på samme sted i ett varmt rom. Store avvik (flere grader)

Regnet ut gjennomsnitt og kalibrerte alle så de hadde lik temperatur. 

 

Deretter flyttet jeg alle til ett kladt rom. 

På nytt store avvik. 

 

Endte med å gi opp og godta ett visst avvik. De sensorene som skal være i varme rom, kalibrerte jeg på ca 22 grader, mens de som skal være i kjeller kalibrerte jeg på ca 15 grader. 

 

Del dette innlegget


Lenke til innlegg
Del på andre sider

Jeg sliter med det samme - jeg har åpen løsning med stue, gang og kjøkken og jeg mener jeg har 8 sensorer tilsammen som gir meg temperatur. Jeg endte med å skrive et script som gir meg en snitt-temperatur av disse, og som også tar hensyn til om noen av de går offline eller har for gamle verdier.
Jeg bruker det samme scriptet for utetemperatur - der har jeg vel tre sensorer på forskjellige sider av huset.

Scriptet skriver til to virtuelle devicer i HomeSeer, som igjen kan brukes som input til andre ting.

 

virtualTemp.JPG.a66a6dd595ca16fca33a3e46029105d3.JPG

 

Dersom det er noen interesse for det kan jeg se om jeg ikke får lagt ut scriptet her.

  • Like 3

Del dette innlegget


Lenke til innlegg
Del på andre sider
16 minutter siden, HSv skrev:

Jeg sliter med det samme - jeg har åpen løsning med stue, gang og kjøkken og jeg mener jeg har 8 sensorer tilsammen som gir meg temperatur. Jeg endte med å skrive et script som gir meg en snitt-temperatur av disse, og som også tar hensyn til om noen av de går offline eller har for gamle verdier.
Jeg bruker det samme scriptet for utetemperatur - der har jeg vel tre sensorer på forskjellige sider av huset.

Scriptet skriver til to virtuelle devicer i HomeSeer, som igjen kan brukes som input til andre ting.

 

virtualTemp.JPG.a66a6dd595ca16fca33a3e46029105d3.JPG

 

Dersom det er noen interesse for det kan jeg se om jeg ikke får lagt ut scriptet her.

 

Det ville vært interessant. 

Blir i så fall mitt første script i HS, og det synes jeg det er på høy tid at jeg forsøker meg på. 

Del dette innlegget


Lenke til innlegg
Del på andre sider

Min versjon brukes til å beregne både innendørs og utendørs temperatur - derfor vil du finne variabler "Indoor...." og "Outdoor..."
Du trenger ikke bruke begge, siden de blir kalt med forskjellige input parameter.

Advarsel:
dette er ikke helt plug&play, men jeg har forsøkt å gjøre det litt brukervennlig iallefall. Det kreves at du vet hvordan du legger inn et script, og litt om hvordan du editerer det for å tilpasses ditt bruk. Det er testet på Linux, og ikke forsøkt kjørt på Windows.

 

Du kan først lage ett virtuelt device som du får gjennomsnittstemperaturen skrevet ut til. (Du kan gjerne lage to - ett for Standard avviket også, dersom du ønsker det - men det er ikke nødvendig) Det er forsåvidt ikke påkrevd å ha noe "out-device" - i så fall skrives det bare ut i loggen.

 

 

Sett son "Status Only Device" (ikke påkrevd - bare for å unngå å få "kontroller-knapper")

virtualTemp3.JPG.1b0b563715af47bc7272d0ec36332faf.JPG

 

Noter deg "Reference ID" - dette skal du legge inn i scriptet

virtualTemp4.JPG.5dd0424c2690d2184a2dd1a8e6d89ce1.JPG

 

Formatere output.

virtualTemp5.JPG.c172f40c933f36608cb0e2050e026554.JPG

 

 

Og slik startes scriptet - knock yourself out med andre triggere om du vil 🙂

virtualTemp2.JPG.8ffd3aa7e10c7b467b23f25769032166.JPG

 

 

Spoiler

' TempAverager.vb, v. 1.2
' Input param: location, as defined further down the script.
' In this example location can be "indoor" or "outdoor"
'   HSv, Feb. 2019


Public module GlobalVars
  public shared infoLog  as boolean = true      ' Log whats happening...?
  public shared warnLog  as boolean = true      ' Log warnings...? (you really should!)
  public shared debugLog as boolean = false     ' Log a bit more...?
end module

public sub Main(ByVal _params as Object)
  ' Enter the device ref. for the sensors you want to use,
  ' and enter a calibration value if needed:
  '     '0'   means the thermometer is ~correct
  '     '-1'  means it seems to show 1 deg more than the actual temperature
  '     '0.5' means it seems to show half a deg less than the actual temperature
  ' The script demands that you enter the parameters, one for each sensor, even if it is zero.
  ' On a general note - be careful to use calibrations, unless you are quite sure it is valid.
  ' After all - this script is meant to average out several un-certain values :-)

  dim location as string = _params.Tostring

  dim Sensor() as integer       ' ref ID for temp. sensors, as found in HomeSeer
  dim Calibr() as integer       ' Calibration for each sensor.
  dim devAvg   as integer       ' ref ID for Average tenp dev. (0 means don't save to any device)
  dim devStdev as integer       ' ref ID for StDev (0 means don't save to any device)
  dim LogID    as string        ' Identifier for the log
  dim oldish   as integer       ' mins - how old before we only let it count half? (0 means use all data)
  dim tooOld   as integer       ' mins - how old before we scrap the data? (0 means use all data)

  ' When input parameter = "indoor"A (i.e. location is "indoor")
  dim IndoorSensor()  as integer = {  85,   80, 739, 745, 742, 754, 704, 940}
  dim IndoorCalibr()  as integer = {-0.7, -0.5,   0,   0,   0,   0,   0,   0}
  dim IndoordevAvg    as integer = 951
  dim IndoordevStdev  as integer = 0
  dim IndoorLogID     as string  = "Indoor Temp"
  dim Indooroldish    as integer = 60
  dim IndoortooOld    as integer = 120

  ' When input parameter = "outdoor"
  dim OutdoorSensor() as integer = { 874, 494, 748}
  dim OutdoorCalibr() as integer = {   0,   0,   0}
  dim OutdoordevAvg   as integer = 978
  dim OutdoordevStdev as integer = 0
  dim OutdoorLogID    as string  = "Outdoor Temp"
  dim Outdooroldish   as integer = 60
  dim OutdoortooOld   as integer = 120

  select case location
    case "indoor"
      Sensor   = IndoorSensor
      Calibr   = IndoorCalibr
      devAvg   = IndoordevAvg
      devStdev = IndoordevStdev
      LogID    = IndoorLogID
      oldish   = Indooroldish
      tooOld   = IndoortooOld
    case "outdoor"
      Sensor   = OutdoorSensor
      Calibr   = OutdoorCalibr
      devAvg   = OutdoordevAvg
      devStdev = OutdoordevStdev
      LogID    = OutdoorLogID
      oldish   = Outdooroldish
      tooOld   = OutdoortooOld
    case else
      Logging("Temp. averager", "warn", "Location '" & location & "' does not exist")
      exit sub
  end select

        ' Info:  85  = Living room thermostat
        '        80  = Hallway thermostat
        '       739  = Sensor 433 Stue 1 Temp.
        '       745  = Sensor 433 Stue 2 Temp.
        '       742  = Sensor 433 Kjøkken Temp.
        '       754  = Living room Couch/TV Sensor
        '       704  = Kitchen sensor
        '       940  = Bookshelf sensor

        '       874  = Backyard sensor
        '       494  = Entrance sensor
        '       748  = Sensor 433 Back yard
        '      1019  = WeatherXML, St. Johannes



' ---------------------------------------------------
'  There should not be anything to change below here
' ---------------------------------------------------

  ' Negative time...? You ain't Cristopher Lloyd!
  ' ...or more than i year(ish)...? - I consider that "all sensors at all times"
  if (oldish < 0) orelse (oldish > 530000) then oldish = 0
  if (tooOld < 0) orelse (tooOld > 530000) then tooOld = 0
  if (oldish > tooOld) andalso (tooOld > 0) then oldish = tooOld

  ' A few declarations
  dim numSensors       as integer = Sensor.GetLength(0)
  dim Temp(numSensors) as decimal
  dim LastUpd          as DateTime
  dim deviceName       as string
  dim averageTemp      as decimal = -1
  dim StandardDev      as decimal = -1
  dim sumTemp          as decimal
  dim sumDeviation     as decimal
  dim samples          as decimal

  ' Collect data
  ' --------------------------------------------------------------

  ' Loop through all the sensors
  for i as integer = 0 to (numSensors - 1)
    if hs.DeviceExistsRef(Sensor(i)) then
      Temp(i)     = hs.DeviceValueEx(Sensor(i)) + Calibr(i)             ' DeviceValueEx gives me the decimal value :-)
      dim currentTemp as string   = Temp(i).ToString
      dim LastUpd     as DateTime = hs.DeviceLastChangeRef(Sensor(i))   ' What time was the dev. last updated?
      dim timeDiff    as TimeSpan = (Date.Now - LastUpd)                ' ...how long ago is that?
      dim addonText   as string

      ' Prettify the timediff - i.e. remove everything after the last ".", which are millisecs
      dim myts       as string = timeDiff.ToString
      dim timestring as string = myts.Substring(0, myts.LastIndexOf("."))

      ' Check if it is too long since the device-value was updated
      if (timeDiff.TotalSeconds > tooOld*60) andalso (tooOld > 0) then                  ' Too old? - junk it!
        addonText = "Age: " & timestring & " > " & tooOld & " min. - Disqualified"
        Temp(i) = -1000
      else if (timeDiff.TotalSeconds > oldish*60) andalso (oldish > 0) then             ' Almost too old?
        addonText = "Age: " & timestring & " > " & oldish & " min. - half weight"
        sumTemp += (Temp(i) / 2)
        samples += 0.5
      else                                                                              ' Not old at all :-)
        addonText = "Age: " & timestring
        sumTemp += Temp(i)
        samples += 1
      end if

      ' Do we want detailed logging...?
      deviceName = hs.GetDeviceByRef(Sensor(i)).name(hs)
      Logging(LogID, "debug", "Device " & Sensor(i) & ", " & deviceName & ": " & currentTemp & "°C - " & addonText)
    else
      Logging(LogID, "warn", "Device " & Sensor(i) & " does not exist")
    end if
  next

  ' Data in 'da house - lets do the math and show what we got!
  ' --------------------------------------------------------------

  ' Avearege - do we have any data to calculate it?
  if samples > 0 then
    ' Average temperature (with 2 decimals)
    ' but don't write it to the device yet, as we want to calculate StDev first
    averageTemp = Math.Round((sumTemp / samples), 2)

    ' Do some calculations for the StDev.
    dim counter as integer = 0
    for i as integer = 0 to (numSensors - 1)
      if Temp(i) > -1000 then
        sumDeviation += (Temp(i) - averageTemp)^2
        counter += 1
      end if
    next

    ' Standard deviation - but only if there is any data
    if counter > 0 then
    ' Standard deviation (with two decimals)
      StandardDev = Math.Round(Math.Sqrt(sumDeviation / counter), 2)
      ' write the standard deviation to the StDev device - if we have one defined and it exists
      if devStdev = 0 then
        Logging(LogID, "debug", "No device defined for StDev")
      else
        if (not hs.DeviceExistsRef(devStdev)) then
          Logging(LogID, "warn", "StDev device " & devStdev & " does not exist")
        else
          hs.SetDeviceValueByRef(devStdev, CStr(StandardDev), True)
        end if
      end if
    else
      Logging(LogID, "warn", "Not enough valid data to calculate StDev")
    end if

    ' Write average to the device - if there is an existing device defined.
    ' (... now that we also have the StDev and can make a proper deviceString)
    dim devString as string = averageTemp & "°C (StDev: " & StandardDev & "°C - " & samples & " samples)"
    if devAvg = 0 then
      Logging(LogID, "warn", "No device defined for average temp")
    else
      if (not hs.DeviceExistsRef(devAvg)) then
        Logging(LogID, "warn", "Avg.temp device " & devAvg & " does not exist")
      else

        hs.SetDeviceValueByRef(devAvg, CStr(averageTemp), True)
        hs.SetDevicestring(devAvg, CStr(devString), True)
      end if
    end if

    ' Do we want any logging?
    Logging(LogID, "debug", "Sum: " & sumTemp & " - Samples: " & samples )
    Logging(LogID, "info", devString)
  else
    Logging(LogID, "warn", "Not enough valid data to calculate average temp")
  end if

end sub

' Routine for writing to the log
Sub Logging(ByVal LogID as string, ByVal msgType as String, ByVal msg as string)
  dim msgComplete as string
  dim writetolog as boolean = false

  select case msgType
    case  "info"
      if GlobalVars.infoLog then
        msgComplete = "Info: " & msg
        writetolog = true
      end if

    case  "debug"
      if GlobalVars.debugLog then
        msgComplete = "Debug: " & msg
        writetolog = true
      end if

    case  "warn"
      if GlobalVars.warnLog then
        msgComplete = "Warning: " & msg
        writetolog = true
      end if

    case else
      msgComplete = "Msgtype '" & msgType & "' undefined"
      writetolog = true
  end select

  if writetolog then hs.Writelog (LogID, msgComplete)

end sub

' That's all folks!

 

 

Til slutt må du editere scriptet, slik at du bruker de Ref. ID som gjelder for dine sensorer. Du kan bruke så mange eller så få du vil - du bare forlenger/forkorter array'ene som det passer.

Du kan også legge inn andre verdier for når du vil tillegge sensoren halv vekt, og for når du vil forkaste verdien.

Jeg håper dette kan være til hjelp for noen, og at beskrivelsen/forklaringen min ikke er helt på bærtur. Koden er helt sikkert ikke optimal, men det får stå sin prøve. Utregningen av standardavvik er heller ikke helt korrekt, men "riktig nok" for mitt bruk.

 

For ordens skyld - jeg bruker ikke noe device for standardavvik, og derfor er refID der satt til null. Om du ønske, så lager du en device og legger inn refID i stedet for null.

 

Endret av HSv
"Clearification" :-)
  • Like 3

Del dette innlegget


Lenke til innlegg
Del på andre sider

All tilbakemelding blir satt veldig stor pris på - det er kun et par uker siden jeg begynte å kode i VB så jeg vet at koden ikke er optimal.

Del dette innlegget


Lenke til innlegg
Del på andre sider

Hvis du ikke har prøvd det enda, så anbefales tenScripting for Visual Studio. Full intellisense når man programmerer er veldig hendig. :) 

(Og så får man automatisk stor i i Integer, etc ;) ) 

Del dette innlegget


Lenke til innlegg
Del på andre sider

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå

×