Math help needed!

I'm trying to get a temperature humidity sensor to compare to another to determine if the amount of humidity is high and if so start an exhaust fan. Program runs fine but I want to change from a humidity comparison to a dewpoint comparison to make it more reliable. In that calculation I need to take the log() of a number. I know that I need to import java.lang.Math for the function but I cannot get it working.

I know it is the log() function causing issues because I've removed that part of the equation and it runs through the sub-routine fine. This is in a driver not and app, could that be the issue?


// *?*?*?*?*?*?*?*?*?*?*?*?*?                
                def DewPoint = dewpt(ftemp,humid)
                if(logEnable) log.info "Current Humidity: ${DewPoint}"
                sendEvent(name: "calcDewPt", value: DewPoint)
// *?*?*?*?*?*?*?*?*?*?*?*?*? 

...
def dewpt(temp,humd) {
    if(logEnable) log.info "DewPoint: ${temp}f -> ${humd}%"
    C1=-10214.165
    C2=-4.8932428
    C3=-0.005376579
    C4=1.92024e-7
    C5=3.55758e-10
    C6= -903447e-15
    C7=4.1635019
    C8=-10440.397
    C9=-11.29465
    C10=-0.027022355
    C11=1.28904e-5
    C12=-2.47807e-9
    C13=6.5459673
    ln=0.4342944819
    Tr=459.67+temp
    if (temp < 32) {
        def double lnPws=C1/Tr+C2+C3*Tr+C4*Tr**2+C5*Tr**3+C6*Tr**4+C7*log(Tr)/ln
    } else {
//        lnPws=C8/Tr+C9+C10*Tr+C11*Tr**2+C12*Tr**3+C13*log(Tr)/ln  *** Commented out for trouble shooting
        def double lnPws= Math.log(11.638)
    }
    if(logEnable) log.info "DewPoint lnPws: ${lnPws} -> ${ln}**"  // Never gets here!
    Pws= exp(lnPws)
    Pw=humd*Pws
    lnPw=log(Pw)/ln
    if (temp < 32) {
        Td=90.12+26.412*lnPw+0.8927*lnPw*lnPw
     } else {
        Td=100.45+33.193*lnPw+2.319*lnPw*lnPw+0.17074*lnPw**3+1.2063*Pw**0.1984
     }
    if(logEnable) log.info "DewPoint: ${Td}f -> ${Pws}--"

    return Td
}

Thanks for any suggestions

Are you showing any errors? I barely know what I'm talking about, but could it be that your integer is not a double type?

So the error is (possibly not declaiming double correctly .. I'll chase that now) in ...

...
    def double lnPws= Math.log(11.638)
...

Which is about 2/3 the way through the sub-routine.

You never said what the exact problem was, but here's a guess: is this getting shown as null when you print the value on your log.info line? If so, that's because you're declaring this variable inside your if/else (actually two different ones, each with their own scope, only inside the if or else and no longer accessible once you're outside that block).

To fix, declare this variable somewhere before that so it is still in scope by the time you need it. Right before (and outside of) your if is one place that would work. What you wrote should work, though in Groovy you'll normally see something like this:

Double lnPws
if (temp < 32) {
   lnPws = // ...
// ...

Solved with your assistance: Declaration of double was the trick ....

def dewpt(temp,humd) {
    def double lnPws
    def double Pws
    def double Pw
    def double lnPw
    
    if(logEnable) log.info "DewPoint: ${temp}f -> ${humd}%"
    C1=-10214.165
    C2=-4.8932428
    C3=-0.005376579
    C4= 0.000000192024
    C5= 0.000000000355758
    C6= -0.0000000000000903447
    C7=4.1635019
    C8=-10440.397
    C9=-11.29465
    C10=-0.027022355
    C11=1.28904e-5
    C12=-2.47807e-9
    C13=6.5459673
    ln=0.4342944819
    Tr=459.67+temp
    if (temp < 32) {
        lnPws=C1/Tr + C2 + C3*Tr + C4*Tr**2 + C5*Tr**3 + C6*Tr**4 + C7*Math.log(Tr)
    } else {
        lnPws= C8/Tr + C9 + C10*Tr + C11*Tr**2 + C12*Tr**3 + Math.log(Tr)*C13
    }
    Pws= Math.exp(lnPws)
    Pw=humd*Pws/100
    lnPw=Math.log(Pw)
    if(logEnable) log.info "DewPoint: Tr = ${Tr}R -> lnPws = ${lnPws} -> Pws = ${Pws} -> Pw = ${Pw} -> lnPw = ${lnPw}"
    if (temp < 32) {
        Td=90.12+26.412*lnPw+0.8927*lnPw**2
     } else {
        Td=100.45+33.193*lnPw+2.319*lnPw*lnPw+0.17074*lnPw**3+1.2063*Pw**0.1984
     }
    if(logEnable) log.info "DewPoint: ${Td}f"

    return Td
}

Thanks ALL.

2 Likes

Typically you would use either "def" or "Double" but not both. def is used to define an untyped variable. Also be careful with doing math on doubles, you can get odd decimals, its a java thing. For the best precision decimals use type BigDecimal.

https://www.baeldung.com/groovy-def-keyword#:~:text=The%20def%20keyword%20is%20used,is%20an%20optionally-typed%20language.

Info about the double issues

1 Like

Thanks. I have a lot of internal apps to fix.

Obviously this is purely a hobby for me but I really enjoy the stuff I can do with it.

I switched back to "import java.math.BigDecimal" and everything still worked.
Thanks for the extra input on my work. It is bound to pay off in the future.

BigDecimal is imported by default in Groovy, including the Hubitat app and driver environment, and it should not be necessary to do so yourself. If you find the need to do so, something else is probably going on...