Frequency/pulse counter interrupt

hello,
I am trying to count reluctor teeth with a hall effect sensor. I need the system active when "speedPin" reads over 433counts/hz? and the system deactivated when "speedPin" reads less than 433.
The code works "as is" without the interrupt function. Now I am attempting to add a "anti-stall" function.

The more I research frequency counting/pulse counting, the farther I get from where I want to be.
This is my first UNO project.

Here is what I have so far - minus frequency counting

Thanks,

```
//Torque converter control module v1.2

//60% duty cycle, 30.0hz, mech. pushbutton On/Off switch

//Debounce'd switch

//speedPin = master switch (<433 counts = system disabled, = >433 counts system enabled)

int switchPin = 3;

int outPin = 9;

int speedPin = 1;

int outLevel = 0; //duty cycle 0-255

boolean lastButton = LOW;

boolean currentButton = LOW;

void setup()

{

TCCR1B = TCCR1B & B11111000 | B00000101; // for PWM frequency of 30.64 Hz

pinMode (switchPin, INPUT);

pinMode (outPin, OUTPUT);

pinMode (speedPin, INPUT);

}

boolean debounce (boolean last) //debounce function start

{

boolean current = digitalRead(switchPin);

if (last != current)

{

delay (5); //debounce delay in ms

current = digitalRead(switchPin);

}

return current; //debounce function end

}

void loop()

{

currentButton = debounce(lastButton);

if (lastButton == LOW && currentButton == HIGH)

{

outLevel = outLevel + 153; //duty cycle set to 60% (starts @ "0" then increases by 153 every button press)

}

lastButton = currentButton;

if (outLevel > 255) outLevel = 0; //sets outLevel back to "0" if 255 is exceeded

analogWrite(outPin, outLevel);

}```

By far the best and most complete tutorial is this one (for ATmega Arduinos, Uno etc.): Gammon Forum : Electronics : Microprocessors : Timers and counters

If you just want to determine the frequency, not RPM, then you should be able to reuse this code I copied out of my tachometer.
This uses the pulsein function and in my testing it has given quite accurate results.
Just set the minimum expected frequency, which maybe lower than 1 but not 0. I havent tested that :slight_smile:

You'll have to work your inputs and outputs into it.

I've found it's handy to debounce your switches externally so you dont need a delay or additional complex code. A capacitor and resistor are usually enough.

I searched far and wide for tachometer and speedometer programs and tested many of the methods I found, including such as using interrupts. This method here seemed most stable and worked best for me.
Bonus is no tricky timers or interrupts - pulsein and tiny bit of maths does everything.

This may not compile as-is since I pulled it out of a bigger program, but it should be easy to get going with your requirements.

// Frequency counter
// uses microseconds via the pulsein functions
//
// Does not use interupts
//
// There will be some slight blocking delay
// as pulsein waits for very slow pulses
//
// pulsein timeout is calculated
// from the lowest expected frquency


//==================================================
// Set this to the minimum expected frequency in Hz
float Min_Freq = 10
//==================================================

// RPM frequency input pin
const int speedPin = 1;              

// RPM variables
unsigned long hightime, lowtime, pulsein_timeout;
float freq, period;

//---------------------------------------------------

void setup() {

// Digital inputs
pinMode(speedPin, INPUT);

// Maximum time for pulseIn to wait in microseconds
// Use the period of the lowest expected frequency, and double it
if (Min_Freq < 1) Min_Freq = 1;
pulsein_timeout = 1000000.0 / Min_Freq * 2.0;

}  // End void setup

//---------------------------------------------------

void loop() {

hightime = pulseIn(speedPin, HIGH, pulsein_timeout);
lowtime = pulseIn(speedPin, LOW, pulsein_timeout);
period = hightime + lowtime;
freq = 1000000.0 / period;

// Limit the frequency range if necessary
// to remove erroneous readings
freq = constrain(freq, Min_Freq, 2000);

// Your stuff here
// at this point freq is a float
// so convert to an interger or whatever required

if (freq >= 433) {do something};
else {some other thing};

// maybe display the freq


}  // End void loop

//---------------------------------------------------

Does the reluctor have all of its teeth, or is it like a crank position sensor that is missing one tooth to provide an index?

No, it is symmetrical.

Thank you!

This is wonderful. Thank you.

So to detect 'faster than 433 Hz' you can just check the time between pulses. If it is shorter than 2309 microseconds, the rate is faster than 433 Hz.

// speedPin = master switch (<433 Hz = system disabled, = >433 counts system enabled)
int speedPin = 1;

void speedPulseISR()
{
  unsigned long currentMicros = micros();
  static unsigned long lastMicros = 0;

  if (currentMicros - lastMicros > 2309)
  {
    // Fewer than 433 pulses per second
    // ENABLED
  }
  else
  {
    // More than 433 pulses per second
    // DISABLED
  }
}

void setup()
{
  pinMode(speedPin, INPUT);
  attachInterrupt(digitalPinToInterrupt(speedPin), speedPulseISR, RISING);
}

void loop()
{
}