Trouble reading an anemometer

Hello-

I’m having trouble reading an anemometer and am curious if anyone is available to take a peek at my code/project. The anemometer is from Fascinating Electronics. I’ve connected to it using CAT5 cable and 22 gauge, shielded cable. The 22 gauge cable seems to give a reading more consistently. Might just be stronger wire going in and out of the breadboard. Also, I removed the PCB with diode from the reed switch and soldered directly to the reed switch. I’ve been having trouble for about a week now so I have been stripping things down. Removal of the PCB and diode appear to have made the sensor read more consistently.

From the instruction manual under ‘Create your own software’, the equation to calculate wind speed (MPH) is 1.758*(2*Hz)+2.121 .

A PCB with reed switch connected.
Demo Image 1

The PCB that was removed on the setup mentioned below.
Demo Image 2

I have tried three different scripts to solve the problem. Below is a schematic of the circuit. In general, the results that I get are vary wildly and are not reasonable. In all cases, when I turn the anemometer one full revolution (two passes over the switch(two magnets in the anemometer cap)), several passes are recorded (between 11 and 50+). I’ve played with the debounce over a range of 15-155 milli-seconds but it doesn’t seem to give me much improvement.

You will probably find some bugs in the code below. Thank you in advance for your help.
Demo Image 3
Demo Image 4
Demo Image 5

Approach 1: Count the number of times the switch is closed using a high level interrupt. Note: Connect Anemometer to D3

/* Modified by Kellen Nelson 5/18/2015

Sketch to read David Wind Vane de ON7EQ Dec 2011
http://www.qsl.net/on7eq/projects/arduino_davis.htm
    To disable interrupts:
    cli();                // disable global interrupts 
    and to enable them:  
    sei();                // enable interrupts

On RJ-45 plug terminals:

Black =  pulse from anemometer. Connect to Digital 2 pin, and use a 4k7 resistor as pull up to + 5v.
         use a 10 to 22nF capacitor from pin D2 to ground to debounce the reed switch of anemometer
Red =    Ground
Yellow = + 5v (reference of potentiometer)
*/

volatile unsigned long rpsTops;  
// rps tops counter in interrupt routine                             
volatile unsigned long ContactTime;  
// Timer to avoid conatct bounce in interrupt routine                              

float rps;
float mph;
volatile long now;
volatile long later;
volatile float deltatime;
volatile unsigned long last_micros;

#define rpssensor (3)
//The pin location of the anemometer sensor

////////////////////////////////////////////////////////////////////
void setup() { 
    Serial.begin(9600);
    pinMode(rpssensor, INPUT);
    attachInterrupt(1, readrps, FALLING); 
} 

/////////////////////////////////////////////////////////////////////

void loop() { 
    // measure rps
    rpsTops = 0;   //Set NbTops to 0 ready for calculations
    now=millis();
    sei();         //Enables interrupts
    delay (5000);  //Wait 5 seconds to average
    cli();         //Disable interrupts
    later=millis();
    deltatime=(later-now)/1000;
    Serial.print("Millis: ");Serial.println(millis());
    Serial.print("Delta_time: ");Serial.println(deltatime);
    Serial.print("rpsTops: ");Serial.println(rpsTops);
    rps = (rpsTops/2)/deltatime;
    Serial.print("rps: ");Serial.println(rps);
    mph = 1.758*(rps)+2.121;
    Serial.print("MPH: ");Serial.println(mph);
    delay(1000);
}

//// This is the function that interrupt calls to measure  rps  
 void readrps ()   { 
    if((long)(micros() - last_micros) >= 15 * 1000) {
    //if ((millis() - ContactTime) > 25 ) {  
    // debounce of REED contact. With 15ms speed more than 150 km/h can be measured
        rpsTops++; 
        //ContactTime = millis();
        last_micros = micros();
}
}

Approach 2: Count the number of times that the switch is closed using a lower level interrupt. Honestly, this bit of code is beyond my current understanding. BUT, it runs and gives me a reading–wrong, of course.
Note: Connect Anemometer to D5

// Modified by Kellen Nelson 5/18/2015

// Timer and Counter example
// Author: Nick Gammon
// Date: 17th January 2012
//http://www.gammon.com.au/forum/?id=11504
//Top code block
// Input: Pin D5

// these are checked for in the main program
volatile unsigned long timerCounts;
volatile boolean counterReady;

// internal to counting routine
unsigned long overflowCount;  //I am uncertain what the overflow counts are doing.
unsigned int timerTicks;
unsigned int timerPeriod;

float mph;

void startCounting (unsigned int ms) 
  {
  counterReady = false;         // time not up yet
  timerPeriod = ms;             // how many 1 mS counts to do
  timerTicks = 0;               // reset interrupt counter
  overflowCount = 0;            // no overflows yet

  // reset Timer 1 and Timer 2
  TCCR1A = 0;             
  TCCR1B = 0;              
  TCCR2A = 0;
  TCCR2B = 0;

  // Timer 1 - counts events on pin D5
  TIMSK1 = bit (TOIE1);   // interrupt on Timer 1 overflow

  // Timer 2 - gives us our 1 mS counting interval
  // 16 MHz clock (62.5 nS per tick) - prescaled by 128
  //  counter increments every 8 µS. 
  // So we count 125 of them, giving exactly 1000 µS (1 mS)
  TCCR2A = bit (WGM21) ;   // CTC mode
  OCR2A  = 124;            // count up to 125  (zero relative!!!!)

  // Timer 2 - interrupt on match (ie. every 1 mS)
  TIMSK2 = bit (OCIE2A);   // enable Timer2 Interrupt

  TCNT1 = 0;      // Both counters to zero
  TCNT2 = 0;     

  // Reset prescalers
  GTCCR = bit (PSRASY);        // reset prescaler now
  // start Timer 2
  TCCR2B =  bit (CS20) | bit (CS22) ;  // prescaler of 128
  // start Timer 1
  // External clock source on T1 pin (D5). Clock on rising edge.
  TCCR1B =  bit (CS10) | bit (CS11) | bit (CS12);
  }  // end of startCounting

ISR (TIMER1_OVF_vect)
  {
  ++overflowCount;               // count number of Counter1 overflows  
  }  // end of TIMER1_OVF_vect


//******************************************************************
//  Timer2 Interrupt Service is invoked by hardware Timer 2 every 1ms = 1000 Hz
//  16Mhz / 128 / 125 = 1000 Hz

ISR (TIMER2_COMPA_vect) 
  {
  // grab counter value before it changes any more
  unsigned int timer1CounterValue;
  timer1CounterValue = TCNT1;  // see datasheet, page 117 (accessing 16-bit registers)
  unsigned long overflowCopy = overflowCount;

  // see if we have reached timing period
  if (++timerTicks < timerPeriod) 
    return;  // not yet

  // if just missed an overflow
  if ((TIFR1 & bit (TOV1)) && timer1CounterValue < 256)
    overflowCopy++;

  // end of gate time, measurement ready

  TCCR1A = 0;    // stop timer 1
  TCCR1B = 0;    

  TCCR2A = 0;    // stop timer 2
  TCCR2B = 0;    

  TIMSK1 = 0;    // disable Timer1 Interrupt
  TIMSK2 = 0;    // disable Timer2 Interrupt
    
  // calculate total count
  timerCounts = (overflowCopy << 16) + timer1CounterValue;  // each overflow is 65536 more
  counterReady = true;              // set global flag for end count period
  }  // end of TIMER2_COMPA_vect

void setup () 
  {
  Serial.begin(9600);       
  Serial.println("Frequency Counter");
  } // end of setup

void loop () 
  {
  // stop Timer 0 interrupts from throwing the count out
  byte oldTCCR0A = TCCR0A;
  byte oldTCCR0B = TCCR0B;
  TCCR0A = 0;    // stop timer 0
  TCCR0B = 0;    
  
  startCounting (1000);  // how many mS to count for

  while (!counterReady) 
     { }  // loop until count over

	 
	Serial.print("Timer_period = ");Serial.println(timerPeriod);
  // adjust counts by counting interval to give frequency in Hz
  float frq = ((timerCounts *  1000.0)/2) / timerPeriod;
//I'm not sure what why I have to multiply by 1000 above.
  Serial.print ("Frequency: "); Serial.print ((unsigned long) frq); Serial.println (" Hz.");
  float mph = 1.758*(frq)+2.121;
  Serial.print("MPH: ");Serial.println(mph);
  // restart timer 0
  TCCR0A = oldTCCR0A;
  TCCR0B = oldTCCR0B;
  
  // let serial stuff finish
  delay(200);
  }   // end of loop

Approach 3: Measure the time between the falling edge of the pulse produced by the switch closure. Again, gives me a reading but :( ... Note: Connect Anemometer to D3

// Modified by Kellen 5/18/2015
//See last post...
//http://forum.arduino.cc/index.php?topic=13985.15

long pulsewidth1;
float wspeed1;

void setup()
{
   Serial.begin(9600);
   pinMode(3,INPUT);  //Anemometer 1
}

//2.5mph per Hz, pulsewidth is delivered as period in microseconds
void loop()
{
    Serial.print("Millis = ");Serial.println(millis());
    pulsewidth1=pulseIn(3, LOW);  //Anemometer 1
    Serial.print("Pulse width: = ");Serial.println(pulsewidth1);   
    //Wind speed in MPH
    wspeed1=1.758*(1000000/pulsewidth1)+2.121;
    Serial.print("Wind speed: = ");Serial.println(wspeed1);

    delay (2000);
}

If you are wired like Demo Image 3 the reed switch is either open or grounded, the resistor is only drawing power off the power supply.

You don't need the resistor, use internal pullup:

pinMode(3, INPUT_PULLUP);

Very nice. Thanks for the advice. I had the circuit that way initially except I was using an external 10k resistor instead of the pullup resistor. The internal pullup works great for Approach 1 but I am still having problems with the other approaches.

Here is a new link to the circuit.

Approach 1: When I spin it one revolution, I get 2 passes and when I spin it two revolutions I get 4 passes. This is correct because there are two magnets in the cap.

Serial-Approach 1 correct

Approach 2: I still get irregular results. Might be a software problem. **How do I change this code to use D3 instead of D5? Serial-Approach 2-->irregular results

Approach 3: No matter how fast I spin the anemometer, I get a pulse width of 52-54 milliseconds. Plus, this method only measures the time between high and low but it would be more meaningful/useful to get the pulse width between high to high or low to low. Any ideas on how to fix this code.

Approach 3-->regular incorrect results.

Could you post your latest code ?