lheijst / weewx-rtldavis

weewx driver that captures data from software-defined radio using the rtldavis software.
GNU General Public License v3.0
14 stars 5 forks source link

Does not calculate below zero F values properly #14

Open LloydR opened 1 year ago

LloydR commented 1 year ago

This is how I changed the program rtldavis.py so it will properly calculate the below zero temperatures. This is in the parsing the packet from the ISS message type 8 if temp_raw != 0xFFC: if pkt[4] & 0x8:

digital temp sensor

                    # remove the simple 1 step
                    # temp_f = temp_raw/10.0 to account for negative values or below zero
                    #
                    # need a temp_raw1 so the debug statement can work since I changed temp_raw to an int.
                    temp_raw1 = temp_raw
                    # What a pain, the just shifting (as above) fails when temperature goes below 0 F
                    # So need to convert 2 bytes to a signed int for proper values when temp < 0 F
                    # int.from_bytes is a Python3 expression, would need to do struct.upack for python2
                    temp_raw = int.from_bytes([pkt[3], pkt[4]], byteorder='big', signed=True)
                    # The above temp raw (a 16 bit value) needs to be divided by 160 to get true temp
                    # The 12 bit value is already divided by 16 (ie 12 bits = 16 bits shifted right 4 places)
                    # but the 16 bit value is not
                    temp_raw = temp_raw / 16
                    #
                    temp_f = temp_raw / 10.0
                    temp_c = weewx.wxformulas.FtoC(temp_f) # C
                    dbg_parse(2, "digital temp_raw=0x%03x temp_f=%s temp_c=%s"
                              % (temp_raw1, temp_f, temp_c))
t-licious commented 1 year ago

I am also experiencing this problem. For reasons I never quite got to the bottom of, I was only successful getting my weather station up and running with the Python 2 variant of weewx, so this proposed solution will not work in my case. I am not knowledgeable enough to work out the python 2 version of the correction above either and would appreciate a solution that would work for both versions.

LloydR commented 1 year ago

t-licious I used NumPy int16() as below but it was a different program and not Luc's. Also NumPy support for Python2 has been removed. If I were you I would revisit making weewx run on Python3. I assume that pretty soon any new weewx program updates will only run on Python3. Or you could read up on struct.unpack and modify the program using that. elif typepac == 8: # it is temperature xtemp = ((pac[3] << 8) + pac[4]) outTemp = int16(xtemp)/16

loopData.outsideTemperature = (int16_t)(word(radio.DATA[3], radio.DATA[4])) >> 4;

    packetData[0] = outTemp/10.0
    if (debug == True or tempdebug == True):
        print "outsideTemperature =", outTemp, packetData[0], pac[3], pac[4]

Here are some byte data vs temperatures I observed using int.from_bytes digital temp_raw=0xf40 temp_f=-19.14375 digital temp_raw=0x072 temp_f=11.45625 digital temp_raw=0xfef temp_f=-1.65 digital temp_raw=0xff9 temp_f=-0.64375 digital temp_raw=0xffd temp_f=-0.25 digital temp_raw=0xfff temp_f=-0.05 digital temp_raw=0x000 temp_f=0.05625 digital temp_raw=0x000 temp_f=0.0625 digital temp_raw=0x001 temp_f=0.16875 digital temp_raw=0x06b temp_f=10.75625

LloydR commented 1 year ago

Using ChatGPT I asked it to allow either python2 or 3 to change the temperature to a signed int. This is what it gave me from what I had done for python3. Pretty easy if one knew python2 and 3 I guess. Also there is a check for python2 or 3 on weewx-rtldavis starting line 87 where one could put the import struct in the python2 try.

Yes, "import struct" is a Python 2 command. It is used to provide pack and unpack functions for working with variable-length binary data described using special format strings. In this case, the struct.unpack function is used to convert the two bytes from the packet to a signed integer, specifically using the format '>h' which stands for "signed short in native byte order"

import struct

if temp_raw != 0xFFC: if pkt[4] & 0x8:

digital temp sensor

    # remove the simple 1 step (shown below)
    # temp_f = temp_raw/10.0 
    #
    # account for negative values or below zero
    #
    # need a temp_raw1 so the debug statement can work since temp_raw is changed to an int.
    temp_raw1 = temp_raw
    #  Just shifting (as above) fails when temperature goes below 0 F
    # So need to convert 2 bytes to a signed int for proper values when temp < 0 F
    if sys.version_info[0] == 2:
        temp_raw = struct.unpack('>h', pkt[3:5])[0]
    else:
        temp_raw = int.from_bytes([pkt[3], pkt[4]], byteorder='big', signed=True)
    # The above temp raw (a 16 bit value) needs to be divided by 160 to get true temp
    # The 12 bit value is already divided by 16 (ie 12 bits = 16 bits shifted right 4 places)
    # but the 16 bit value is not
    temp_raw = temp_raw / 16
    #
    temp_f = temp_raw / 10.0
    temp_c = weewx.wxformulas.FtoC(temp_f) # C
    dbg_parse(2, "digital temp_raw=0x%03x temp_f=%s temp_c=%s"
              % (temp_raw1, temp_f, temp_c))