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.
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!
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.
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:
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.
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.
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.
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.