OWL2pe and BASIC Stamp to anemometer
Here is calibration data from a couple of popular anemometers:
mph = 1.789 * Hertz
mps = 0.8 * Hertz
The anemometer is connected to an i/o pin on the
OWL2 or BASIC Stamp with a pullup resistor (~2k to 20k).
Use the higher
resistance value when the wiring to the anemometer is short and the
lower value when the wiring is long or subject to leakage or
noise. The pullup resistor can go either to a power supply or to
to
another Stamp i/o pin. The advantage of using another Stamp pin
is that it can be made high only when it is time to count
pulses, to save power if need be. Note that the anemometer switch
can stop anywhere in its
travel, with the switch either open or closed. The 100 ohm
resistor is built into the DV6410 anemometer, and it protects the reed
switch from overcurrent that would cause sparking and shorten its
life. The 470 ohm resistor is there to protect the Stamp
pin from ESD.
We'd like to count the number of pulses in a time interval, which
is directly proportional to windspeed. Counting the signal from the Davis 6410 for 2.25 seconds
will give a result directly in units of mph,
mph = 2.25 * counts / seconds ' (so counts=mph when seconds=2.25)
Here is how to implement this on the OWL2pe (Stamp BS2pe) data logger:
wind var byteThe syntax of the BASIC Stamp COUNT command includes the duration parameter, which on the original BS2 and on the BS2e is one millisecond units. But it is different on the other Stamps, 0.72 mS on the BS2pe, 0.4mS on the BS2sx and 0.287 mS on the BS2pe. So the parameter that goes in the units slot for those stamps is different, always to get the 2250 mS total count time.
COUNT wpin,3125,wind ' the BS2pe marks time in units of 0.72 milliseconds, so 2250 mS / 0.72 mS per unit = 3125 units
Sometimes windspeed must be returned directly in other units. Meters per second and miles per hour are the most common units.
mps = mph * 0.447Here are other COUNT commands useful with the Davis anemometers:
mph = mps * 2.237
wind var byteIt may be convenient to count for some constant length of time and then convert mathematically to units of windspeed. For example, counting for 5 seconds:
COUNT wpin,3125,wind ' BS2pe, 1 mph resolution with Davis, count for 2.25 seconds.
DEBUG "mph=",DEC wind,CR
COUNT wpin,6250,wind ' BS2pe, 0.5mph resolution with Davis, count for 4.5 seconds.
DEBUG "mph=",DEC wind*5/10,".",DEC1 wind*5,CR
COUNT wpin,1397,wind ' BS2pe, 1 mps resolution with Davis, count for 1.006 seconds
DEBUG "mps=",DEC wind,CR
COUNT wpin,2794,wind ' BS2pe, 0.5 mps resolution with Davis, count for 2.012 seconds
DEBUG "mps=",DEC wind*5/10,".",DEC1 wind*5,CR
wind var byte
COUNT wpin, 1389*5, wind ' BS2pe, count for 5.0 seconds, 1389 is 1 second on the 'pe
wind = wind */ 5760 / 5 ' */576 is stampese for *2.25
DEBUG "mph=",DEC wind/10,".",DEC1 wind ' display as xx.x
LOW ct515data
PAUSE 10
INPUT ct515data
SERIN ct515data, $54, [SPSTR 12] ' 1 status, and 5 data words,
Please refer to the CT515 document for advice on how to set up and read out the CT515 data.x VAR Byte
GET 2, word x
x = x */ 5760 / interval ' */ 576 is stampese for 2.25 mph per hertz (576/256=2.25)
DEBUG "mph=",DEC wind/10,".",DEC1 wind ' display as xx.x
wind VAR Byte
windacc VAR Word ' accumulation for average
windmax VAR Byte ' maximum
windmin VAR Byte ' minimum
Nsmpl VAR Word ' number of samples
windmin = 255
' frequently, e.g. once per 10 seconds
COUNT wpin,2250,wind ' windspeed to one mile per hour resolution
windmax = wind MIN windmax ' maintains maximum windspeed
windmin = wind MAX windmin ' maintains minimum windspeed (there is not a typo, MAX does for minimum)
windacc=windacc + wind '
Nsmpl=Nsmpl+1 ' one more sample
' infrequently, only when it is time to log data
result=windacc/Nsmpl ' compute average
GOUSB logdata ' log it
result=windmax ' fetch maximum
GOSUB logdata ' log it
windavg=0 ' reinitialize
Nsmpl=0
windmax=0
windmin=255
Windspeed tends to be sporadic, and the distribution highly
skewed. Infrequent samples (e.g. hourly) of windspeed tend to be
quite low, compared to the average or maximum. It is best to sample
the windspeed frequently. The sum may need to use double
precision math (32 bits) if lots of samples are taken, enough to
overflow the accumulator.
Here is our double precision averaging routine for t he
OWL2pe. This routine expects the new raw value in a word
variable wx, and the variable wpe1 is a pointer to a 4 byte buffer in
the scratchpad that holds the current accumulation, and the variable wj
holds the current number of samples. At exit, the current
average value (accumulation over number of samples) is returned in the
variable wx, the scratchpad buffer contains the new accumulation, and
wj is unchanged. The routine uses a couple of other
variables (wy and wz) for intermediate computations.
Average4:
' Double Precision averaging routine
' enter with
' wpe1 = address of 2 words (4 bytes) allocated in SPram
' wj = number of samples
' wx = value to accumulate
' exit with
' wx = current average value result
' wj and wpe unchanged
' uses wy and wz for computation
GET wpe1,Word wy ' get low word of accumulation
wy=wy+wx ' accumulate
PUT wpe1,Word wy ' save
GET wpe1+2, Word wz ' high word of accumulation
IF wy<wx THEN ' accumulate iff carry from low word
wz=wz+1
PUT wpe1+2,Word wz
ENDIF
' now double precision divide by # of samples
wx=65535//wj*wz//wj+wz+(wy//wj)
wx=65535/wj*wz+(65535//wj*wz/wj)+(wy/wj)+(wx/wj)
RETURN
Here is a circuit that can convert the output of the Davis anemometer (Or any anemometer that uses a switch-type output), into a voltage for input to an analog to digital converter. The output of this circuit can be calibrated to give 1 volt output at 100 miles per hour by adjusting RT1. The network of resistors and capacitors at the input is there to turn the on-off switch action into a series of bipolar pulses for input into the LM2917 tachometer chip (National Semi). Also, the circuit at the input protects the circuit from lightning induced surges. Anemometers are available that have a AC generator, and these produce an AC sine wave signal. Those anemometers can also use this circuit, but remove R1, R3 and R6 and replace C1 with a jumper.
Where Dm=xxx is the tag for direction, xxx is 0 to 359 degrees, Sm=xxx.x is the tag for speed, xxx.x in miles per hour, and Th=sxx.x is the tag for temperature, sxx.x in Celsius, signed. Here is the OWL2pe routine that asks for and receives the data.0R0Dm=xxxSm=xxx.xTh=xxx.xCRLF
The wind direction returned is not reliable when the wind speed is less than 1mph, so accumulations of direction are made only when the speed is greater than 1 mph.wmt50_acquire:
de485 CON 11 ' rs485 direction pin
dt485 CON 10 ' rs485 data pin
wbaud CON 813 ' 1200 baud
HIGH de485
SEROUT DT485,wbaud,["0R0!"] ' command to WMT50 to send data
LOW de485
SERIN dt485,wbaud,1000,wmt50_timeout,[WAIT("0R0"),WAIT("Dm="),DEC ww,WAIT("Sm="),DEC wy1,DEC wy0,WAIT("Th="),SDEC wz1,DEC wz0]
' DEBUG DEC ww,TAB,DEC wy1,".",DEC1 wy0,TAB,DEC wz1,".",DEC1 wz0,CR
HIGH de485 : HIGH dt485 ' leave RS485 as driver asserted
wy = wy1 * 10 + wy0 ' mph * 10 coding is wy1 is units, wy0 is tenths
wz = wz1 * 10 + (-wz1.BIT7 ^ wz0) + wz1.BIT7 ' negative t sign extend
' returns with ww=direction degrees, wy=speed mph, wz=temperature Celsius
wmt50_continue:
RETURN
There are two ways we connect the wind vane:
Wind vane pot connects between 4.096 volts reference output
and
common, and the wiper goes into one of the OWL2c input channels. The
potentiometer produces a voltage between 0 and 4.096 that varies
linearly with azimuth. This configuration requires three
conductors in a cable from the logger out to the anemometer.
Wind vane pot is configured as a variable resistor, and this
resistance is transmitted over 2 wires back to the data
logger. At the data logger, the variable resistance is in
series with a fixed resistor to the 4.096 volt excitation, and the
junction of the two is connectecd to the OWL2pe input
channel. The OWL2pe computes the resistance from the input
voltage, and from that the azimuth.
The figure shows the recommended mounting, with the wind vane arm pointing out from the mast. There are often restraints on the mounting and considerations of the prevailing winds to take into consideration when deciding which way to point the arm. The OWL2pe has provision to enter the direction that the mounting arm is actually pointed, and the OWL2pe compensates properly to return the correct azimuth. The Davis anemometers, as supplied from the factory, have the crossover point when the tail of the vane is back along the arm and the tip of the vane points out from the arm. So that direction is nominally North.
The potentiometer in the wind vane is free to move through 360 degrees, but there is a dead band of about 10 degrees at the crossover point in the potentiometer travel. As shown in the graph, the output signal is zero volts for 5 degrees before the signal starts its linear rise, and the signal is maximum voltage through 5 degrees at the other extreme of the travel. The dead band varies some from unit to unit. If you are looking for the greatest possible accuracy, then you will need to find out exactly what the dead band is. You can also find out exactly what the dead band is by cutting a hole and a slit in a sheet of polar graph paper and putting it around the vane, and taking readings of w1 as a function of position of the vane in degrees. If you do not need great accuracy (5%) then simply use the typical value, 10 for the dead band calibration factor.
.
The following formula in the OWL2, BASIC Stamp, converts the reading from millivolts to azimuth:
WDead con 10 ' dead band in degrees
WDead2 con WDead/2 ' half the dead band in degrees
WDfs con 360-WDead ' full scale span
gosub ADread 'result is 0-5120 millivolts
azimuth = result */ WDfs / 20 + WDead2
The formula for azimuth produces in readings that go from 5 degrees to 355 degrees. The reading in the dead band is 5 degrees from zero to 5 degrees azimuth, and 355 degrees for 355 to 360 degrees azimuth.
{The */ operator is described in the document on math
operations.}
' wind direction
READ windAZcal0,Word wz ' value in degrees that must be added to reading to give true direction
ww=ww + wz +360//360 ' corrected azimuth
IF wy>10 THEN PUT degWindAZ,Word ww ' direction update only if windspeed > 1mph
GET degWindAZ,Word wx ' most recent value even if not updated
GOSUB showdec0
If you only need 16 compass points, then you can use a simpler
formula. Wind vanes often don't require much accuracy, and in such
cases, 16 compass points may suffice.
compass = result + 160 // 5120 / 320
16 compass points come out as 320 millivolts per compass point. The "+160" offsets the result, so that compass point zero comes out at 22.5 degrees on each side of north, and so on, the compass points are centered on the 16 cardinal directions.
When you put the vane up on a pole, you may have to orient it with the dead band pointing in a different direction. Then you only need to enter that direction in the calculation as an offset::
WDead con 10 ' dead band in degrees
WDead2 con WDead/2 ' half the dead band in degrees
WDfs con 360-WDead ' full scale span
WDoff con 105 ' offset=105 degrees (example)
gosub ADread 'result is 0-5120 millivolts
azimuth = result */ WDfs / 20 + WDoff +WDead/2 // 360
In this example, the azimuth goes from 110 degrees, smoothly
through 360 to zero at North azimuth, and then back to 100 degrees at
the other side of the dead band, and jumps back to 110 degrees at the
midpoint of the dead band.
Here is a routine for averaging the aneometer direction
component. Note that this has to be done using the sine and
cosine components. Note also that a wind that blows
half from one direction and half from its opposite will have an average
direction of zero. Average direction is only of limited usefulness.
The following algorithm keeps an accumulation of the compass points that are visited by the anemometer over a period of time. This is stored in word variable, so that each bit represents one compass point. At the end of an interval, you might find for example that this variable is %1100000000000001, which means the wind directions detected were N, NNE, and NNW.average_azimuth:
' at entry ww is current corrected azimuth 0 - 360
ww = ww */ 182 ' convert to 0 to 256 brads
wx = COS ww
GET wdcos, Word wz
wx = wx + wz
PUT wdcos, Word wx
wx = SIN ww
GET wdsin, Word wz
wx = wx + wz
PUT wdsin, Word wx
GET wdcos,Word ww
GET samplesSP, Word wj
wx = -wx.BIT15 ^ (ABS wx / wj) + wx.BIT15
ww = -ww.BIT15 ^ (ABS ww / wj) + ww.BIT15
wx = wx ATN ww
RETURN
The following algorithm counts the number of ones as a measure of the total spread of wind directions:GET windCompass,Word wx ' get the current accumulation
IF wy>10 THEN
wz = wz * 4 + 1485 // 1440 / 90 // 16 ' wz is 360 degrees as input, 0 to 15 output with north =-11.25 to +11.25
wx = DCD wz | wx ' OR new direction into existing accumulation
PUT windCompass,Word wx ' only do update accumulation if speed is >1.0 mph
ENDIF
GOSUB showbin16 ' e.g. %1100000000000001
' finds the spread
' counts the number of 1s in wx
countOnes:
N=0
DO WHILE wx
wx = wx - (DCD (NCD wx - 1)) ' knock down one bit at a time
N=N+1 ' count how many
LOOP
RETURN