Trying To Read Wind Speed, Noise On Input?

I'm trying to count pulses from an anemometer that gives 36 pulses per revolution using pin 25 on a ESP32WROOM development board. But even at very slow rotation, the pulse count jumps to the 300s. No rotation displays 0. Increasing the rotation doesn't change the Count. It always stays in the 300s.

I've tried various code found on-line with the same results so I'm missing the bigger picture apparently. The attached code is me simply trying to figure out why 1 pulse causes the Count to show 300.

Pin 25 is pulled low externally and driven from a transistor going high to 2.9 volts. My scope displays clean square waves that vary in width with rotation speed. Adding 100nf cap to the input caused the count to drop from the 300s to the mid-100s.

I'm not a coder as you can tell so any guidance and recommendations are appreciated.

unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 1000;    // the debounce time; increase if the output flickers
 
int pinInterrupt = 25;
 
int Count = 0;
 
void onChange()
{
  if ( digitalRead(pinInterrupt) == HIGH )
    Count++;
}
  
void setup()
{
  Serial.begin(9600); //Initialize serial port
  pinMode( pinInterrupt, INPUT);// set the interrupt pin
 
  //Enable
  attachInterrupt( digitalPinToInterrupt(pinInterrupt), onChange, RISING);
   
}
 
void loop()
{
  if ((millis() - lastDebounceTime) > debounceDelay)
  {
    lastDebounceTime = millis();
    
   Serial.println(Count);
    
  //  Serial.print((Count * 8.75)/100);
    
    Count = 0;
    
  }
  delay(1);
}

That sounds like contact bounce, what is the bandwidth of your scope? What is the level of the signal plus and minus? How is the transistor configured in the circuit.

Scope bandwidth is 20MHz. Signal goes from 0 to 2.9 volts.

Correction: pin 25 is pulled high externally and a 2N3904 pulls that to ground. I changed the code to reflect the falling signal but no improvement. I wasn't aware that a transistor had contact bounce. The wind pulses are generated from a opto-interrupt transistor on the outdoor sensor that drives the 2N3904 located inside at the ESP32.

If you are serious about help, you need to show us the complete code you have.

The code I posted above is all I have at this time.

Can't be! You have an attach interrupt with function name, but the function does not appear in what you posted. How did you compile and test that code?

No point checking if the pin is HIGH. You already know it is HIGH because the interrupt trigger is RISING.

This function is where you should be debouncing. Your "debouncing" code in loop() isn't debouncing anything, it's printing the count every second. That's a good thing to do, but it isn't debouncing!

PaulRB I was using an example from this web page:

Not knowing the details of the debouncing lines, I assumed they worked.
Can you tell me what I need to do to make the debouncing code work?

unsigned long lastDebounceTime = 0;  // the last time the input pin was toggled
const unsigned long debounceDelay = 10;    // the debounce time; increase if the measured windspeed is much higher than actual

unsigned long lastMeasurementTime = 0;  // the last time the windspeed was measured
const unsigned long measurementInterval = 1000; // desired time between windspeed measurements
 
const int pinInterrupt = 25;
 
volatile int Count = 0; // volatile because updated by interrupt and read in other code
 
void onChange()
{
  if (millis() - lastDebounceTime > debounceDelay) {
    lastDebounceTime = millis();
    Count++;
  }
}
  
void setup()
{
  Serial.begin(115200); //Initialize serial port with a 21st century board rate
  pinMode( pinInterrupt, INPUT);// set the interrupt pin
 
  //Enable
  attachInterrupt( digitalPinToInterrupt(pinInterrupt), onChange, RISING);
   
}
 
void loop()
{
  int newCount;
  if (millis() - lastMeasurementTime > measurementInterval)
  {
    noInterrupts(); // protect reading Count
    newCount = Count; // read Count
    Count = 0; // reset for next period
    interrupts(); // re-enable interrupts quickly to avoid missing any
    
   Serial.println(newCount);
    
  //  Serial.print((newCount * 8.75)/100);

    lastMeasurementTime += measurementInterval;

  }
}

Being a beginner yourself, you are unable to know that you are copying code from other beginners.

The type of anemometer they use on that web page does not need to be debounced, I suspect. It uses either optical sensor or hall sensor (magnetic) and they don't bounce. Only mechanical switches bounce, such as the reed switch inside my anemometer.

Are you sure your anemometer needs to be debounced? I guess the fact that you are getting unexpectedly high counts means it might need debouncing.

Can you give more detail about the anemometer? You said 36 pulses per rotation, but what's the maximum windspeed and the number of rotations per second at a known windspeed?

What's the purpose of the transistor you mentioned? Please post a schematic showing how it's all wired.

They do not but they respond to the input signal which if it has bounce the output will amplify it. Posting an annotated schematic would help.

The wind speed sensor uses an IR source and detector with a round plastic disc and 36 black squares around the outside that make/break the IR beam. I have attached the schematic of the transistor circuit used to drive pin 25 of the ESP32. I used the same circuit the manufacturer of the weather station used in their display console. I don't have this console so this is why I am attempting to build my own.

The manufacturer was only able to provide me with this formula they used to calculate wind speed. Frequency =(W)-0.1933/0.0975 The original software writers are no longer available and this was the only thing the present staff could provide.

I was able to compile the example code you posted but only get this from the serial monitor:

rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:1344
load:0x40078000,len:13964
load:0x40080400,len:3600
csum err:0x8f!=0xc9
ets_main.c 371
ets Jun 8 2016 00:22:57

Thank you for your assistance!!
speed

PaulRB My error regarding the serial monitor output error. I had another pin pulled low on the ESP32 while trying to upload your code.

I'm running out of time today but after successfully uploading the code you posted, it appears to now be properly counting pulses!!

So even though I am not using any mechanical switches, a debounce is still needed?

Did you cut off the bottom part of the schematic? It does not show a connection to the ESP32, or a connection to the anemometer. But there are 2 wires disappearing off the bottom of the schematic.

Did you copy this correctly? It is a formula for frequency, not windspeed. It could be solved to give windspeed, assuming W represents windspeed. But if so, what are the units of windspeed? MPH, KPH, m/s? Whatever, the formula is wrong, it must be because the units don't match on each side of the "=". If that "-" was a "*" or "/", that would make more sense.

Theoretically, no.

I made several changes to your original code.

I added debounce code to the interrupt routine. With an optical encoder, it should not be needed. Probably needs more adjusting because it will limit the maximum wind speed that can be detected.

I protected the code where Count is read in loop() by briefly disabling interrupts. But since Count is a 32-bit int due to the ESP32 having a 32-bit CPU, that is not strictly necessary either.

I made Count volatile, because it is updated by an interrupt function and read outside the interrupt function. So maybe that's what fixed it.

Give your original code a try, making just one change: make Count volatile.

I enjoyed reading about the IR interrupt, the pin will be LOW or HIGH for shorter times depending on RPM?

Time with micros(), not millis(). Know that micros has() a grain of 4 but the unit is still ms/1000. And millis() is +/- 1 so for close use micros()!

You can work with just collecting IR detect pulses in micros().
How long it blocked tells me appx speed. And too long no change is appx stopped.

An Uno can poll that pin and do something about it over 50x per ms, interrupts are for shorter events.

and make it unsigned since Count will never be negative?

Could the instrument be interfered with? It's likely tested, no?

I'm wondering if polling the pin every 20 ~ 64 micros would be close enough to get vane to vane turn time to needed # of places?

You could do that, yes. But I can't see that a signed integer is going to be a problem, whether it's 16 or 32 bits.

Don't understand what you are asking!

It probably could be polled, but that would take a lot of CPU cycles.

I don't know why this anemometer was designed with 36 pulses per revolution, to me it seems totally overkill. My anemometer gives 2 pulses per revolution, but if it gave only 1, that would still be fine.

Could that be due to stray, reflected IR affecting your detector?

The OP could say what the max wind speed and 'mometer RPM there is and enough to calculate detect LOW time. I have a feeling that it will be read LOW many times at max speed.

It takes very few cycles to read a port and mask the pin bit read, like two or three where the mask stays in a cpu register then 2 cycles.