Debounce and Read Davis Anemometer 6410 wind speed

This is more a solution than a question. I have been using this anemometer for some time. Compared to an analog anemometer, there is no question that this anemometer is a pain you know where... this is a digital anemometer, every time it turns, it produces a pulse, dealing with this pulse is the story I will try to clarify.

So the Owner's Manual says the following.

V = P(2.25/T)
V = speed in mph
P = no. of pulses per sample period
T = sample period in seconds

To use the T, you must create some kind of timer. I am using Blynk, this app allows you to create timers very easily. If you don't use Blynk, you can use millis(), etc. DAVIS1 works very well, DAVIS2 is just to show you that no matter how much time you record the pulses, you will get the same wind speed. The key part is to divide 2.25 by the number of seconds you are recording the pulses.

Here is the entire code I am using to test it, but first, I debounce the wind pin:

const int  WindPin = 4;
volatile int pulse1 = 0;   // Davis Anemometer Pulse Tracking
volatile float mph = 0.0; // Davis MPH Variable
bool lastState     = LOW; // Wind Pin  previous state
bool currentState;        // Wind Pin current reading 

volatile int pulse2 = 0; 
volatile float mph2 = 0.0;

/* Debounced the Wind Pin */
void Davis_ISR()
{
  currentState = digitalRead(WindPin); // Read Wind Pin state
  if (lastState == HIGH && currentState == LOW)
  {
    pulse1++;
    pulse2++;
    
  }
  lastState = currentState; // Save Wind Pin last state
}

/* Per Davis Manual:  2.25 (2250 mS) seconds is the sample period  */
void DAVIS1()
{
  mph = pulse1 * 0.75; /* timer for 3 Seconds. */
  Blynk.virtualWrite(V14, "Davis WS ",  String(mph, 2), " (", pulse, ")",  "\n");
  Blynk.virtualWrite(V16, mph); // Super Chart
  pulse1 = 0; // Clear tracking variable pulse1, and start all over again. 
}

void DAVIS2()
{
  mph2 = pulse2 * 0.375; /* timer for 6 Seconds. */
  Blynk.virtualWrite(V20, "Davis WS ",  String(mph2, 2), " (", pulse2, ")",  "\n");
  pulse2 = 0; // Clear tracking variable pulse2, and start all over again. 
}

If we set timer 1 to 3 seconds (3000mS) for Davis1, and divide 2.25 by 3, we get 0.75
if we set timer 2 to 6 seconds (6000 mS) for Davis2, and divide 2.25 by 6, we get 0.375

These two functions should produce the same wind speed assuming the wind speed remains constant.
If the wind speed does not remain constant, the wind speed will be different, but is easy to see why, Davis1 will indicate the wind speed sooner than Davis2, right?

You attach the interrupt in setup like so:

  pinMode(WindPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(WindPin), Davis_ISR, CHANGE);

Also in setup, here are my two timers:

timer.setInterval(3000, DAVIS1);
  timer.setInterval(6000, DAVIS2);

So your resolution is either 0.75MPH or 0.375MPH

The shorter the sampling period, the more responsive it will appear because the number of pulses delivered by the device is averaged over a shorter period and hence the result is delivered more quickly. However, if the sampling period is too short, the results will show spikes. This will be most noticeable during periods of low wind speeds where multiple samples may be taken in the interval between pulses. A nice smoothing algorithm is required.

Where is setup()? Where is loop()?

There's probably no need to make this variable volatile. I don't believe that Blink timers use interrupts, they just use millis() internally.

Variables that are updated in interrupt routine should be protected when they are read by your main code. This may not be necessary for int or even long variables on 32-bit MCU, but is important on 8-bit MCU. You did not say what you're of arduino you are using. The time when they are protected should be kept to a minimum. Like this:

void DAVIS1()
{
  noInterrupts();
  int p1 = pulse1;
  pulse1 = 0; // Clear tracking variable pulse1, and start all over again. 
  interrupts();
  mph = p1 * 0.75; /* timer for 3 Seconds. */
  Blynk.virtualWrite(V14, "Davis WS ",  String(mph, 2), " (", pulse, ")",  "\n");
  Blynk.virtualWrite(V16, mph); // Super Chart
}

There's an optimisation/simplification you can make here:

if (lastState == HIGH && currentState == LOW)

This code checks for the falling edge of the signal from the sensor. You can achieve the same thing using:

  attachInterrupt(digitalPinToInterrupt(WindPin), Davis_ISR, FALLING);

then there is no need for that test, or reading the sensor pin in the interrupt routine.

Finally...

No debouncing is performed by your code!

Yes, I thought that as well. It may possibly have a small debouncing effect in that, in the early stages of the bounce, the signal that triggered the ISR may have already gone by the time the digitalRead() is executed. I personally would have used a timed lockout to prevent a signal being accepted to quickly following the last one. Anyway, since it is a "digital" Anemometer, it could well be that the signal is already clean.
I'm not so sure about your statement about volatile though. It appears, in this case to be a conventional ISR based on his later code snippet.

Davis_ISR() is a conventional ISR. But DAVIS1() is a timer routine and I don't believe they are ISR at all, they are just called by a Blink function called from loop() based on millis(). pulse1 is updated in a conventional ISR, so needs to be volatile, but mph is only updated in a timer routine, so I don't think that needs to be volatile.

Oh yes, you are right. I see now that you were referring to the specific variable mph. I read it too quickly and assumed that you had referred generally to them all which would include pulse1, pulse2 etc. which should be volatile.

Even a sensor based on magnetic reed switches could be described as "digital" and they can suffer from bouncing. But if the sensor uses optical or hall effect sensors, the signal is probably clean.

The anemometer I use for my home weather station uses a reed switch and produces a pulse once per revolution of the cups. I use an R-C-Diode/Schmidt trigger debounce circuit.

I prefer to measure instantaneous wind speed as well as average so I measure the period between pulses as well as the number of pulses per 600 seconds using an interrupt service routine triggered by the rising edge of the anemometer signal. The latter gives a wind speed more like reported by the weather bureau and the former is just something I'm interested in.

Thanks a lot, Folks. I will keep in mind suggestions and ideas. How accurate this anemometer is? I have no way to test that, I can only go by what the Manual says. I wish I can have a wind tunnel like this: Anemometer | PCE Instruments The anemometer is part of my Personal Weather Station feeding data to https://www.wunderground.com/

I calibrated the thermometer. My home thermostat also has been calibrated with the same instrument.


This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.