Wind Speed and Direction

I use Arduino Mega 2560 for metrological station.
As part of it I connected a PEET BROS. ULTIMETER® PRO Anemometer.

The calculation of the wind Speed done by counting the speed pulses during 1 sec.

Wind Direction
Direction is calculated as the relative timing (phase relationship) between contact closures of the two reed switches. This is a non-linear, sinusoidal relationship. We regard repeated actuation of the speed reed as the reference and arbitrarily define “North” as the vane orientation that causes the two reed switches to close at the same time. “South” is the vane orientation that
causes the direction reed to close exactly halfway between two closures of the speed reed.
Note that the open and closed intervals are not necessarily equal and may differ between the two switches.

  1. Can I connect the speed and direction pulses to D2 and D3 inputs?
  2. I need the code for it, because I didn’t understand from all the web sites I read how to do it.


  1. Can I connect the speed and direction pulses to D2 and D3 inputs?



  1. Can I connect the speed and direction pulses to D2 and D3 inputs?

Yes, with Atmega328 based boards you could use D2 with interrupt-0 and D3 with interrupt-1 to create interrupt handling routines when the reed switch closes.

Although: When adding a rain gauge that also uses a reed switch, you'd then have to use either a pinchange interrupt for the rain gauge reed switch or have to use a different board that supports more than 2 hardware interrupts.

2. I need the code for it, because I didn't understand from all the web sites I read how to do it.

The interrupts routines need to keep track about:

  • the current and the last micros() timestamp of the speed switch signal
  • the current micros() timestamp of the direction switch signal
  • the count of the speed switch signals

Your normal code then can evaluate the data provided by the interrupt handling routines to calculate

  • wind speed
  • wind direction

Wind direction is then calculated from:

  • time difference of last two signals from the speed switch
  • time difference of the direction switch and one signal from the speed switch
    by linear interpolation between 0° and 360°.

The signal bandwidth and need for timing accuracy is low. I would suggest trying timer controlled polling before using interrupts for this task.

According to this document:
It would rotate at about 4,000 RPM at 181 MPH. That's 42us per degree of revolution. So if you sample at millisecond speed, your max error would be about 25 degrees.

You don't need to sample wind speed continuously, you could do it every few seconds. That does have timing ramifications at low speeds that you would need to sort out.

If you want the best accuracy, then yes, interrupts are best. Careful about switch bounce.

Any luck with this? I’m trying to do the same thing though I’m using a Pro Mini instead. I’ve connected it to pins 2 & 3 utilizing external interrupts and microsecond timing. I’m using a minimum high pulse duration of 2000 microseconds to count as a valid pulse. This seems to work well as switch de-bouncing for both wind speed and direction. Now I’m just trying to figure out how to make sure that I have a series of three valid pulses (wind-direction-wind) to ensure that I’m calculating valid wind speed and direction. It’s not as easy as it sounds - at least for me. I’ll share my code when I get back in town but would be interested in hearing how you’re approaching it.

I was just about to say something about debouncing - reed switches have
a short bounce time (a few ms) so that sounds about right.

If you debouncing is done in an interrupt routine for each signal it should
just work - say you trigger on a leading edge, you check against the last
recorded time to see if this is a bounce, and if so just return. If not a bounce,
record the new value of micros for both debouncing and calculating the angle
(which you can do directly in the ISR).

Make sure to sample volatile variables with interrupts disabled for just long
enough to copy them, ie:

volatile int angle ;   // updated only in the ISRs

int readAngle ()
  noInterrupts () ;
  int result = angle ;
  interrupts () ;
  return result ;