Looking for suggestions to help debounce hall effect sensor

Hello all. So here's what i have going on. I have a small 7x10 metal lathe that i use for turning parts along with using it for wrapping transformer/inductor coils. In the past i used a reed switch and an arduino and made a turn counter. it worked good, but was temporary and was bulky, so i've decided to make a dedicated rpm meter and turn counter using a hall effect sensor.

For the code, i borrowed a micros() based rpm meter from a guy on youtube, and have been modifying it meet my needs. and so far everything is working well, but i'm looking for suggestions with a small glitch i have. At super slow speeds. like under 60rpm, the hall effect sensor is reading the magnet twice before the magnet passes by, so i have inserted a 100ms delay when it's detected, and that helps a lot, but if i go too slow it'll still registers it twice. But this is wrong because it will effect the counter at higher speeds which will be used on occasion when i'm refilling wire spools. at the moment i'm using an 8mm magnet for the hall sensor, but have ordered and waiting on some 3mm magnets which i hope will help the problem even more.

Ok. here's the setup, and below is the code. I'm using a dpdt switch to activate pin 12 on the arduino which turns off the rpm meter and turns on the turn counter, and the other half of the switch redirects the hall effect sensor from pin 2, which is set an interrupt for the rpm code, into pin 11 to count the turns.

If i'm unable to debounce the turn counter, one idea i had would be placing a 2 hall sensors close to each other, so the magnet has to activate both hall sensors before it will take a count, which seems to be the best way to count without having errors because a couple of these coils i have to wrap needs to be exactly the same. but that seems like it will be hard to do since one hall sensor is an interrupt and is tied directly to the rpm counter, which i am bypassing when i'm using the counter.

thanks ahead for any suggestions.

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);
                // LCD SDA = A4 pin
                // LCD SDL = A5 pin

const byte rpmOff = 12;
#define input 11
unsigned long pulse = 0;    
int var = 0;
byte switchState;



const byte PulsesPerRevolution = 1;
const unsigned long ZeroTimeout = 2000000;
const byte numReadings = 5;  

volatile unsigned long LastTimeWeMeasured;                        // Stores the last time we measured a pulse so we can calculate the period.
volatile unsigned long PeriodBetweenPulses = ZeroTimeout+1000;      // Stores the period between pulses in microseconds.
                                                                  // It has a big number so it doesn't start with 0 which would be interpreted as a high frequency.
volatile unsigned long PeriodAverage = ZeroTimeout+1000;           // Stores the period between pulses in microseconds in total, if we are taking multiple pulses.
                                                                    // It has a big number so it doesn't start with 0 which would be interpreted as a high frequency.
unsigned long FrequencyRaw;                                         // Calculated frequency, based on the period. This has a lot of extra decimals without the decimal point.
unsigned long FrequencyReal;                                         // Frequency without decimals.
unsigned long RPM;                                                  // Raw RPM without any processing.
unsigned int PulseCounter = 1;  
                                                                // Counts the amount of pulse readings we took so we can average multiple pulses before calculating the period.

unsigned long PeriodSum;                                            // Stores the summation of all the periods to do the average.

unsigned long LastTimeCycleMeasure = LastTimeWeMeasured;            // Stores the last time we measure a pulse in that cycle.
                                                                    // We need a variable with a value that is not going to be affected by the interrupt
                                                                      // because we are going to do math and functions that are going to mess up if the values
                                                                    // changes in the middle of the cycle.
unsigned long CurrentMicros = micros();                               // Stores the micros in that cycle.
                                                                     // We need a variable with a value that is not going to be affected by the interrupt
                                                                      // because we are going to do math and functions that are going to mess up if the values
                                                                     // changes in the middle of the cycle.

                                                                      // We get the RPM by measuring the time between 2 or more pulses so the following will set how many pulses to
                                                                      // take before calculating the RPM. 1 would be the minimum giving a result every pulse, which would feel very responsive
                                                                      // even at very low speeds but also is going to be less accurate at higher speeds.
                                                                      // With a value around 10 you will get a very accurate result at high speeds, but readings at lower speeds are going to be
                                                                      // farther from eachother making it less "real time" at those speeds.
                                                                      // There's a function that will set the value depending on the speed so this is done automatically.
unsigned int AmountOfReadings = 1;

unsigned int ZeroDebouncingExtra;                                       // Stores the extra value added to the ZeroTimeout to debounce it.
                                                                        // The ZeroTimeout needs debouncing so when the value is close to the threshold it
                                                                          // doesn't jump from 0 to the value. This extra value changes the threshold a little
                                                                        // when we show a 0.

                                                                      // Variables for smoothing tachometer:
unsigned long readings[numReadings];                                  // The input.
unsigned long readIndex;                                               // The index of the current reading.
unsigned long total;                                                    // The running total.
unsigned long average;


void setup() {
//Serial.begin(115200);
 
 lcd.init();                     
 lcd.backlight();  

   lcd.setCursor(2,0);
   lcd.print("Lathe Sensor");

  pinMode(rpmOff, INPUT);                                         //LOW = rpm reading; HIGH = turn counter
  pinMode(input, INPUT_PULLUP);                       //signal from hall sensor for turn counter

  attachInterrupt(digitalPinToInterrupt(2), Pulse_Event, FALLING);       // Enable interruption pin 2 when going from LOW to HIGH.

  delay(2000);   
     lcd.clear();


}

void loop() {

checkSwitch();
RPMcode();
Turns();

}
                                                                       // The following is going to store the two values that might change in the middle of the cycle.
 void checkSwitch(){

    switchState = digitalRead(rpmOff);
   
   if (switchState == LOW){
     lcd.setCursor(0,0);
     lcd.print("RPM");
   }
    
     if(switchState == HIGH){
     lcd.setCursor(0,0);
     lcd.print("Turns");
   }
 }

  void Turns(){
       
       if (switchState==HIGH){

detachInterrupt(digitalPinToInterrupt(2)) ;

   
   
      if(digitalRead(input) == 0){

delay(100);

var = 1;
pulse++;

     lcd.setCursor(6,1);
     lcd.print(pulse);
}

if(digitalRead(input) == 1) {var = 0;}

delay(1); // Delay for stability.
                                         // delay in between reads for stability
}
}

  
  
  void RPMcode(){                                       // We are going to do math and functions with those values and they can create glitches if they change in the
                                                                       // middle of the cycle.
  LastTimeCycleMeasure = LastTimeWeMeasured;                         // Store the LastTimeWeMeasured in a variable.
  CurrentMicros = micros();                                            // Store the micros() in a variable.





                                                                         // CurrentMicros should always be higher than LastTimeWeMeasured, but in rare occasions that's not true.
                                                                         // I'm not sure why this happens, but my solution is to compare both and if CurrentMicros is lower than
                                                                          // LastTimeCycleMeasure I set it as the CurrentMicros.
                                                                           // The need of fixing this is that we later use this information to see if pulses stopped.
  if(CurrentMicros < LastTimeCycleMeasure)
  {
    LastTimeCycleMeasure = CurrentMicros;
  }





                                                                         // Calculate the frequency:
  FrequencyRaw = 10000000000 / PeriodAverage;                            // Calculate the frequency using the period between pulses.


  

  
                                                                            // Detect if pulses stopped or frequency is too low, so we can show 0 Frequency:
  if(PeriodBetweenPulses > ZeroTimeout - ZeroDebouncingExtra || CurrentMicros - LastTimeCycleMeasure > ZeroTimeout - ZeroDebouncingExtra)
  {                                                                         // If the pulses are too far apart that we reached the timeout for zero:
    FrequencyRaw = 0;                                                        // Set frequency as 0.
    ZeroDebouncingExtra = 2000;                                             // Change the threshold a little so it doesn't bounce.
  }
  else
  {
    ZeroDebouncingExtra = 0;                                                 // Reset the threshold to the normal value so it doesn't bounce.
  }





  FrequencyReal = FrequencyRaw / 10000;                                      // Get frequency without decimals.
                                                                              // This is not used to calculate RPM but we remove the decimals just in case
                                                                                 // you want to print it.





                                                                             // Calculate the RPM:
  RPM = FrequencyRaw / PulsesPerRevolution * 60;                             // Frequency divided by amount of pulses per revolution multiply by
                                                                              // 60 seconds to get minutes.
  RPM = RPM / 10000;                                                          // Remove the decimals.





                                                                                // Smoothing RPM:
  total = total - readings[readIndex];                                          // Advance to the next position in the array.
  readings[readIndex] = RPM;                                                    // Takes the value that we are going to smooth.
  total = total + readings[readIndex];                                          // Add the reading to the total.
  readIndex = readIndex + 1;                                                    // Advance to the next position in the array.

  if (readIndex >= numReadings)                                                 // If we're at the end of the array:
  {
    readIndex = 0;                                                                // Reset array index.
  }
  
                                                                                  // Calculate the average:
  average = total / numReadings;                                                  // The average value it's the smoothed result.


 char string[10];                // Create a character array of 10 characters
                                 // Convert float to a string:
  dtostrf(average, 6, 0, string);  // (<variable>,<amount of digits we are going to use>,<amount of decimal digits>,<string name>)

     lcd.setCursor(0,1);
     lcd.print(string);


}                                                                                // End of loop.




 
void Pulse_Event()                                                                // The interrupt runs this to calculate the period between pulses:
{

  PeriodBetweenPulses = micros() - LastTimeWeMeasured;                                // Current "micros" minus the old "micros" when the last pulse happens.
                                                                                      // This will result with the period (microseconds) between both pulses.
                                                                                       // The way is made, the overflow of the "micros" is not going to cause any issue.

  LastTimeWeMeasured = micros();                                                       // Stores the current micros so the next time we have a pulse we would have something to compare with.



  if(PulseCounter >= AmountOfReadings)                                               // If counter for amount of readings reach the set limit:
  {
    PeriodAverage = PeriodSum / AmountOfReadings;                                      // Calculate the final period dividing the sum of all readings by the
                                                                                         // amount of readings to get the average.
    PulseCounter = 1;                                                                 // Reset the counter to start over. The reset value is 1 because its the minimum setting allowed (1 reading).
    PeriodSum = PeriodBetweenPulses;                                                   // Reset PeriodSum to start a new averaging operation.


                                                                                      // Change the amount of readings depending on the period between pulses.
                                                                                       // To be very responsive, ideally we should read every pulse. The problem is that at higher speeds the period gets
                                                                                      // too low decreasing the accuracy. To get more accurate readings at higher speeds we should get multiple pulses and
                                                                                        // average the period, but if we do that at lower speeds then we would have readings too far apart (laggy or sluggish).
                                                                                       // To have both advantages at different speeds, we will change the amount of readings depending on the period between pulses.
                                                                                        // Remap period to the amount of readings:
    int RemapedAmountOfReadings = map(PeriodBetweenPulses, 40000, 5000, 1, 10);          // Remap the period range to the reading range.
                                                                                         // 1st value is what are we going to remap. In this case is the PeriodBetweenPulses.
                                                                                         // 2nd value is the period value when we are going to have only 1 reading. The higher it is, the lower RPM has to be to reach 1 reading.
                                                                                        // 3rd value is the period value when we are going to have 10 readings. The higher it is, the lower RPM has to be to reach 10 readings.
                                                                                           // 4th and 5th values are the amount of readings range.
    RemapedAmountOfReadings = constrain(RemapedAmountOfReadings, 1, 10);                    // Constrain the value so it doesn't go below or above the limits.
    AmountOfReadings = RemapedAmountOfReadings;                                          // Set amount of readings as the remaped value.
  }
  else
  {
    PulseCounter++;                                                                     // Increase the counter for amount of readings by 1.
    PeriodSum = PeriodSum + PeriodBetweenPulses;                                        // Add the periods so later we can average.
  }
 

Nonsense! It is reading BOTH poles of the magnet. Orient the magnet properly so only one pole passes the sensor.

Why are you using two different routines for rpm and turns counting. Why not just use the interrupt count for turns?

I may only be reading it once, but the code is looping fast enough to register it twice.

So the sensor is NOT bouncing and nothing needed. Fix your software.

I have tried that already and didn't haven't had any luck with it yet. but since it's two separate functions. i just wrote it that way. and since I have to use a switch anyhow to switch it between rpm and the counter, i just figured redirecting the signal was easy.

but i'm still trying to figure everything out as i'm still fairly new at code.

that's what i'm trying to do. I may not be debouncing. but it's having the same effect as debouncing would.

Post what you tried. You can certainly use the switch to set a flag which determines what pieces of the isr are executed.

No, it's not. Set a boolean to true when you read the sensor and it is active,(low or high, I don't know) and if the boolean is set just look for the sensor to change back and don't indicate the sensor has triggered. when the sensor is back to normal, set the boolean to false, and read the sensor. You need something to tell your code NOT to return a value that the sensor is STILL set, which is what you are doing.

I'll have to post it after i redo it again. I've made about 5 decent attempts since yesterday, but keep deleting them once i find out they don't work. the code i posted is the latest working version, and think once i go to a small magnet, i won't have a problem anymore since my glitch gets worse the closer the sensor is too the magnet.

but i'm still learning and looking for the right ways to do coding.

If you want to poll the state of the hall sensor, then you should look at the state change examples of the IDE. You want to detect when the state changes from 0 to 1 (or 1 to 0).

1 Like

yup. you are correct. thanks. i'll work on that.

ok, i'll check that out today.. thanks

I was able to get it fixed, thanks to ya and some other code i had saved, but i still need to better understand how to do it again for future purposes. but now it only reads the magnet once no matter how slow it goes.

  void Turns(){
       
       if (switchState==HIGH){


detachInterrupt(digitalPinToInterrupt(2)) ;

  bool on_state = false;
                                            // counting number of times the hall sensor is tripped
                                           // but without double counting during the same trip
  while(true){
    if (digitalRead(input)==0){
      
      if (on_state==false){
        on_state = true;
        pulse++;
      }
    } 
    
    else{
      on_state = false;
    }

     lcd.setCursor(6,1);
     lcd.print(pulse);
}
delay(1); // Delay for stability.
                                         // delay in between reads for stability
}
}

Just to make it easy to follow along, can you next post a complete sketch that works to show your solution?

TBH I am curious about the interrupt service routine, and wonder about the detach interrupt call. So I would like to see it in context.

I could try to retrofit and come up with a complete sketch, but that's fraught even if you made no other changes.

TIA

a7

sure. Here's the complete code. I reinstated the comments i deleted so you an see what needs to be changed. The code has a lot of extra stuff that's not really needed for my use. but I haven't attempted to clean it up yet. the RPMcode() used to be the main loop, which i changed to add another function.

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);
                // LCD SDA = A4 pin
                // LCD SDL = A5 pin

const byte rpmOff = 12;
#define input 11
unsigned long pulse = 0;    
byte switchState;


const byte PulsesPerRevolution = 1;                            // 1 pulse per rev for hall sensor
                                                               // Set how many pulses there are on each revolution. Default: 2.


                                                              // If the period between pulses is too high, or even if the pulses stopped, then we would get stuck showing the
                                                              // last value instead of a 0. Because of this we are going to set a limit for the maximum period allowed.
                                                              // If the period is above this value, the RPM will show as 0.
                                                              // The higher the set value, the longer lag/delay will have to sense that pulses stopped, but it will allow readings
                                                              // at very low RPM.
                                                              // Setting a low value is going to allow the detection of stop situations faster, but it will prevent having low RPM readings.
                                                              // The unit is in microseconds.

const unsigned long ZeroTimeout = 2000000;                    // 100000 is roughly 600rpm
                                                              // For high response time, a good value would be 100000.
                                                              // For reading very low RPM, a good value would be 300000.
                                                              
                                                              // Calibration for smoothing RPM:
const byte numReadings = 5;                                   // Number of samples for smoothing. The higher, the more smoothing, but it's going to
                                                              // react slower to changes. 1 = no smoothing. Default: 2.... up to 10
  

volatile unsigned long LastTimeWeMeasured;                        // Stores the last time we measured a pulse so we can calculate the period.
volatile unsigned long PeriodBetweenPulses = ZeroTimeout+1000;      // Stores the period between pulses in microseconds.
                                                                  // It has a big number so it doesn't start with 0 which would be interpreted as a high frequency.
volatile unsigned long PeriodAverage = ZeroTimeout+1000;           // Stores the period between pulses in microseconds in total, if we are taking multiple pulses.
                                                                    // It has a big number so it doesn't start with 0 which would be interpreted as a high frequency.
unsigned long FrequencyRaw;                                         // Calculated frequency, based on the period. This has a lot of extra decimals without the decimal point.
unsigned long FrequencyReal;                                         // Frequency without decimals.
unsigned long RPM;                                                  // Raw RPM without any processing.
unsigned int PulseCounter = 1;  
                                                                // Counts the amount of pulse readings we took so we can average multiple pulses before calculating the period.

unsigned long PeriodSum;                                            // Stores the summation of all the periods to do the average.

unsigned long LastTimeCycleMeasure = LastTimeWeMeasured;            // Stores the last time we measure a pulse in that cycle.
                                                                    // We need a variable with a value that is not going to be affected by the interrupt
                                                                      // because we are going to do math and functions that are going to mess up if the values
                                                                    // changes in the middle of the cycle.
unsigned long CurrentMicros = micros();                               // Stores the micros in that cycle.
                                                                     // We need a variable with a value that is not going to be affected by the interrupt
                                                                      // because we are going to do math and functions that are going to mess up if the values
                                                                     // changes in the middle of the cycle.

                                                                      // We get the RPM by measuring the time between 2 or more pulses so the following will set how many pulses to
                                                                      // take before calculating the RPM. 1 would be the minimum giving a result every pulse, which would feel very responsive
                                                                      // even at very low speeds but also is going to be less accurate at higher speeds.
                                                                      // With a value around 10 you will get a very accurate result at high speeds, but readings at lower speeds are going to be
                                                                      // farther from eachother making it less "real time" at those speeds.
                                                                      // There's a function that will set the value depending on the speed so this is done automatically.
unsigned int AmountOfReadings = 1;

unsigned int ZeroDebouncingExtra;                                       // Stores the extra value added to the ZeroTimeout to debounce it.
                                                                        // The ZeroTimeout needs debouncing so when the value is close to the threshold it
                                                                          // doesn't jump from 0 to the value. This extra value changes the threshold a little
                                                                        // when we show a 0.

                                                                      // Variables for smoothing tachometer:
unsigned long readings[numReadings];                                  // The input.
unsigned long readIndex;                                               // The index of the current reading.
unsigned long total;                                                    // The running total.
unsigned long average;


void setup() {
 
    lcd.init();                     
    lcd.backlight();  

   lcd.setCursor(2,0);
   lcd.print("Lathe Sensor");

  pinMode(rpmOff, INPUT);
  pinMode(input, INPUT_PULLUP);

  attachInterrupt(digitalPinToInterrupt(2), Pulse_Event, FALLING);       // Enable interruption pin 2 when going from LOW to HIGH.

   delay(2000);   
   lcd.clear();


}

void loop() {

checkSwitch();
RPMcode();
Turns();

}
                                                                       // The following is going to store the two values that might change in the middle of the cycle.
 void checkSwitch(){

    switchState = digitalRead(rpmOff);
   
   if (switchState == LOW){
     lcd.setCursor(0,0);
     lcd.print("RPM");
   }
    
     if(switchState == HIGH){
     lcd.setCursor(0,0);
     lcd.print("Turns");
   }
 }

  void Turns(){
       
       if (switchState==HIGH){


detachInterrupt(digitalPinToInterrupt(2)) ;

  bool on_state = false;
                                            // counting number of times the hall sensor is tripped
                                           // but without double counting during the same trip
  while(true){
    if (digitalRead(input)==0){
      
      if (on_state==false){
        on_state = true;
        pulse++;
      }
    } 
    
    else{
      on_state = false;
    }

     lcd.setCursor(6,1);
     lcd.print(pulse);
}
delay(1);                                                           // Delay for stability.
                                     
}
}

  
  
  void RPMcode(){                                                    // We are going to do math and functions with those values and they can create glitches if they change in the
                                                                       // middle of the cycle.
  LastTimeCycleMeasure = LastTimeWeMeasured;                         // Store the LastTimeWeMeasured in a variable.
  CurrentMicros = micros();                                            // Store the micros() in a variable.

                                                                         // CurrentMicros should always be higher than LastTimeWeMeasured, but in rare occasions that's not true.
                                                                         // I'm not sure why this happens, but my solution is to compare both and if CurrentMicros is lower than
                                                                          // LastTimeCycleMeasure I set it as the CurrentMicros.
                                                                           // The need of fixing this is that we later use this information to see if pulses stopped.
  if(CurrentMicros < LastTimeCycleMeasure)
  {
    LastTimeCycleMeasure = CurrentMicros;
  }
                                                                         // Calculate the frequency:
  FrequencyRaw = 10000000000 / PeriodAverage;                            // Calculate the frequency using the period between pulses.
  
                                                                            // Detect if pulses stopped or frequency is too low, so we can show 0 Frequency:
  if(PeriodBetweenPulses > ZeroTimeout - ZeroDebouncingExtra || CurrentMicros - LastTimeCycleMeasure > ZeroTimeout - ZeroDebouncingExtra)
  {                                                                         // If the pulses are too far apart that we reached the timeout for zero:
    FrequencyRaw = 0;                                                        // Set frequency as 0.
    ZeroDebouncingExtra = 2000;                                             // Change the threshold a little so it doesn't bounce.
  }
  else
  {
    ZeroDebouncingExtra = 0;                                                 // Reset the threshold to the normal value so it doesn't bounce.
  }

  FrequencyReal = FrequencyRaw / 10000;                                      // Get frequency without decimals.
                                                                              // This is not used to calculate RPM but we remove the decimals just in case
                                                                                 // you want to print it.

                                                                             // Calculate the RPM:
  RPM = FrequencyRaw / PulsesPerRevolution * 60;                             // Frequency divided by amount of pulses per revolution multiply by
                                                                              // 60 seconds to get minutes.
  RPM = RPM / 10000;                                                          // Remove the decimals.

                                                                                // Smoothing RPM:
  total = total - readings[readIndex];                                          // Advance to the next position in the array.
  readings[readIndex] = RPM;                                                    // Takes the value that we are going to smooth.
  total = total + readings[readIndex];                                          // Add the reading to the total.
  readIndex = readIndex + 1;                                                    // Advance to the next position in the array.

  if (readIndex >= numReadings)                                                 // If we're at the end of the array:
  {
    readIndex = 0;                                                                // Reset array index.
  }
  
                                                                                  // Calculate the average:
  average = total / numReadings;                                                  // The average value it's the smoothed result.


 char string[10];                                                                // Create a character array of 10 characters
                                                                                  // Convert float to a string:
  dtostrf(average, 6, 0, string);                                                  // (<variable>,<amount of digits we are going to use>,<amount of decimal digits>,<string name>)

     lcd.setCursor(0,1);
     lcd.print(string);
/*
                                                                                  // Print information on the serial monitor:
                                                                                  // Comment this section if you have a display and you don't need to monitor the values on the serial monitor.
                                                                                  // This is because disabling this section would make the loop run faster.
  Serial.print("Period: ");
  Serial.print(PeriodBetweenPulses);
  Serial.print("\tReadings: ");
  Serial.print(AmountOfReadings);
  Serial.print("\tFrequency: ");
  Serial.print(FrequencyReal);
  Serial.print("\tRPM: ");
  Serial.print(RPM);
  Serial.print("\tTachometer: ");
  Serial.println(average);
*/

}                                                                                // End of loop.
 
void Pulse_Event()                                                                // The interrupt runs this to calculate the period between pulses:
{

  PeriodBetweenPulses = micros() - LastTimeWeMeasured;                                // Current "micros" minus the old "micros" when the last pulse happens.
                                                                                      // This will result with the period (microseconds) between both pulses.
                                                                                       // The way is made, the overflow of the "micros" is not going to cause any issue.

  LastTimeWeMeasured = micros();                                                       // Stores the current micros so the next time we have a pulse we would have something to compare with.



  if(PulseCounter >= AmountOfReadings)                                               // If counter for amount of readings reach the set limit:
  {
    PeriodAverage = PeriodSum / AmountOfReadings;                                      // Calculate the final period dividing the sum of all readings by the
                                                                                         // amount of readings to get the average.
    PulseCounter = 1;                                                                 // Reset the counter to start over. The reset value is 1 because its the minimum setting allowed (1 reading).
    PeriodSum = PeriodBetweenPulses;                                                   // Reset PeriodSum to start a new averaging operation.


                                                                                      // Change the amount of readings depending on the period between pulses.
                                                                                       // To be very responsive, ideally we should read every pulse. The problem is that at higher speeds the period gets
                                                                                      // too low decreasing the accuracy. To get more accurate readings at higher speeds we should get multiple pulses and
                                                                                        // average the period, but if we do that at lower speeds then we would have readings too far apart (laggy or sluggish).
                                                                                       // To have both advantages at different speeds, we will change the amount of readings depending on the period between pulses.
                                                                                        // Remap period to the amount of readings:
    int RemapedAmountOfReadings = map(PeriodBetweenPulses, 40000, 5000, 1, 10);          // Remap the period range to the reading range.
                                                                                         // 1st value is what are we going to remap. In this case is the PeriodBetweenPulses.
                                                                                         // 2nd value is the period value when we are going to have only 1 reading. The higher it is, the lower RPM has to be to reach 1 reading.
                                                                                        // 3rd value is the period value when we are going to have 10 readings. The higher it is, the lower RPM has to be to reach 10 readings.
                                                                                           // 4th and 5th values are the amount of readings range.
    RemapedAmountOfReadings = constrain(RemapedAmountOfReadings, 1, 10);                    // Constrain the value so it doesn't go below or above the limits.
    AmountOfReadings = RemapedAmountOfReadings;                                          // Set amount of readings as the remaped value.
  }
  else
  {
    PulseCounter++;                                                                     // Increase the counter for amount of readings by 1.
    PeriodSum = PeriodSum + PeriodBetweenPulses;                                        // Add the periods so later we can average.
  }
 
}                                                                                        // End of Pulse_Event.

But this code is subject to change. I really want to do away with half of it and run the counting from the ISR, so i don't have to share the hall sensor between 2 separate pins. but now that i have a working model, i can start playing with it and see if i can make those changes work.

Are you running your sketch for more than 1 hour? (1h11m35s)

Thanks, I will take a low level flight about it later.

But quick question… at a glance I see an interrupt attached in you setup(), the only place and

a detach interrupt in one of your functions, the only place.

Which makes me wonder about the role and duration of run time that uses interrupts compared to the rest of the time when there will be no more. Interrupts.

What are those two phases of operation? Or what am I missing?

As for

… this code is subject to change.

I can safely say I have never finished an Arduino program. :expressionless:

a7

no. i'm still in the testing phase and haven't ran the rpm code more than a minute. But i have left it plugged in for hours and everything still seemed to work normally with the counting. but in my case, with it being on a lathe, i don't expect to be running the rpm code for long periods of time. but once i get it installed i'll see if there's any time glitches.