2024-05-27

WS3085 wind speed codes

I've been examining the raw signals from several Aercus Instruments weather stations, mainly the WS3085 and similar. Two bytes of the long (80-bit) messages appear to carry wind speed, one for the average, and one for gust.

By recording the signals and simultaneously observing the console, I could get a mapping between the signal and reported wind speed. Here are some plain speeds:

byte 1 (wind speed, bits 32-39) console speed (km/hr)
00000000 0.0
00000001 1.1 (corrected signal after possible misreading)
00000010 2.5
00000011 3.6
00000100 5.0
00000101 6.1
00000110 7.2
00000111 8.6

Here are some gust speeds (on a windier day):

byte 2 (gust speed; bits 40-47) console gust speed (km/hr)
00000110 7.2
00001000 9.7
00001001 11.2
00001110 17.3
00001111 18.4
00010001 20.9
00010010 22.0
00011101 35.6
00100000 39.2

Where they overlap, gust speeds and plain wind speeds appear to use the same representation, and larger numbers correspond to greater speeds, so I'm going to assume that they indeed use the same representation. However, there's no consistent ratio shown in the recordings above, but it's always (so far) between 1.1 and 1.25. The mean is ~1.218, which works closely for codes 5 and 8, but over-reports for 1, 3 and 6, and under-reports for 2, 4, 7, 9, 14, 15, 17, 18, 29 and 32. Perhaps using different units would have yielded a more consistent ratio, e.g., the code is first multiplied and rounded to get the speed in another unit, then multiplied again and rounded again to get the speed in km/hr. Other units are m/s (÷3.6), mi/hr (÷1.609) and knots (÷1.852), and none of these are going to yield a nicer ratio.

To get a more intuitive understanding, here's a plot of speeds against raw values, but with a couple of anticipated scales subtracted:

Those drops are all by the same amount. The increments aren't, but some are similar. What's going on?

Here's the Gnuplot script:

set title 'Wind ratio'
set datafile sep ','
set xlabel 'signal'
set ylabel 'speed (km/hr)'
set term pdf monochrome linewidth 0.1
set output 'windratio.pdf'
set key left bottom
set grid xtics
set xtics 1
show grid
plot 'windratio.csv' using 1:($2-$1*1.25) with linespoints title 'observed - 1.25x', \
  'windratio.csv' using 1:($2-$1*1.225) with linespoints title 'observed - 1.225x'

And here's windratio.csv:

0,0
1,1.1
2,2.5
3,3.6
4,5.0
5,6.1
6,7.2
7,8.6
8,9.7
9,11.2
14,17.3
15,18.4
17,20.9
18,22
29,35.6
32,39.2

Looks like you can reproduce that table with something like this:

def conv(i):
    return i * 1.1 + \
        ((i + 3) // 5 + (i + 1) // 5) * 0.3 + \
        ((i + 16) // 25) * 0.1

for i in range(0, 33):
    print('%2d: %4.2f' % (i, conv(i)))
    continue

In other words, add 1.1 per unit, then add 0.3 every 5 units from positions 1 and 4, and add a further 0.1 at 9 (and I'm guessing that's every 25 units, but it must be at least 24).

According to Kevin, just multiply by 0.34, and round to the nearest tenth, to get metres per second. Converting to km/h and rounding again gives all the reported values. Try the following, and you'll see all the reported values matching:

def conv(i):
    return i * 1.1 + \
        ((i + 3) // 5 + (i + 1) // 5) * 0.3 + \
        ((i + 15) // 24) * 0.1

def conv2(i):
    return int(i * 3.4 + 0.5) / 10 * 3600 / 1000

for i in range(0, 33):
    print('%2d: %4.1f %4.1f' % (i, conv(i), conv2(i)))
    continue

[2024-06-10 Minor corrections to table; inferred expression]
[2024-06-12 Linked to Kevin's post with "the answer"; corrected bit positions]

No comments:

Post a Comment