Confused by oscilloscope - square wave signal to RPM

This was correct, it did in fact work - but not before I had to remove "medianFilter.GetFiltered ();" using "GetFiltered" resulting in literally nothing in the serial output. I don't still fully understand how the median filter works, but regardless - I replaced the GetFiltered with "medianFilter.AddValue (pulseDuration);", added a 75% tolerance to the "if" statement and voila, the output is now buttery smooth:

This is the fastest and most accurate the output has ever been. Thank you all so much.

I am not completely out of the woods, however. Now that I have established a working code for measuring the RPM, I thought it would simply be a case of assigning code for the neopixels and job done. Unfortunately, this is not the case.

I have a startup sequence for the neopixels in void setup() and that works, so I know that the arduino can still address them inside this code. The problem is very quickly after the arduino initializes, like about 30 seconds, the arduino freezes up and the serial output dies. I have changed nothing about my neopixel code that I know works from the original sketches.

The most glaring issue is that now that I am using interrupts, the neopixel library doesn't like that and is messing with things somehow. I have a few theories to test using noInterrupts(), and I guess I could use a second arduino dedicated to driving the neopixels, but I'd rather avoid that if possible.

This is the working code as it now stands:

// Measures the HIGH width, LOW width, frequency, and duty-cycle of a pulse train
// on Arduino NANO Pin 8 (ICP1 pin).
// Note: Since this uses Timer1, Pin 9 and Pin 10 can't be used for
// analogWrite().

// Adafruit NeoPixel RGBW strips (2x8 LEDS) 

#include <MedianFilterLib.h>

//MedianFilter < volatile > medianFilter ( 5 ); // 5 samples
volatile MedianFilter<uint32_t> medianFilter(5); // 5 samples
unsigned long pulse = 0;
float sensorRPM;
int RPMno = 3000; // base rpm for led activation
int space = 100; //delays for led startup sequence

//Input for headlight circuit
#define headlights 10
bool val = 0;

//NeoPixels
#include <Adafruit_NeoPixel.h>
#define PIN 6
#define NUM_LEDS 16
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRBW + NEO_KHZ800);
// full brightness
uint32_t r = strip.Color  (200, 0, 0, 0);
uint32_t g = strip.Color  (0, 180, 0, 0);
uint32_t b = strip.Color  (0, 0, 255, 0);
uint32_t w = strip.Color  (0, 0, 0, 120);
uint32_t y = strip.Color  (200, 120, 0, 0);
// dimmed
uint32_t rd = strip.Color  (8, 0, 0, 0);
uint32_t gd = strip.Color  (0, 7, 0, 0);
uint32_t bd = strip.Color  (0, 0, 10, 0);
uint32_t wd = strip.Color  (0, 0, 0, 3);
uint32_t yd = strip.Color  (10, 5, 0, 0);
// off/no color
uint32_t o = strip.Color   (0, 0, 0, 0);

bool ledState = 1;



void setup()
{
  //initiate neopixels
   strip.begin();
  //set strip to nothing, flushes potential random colors
  strip.clear();
  strip.fill(o);
  strip.show();
  ledStartup();
   
  //assign input for relay
  pinMode(headlights, INPUT);
  digitalWrite(headlights, HIGH); //enables pullup resistor - HIGH on an input pin
                                 //also, it inverts signal: < 3v = HIGH, > 3v = LOW
  
  Serial.begin(9600);
  while (!Serial);

  // For testing, uncomment one of these lines and connect
  // Pin 3 or Pin 5 to Pin 8
  // analogWrite(3, 64);  // 512.00, 1528.00, 2040.00, 25.10%, 490.20 Hz
  // analogWrite(5, 64);  // 260.00, 764.00, 1024.00, 25.39%, 976.56 Hz

  noInterrupts ();  // protected code
  // reset Timer 1
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;
  TIMSK1 = 0;

  TIFR1 |= _BV(ICF1); // clear Input Capture Flag so we don't get a bogus interrupt
  TIFR1 |= _BV(TOV1); // clear Overflow Flag so we don't get a bogus interrupt

  TCCR1B = _BV(CS10) | // start Timer 1, no prescaler
           _BV(ICES1); // Input Capture Edge Select (1=Rising, 0=Falling)

  TIMSK1 |= _BV(ICIE1); // Enable Timer 1 Input Capture Interrupt
  TIMSK1 |= _BV(TOIE1); // Enable Timer 1 Overflow Interrupt
  interrupts ();
}

volatile uint16_t Overflows = 0;

ISR(TIMER1_OVF_vect)
{
  Overflows++;
}

ISR(TIMER1_CAPT_vect)
{
  static uint32_t previousRisingEdgeTime = 0;

  uint32_t thisRisingEdgeTime;
  uint16_t overflows = Overflows;

  // If an overflow happened but has not been handled yet
  // and the timer count was close to zero, count the
  // overflow as part of this time.
  if ((TIFR1 & _BV(TOV1)) && (ICR1 < 1024))
    overflows++;

  // Interrupted on Rising Edge
  thisRisingEdgeTime = overflows; // Upper 16 bits
  thisRisingEdgeTime = (thisRisingEdgeTime << 16) | ICR1;

  //uint32_t pulseDuration = thisRisingEdgeTime - previousRisingEdgeTime;
  pulse = thisRisingEdgeTime - previousRisingEdgeTime;
  previousRisingEdgeTime = thisRisingEdgeTime;

  // This is a good place to add 'pulseDuration' to the median filter.
  // Make sure the median filter is marked 'volatile'.
  //medianFilter.AddValue (pulseDuration);
}

void loop()
{
  static uint32_t previousMedian;
  uint32_t thisMedian;

  dimmer();

  noInterrupts();
  // This would be where you get 'thisMedian'
  // from the median filter.
  thisMedian = medianFilter.AddValue (pulse);
  interrupts();

  // If a sample has been measured
  if (thisMedian != previousMedian && thisMedian > previousMedian*0.75)
  {
    // Display the pulse length in microseconds
    //Serial.print("Pulse time (microseconds): ");
    //Serial.println(thisMedian / 16.0, 2);
    
    //measure revs from pulse_length
    //first calculate how many sparks happening per second, 1000ms divided by delay between sparks
    float sparksPerSec = 1000/((thisMedian / 16.0)*0.001);
    //next multiply by 60 for sparks per minute - two revs per spark
    sensorRPM = sparksPerSec*120;
    Serial.println(sensorRPM);
    previousMedian = thisMedian; 
  }
  //delay(100);
}


//__      ______ _____ _____  
// \ \    / / __ \_   _|  __ \ 
//  \ \  / / |  | || | | |  | |
//   \ \/ /| |  | || | | |  | |
//    \  / | |__| || |_| |__| |
//     \/   \____/_____|_____/ 


//     _ _                               
//  __| (_)_ __ ___  _ __ ___   ___ _ __ 
// / _` | | '_ ` _ \| '_ ` _ \ / _ \ '__|
//| (_| | | | | | | | | | | | |  __/ |   
// \__,_|_|_| |_| |_|_| |_| |_|\___|_|                             

void dimmer (void)
{
  
 val = digitalRead(headlights);
  if (val == LOW) leds();
   else            ledsDimmed();
   
}


//  _          _     
// | | ___  __| |___ 
// | |/ _ \/ _` / __|
// | |  __/ (_| \__ \
// |_|\___|\__,_|___/  font = ogre
                                                                 
void leds(void) 
{  
  
if (sensorRPM > 0 && sensorRPM < RPMno) 
 {
  strip.clear();
  strip.fill(o); //----------------
  //strip.setPixelColor(o, 0);
  strip.show(); 
 }
 
if (sensorRPM > RPMno && sensorRPM < (RPMno + 90)) 
 {
  strip.clear();
  strip.fill(g, 14);  //gg--------------
  strip.show(); 
 }
 
if (sensorRPM > (RPMno + 90) && sensorRPM < (RPMno + 220)) 
 {
  strip.clear();
  strip.fill(g, 12);  //gggg------------
  strip.show(); 
  } 
  
if (sensorRPM > (RPMno + 220) && sensorRPM < (RPMno + 330)) 
 {
  strip.clear();
  strip.fill(g, 10);  //gggggg----------
  strip.show(); 
  } 
  
if (sensorRPM > (RPMno + 330) && sensorRPM < (RPMno + 440)) 
 { 
  strip.clear();
  strip.fill(y,8);   //yyyyyyyy--------         
  strip.show(); 
  } 
  
if (sensorRPM > (RPMno + 440) && sensorRPM < (RPMno + 550)) 
 {
  strip.clear();
  strip.fill(y,6);   //yyyyyyyyyy------
  strip.show();
 }
 
if (sensorRPM > (RPMno + 550) && sensorRPM < (RPMno + 660)) 
 {
  strip.clear();
  strip.fill(y,4);         //yyyyyyyyyyyy----
  strip.show();  
 }
 
if (sensorRPM > (RPMno + 660) && sensorRPM < (RPMno + 770)) 
 {
  strip.clear();strip.fill(r,2);         //rrrrrrrrrrrrrr--         
  strip.show(); 
 }
 
if (sensorRPM > (RPMno + 770) && sensorRPM < (RPMno + 880)) 
 {
  strip.clear();
  strip.fill(r,0);        //rrrrrrrrrrrrrr
  strip.show(); 
 } 
 
if (sensorRPM > (RPMno + 880) && sensorRPM < (RPMno + 1100)) 
 {
  strip.clear();
  strip.fill(w);        //wwwwwwwwwwwwwwww 
  strip.show(); 
 }


if (sensorRPM > (RPMno + 1100)) 
 {
  strip.clear();
  strip.fill(o);
  strip.show(); 
 }
 
}

//  _          _        ___ _                              _ 
// | | ___  __| |___   /   (_)_ __ ___  _ __ ___   ___  __| |
// | |/ _ \/ _` / __| / /\ / | '_ ` _ \| '_ ` _ \ / _ \/ _` |
// | |  __/ (_| \__ \/ /_//| | | | | | | | | | | |  __/ (_| |
// |_|\___|\__,_|___/___,' |_|_| |_| |_|_| |_| |_|\___|\__,_|
                                                          
void ledsDimmed(void)  
{  
  
if (sensorRPM > 0 && sensorRPM < RPMno) 
 {
  strip.clear();
  strip.fill(o); //----------------
  //strip.setPixelColor(o, 0);
  strip.show(); 
 }
 
if (sensorRPM > RPMno && sensorRPM < (RPMno + 90)) 
 {
  strip.clear();
  strip.fill(gd, 14);  //gg--------------
  strip.show(); 
 }
 
if (sensorRPM > (RPMno + 90) && sensorRPM < (RPMno + 220)) 
 {
  strip.clear();
  strip.fill(gd, 12);  //gggg------------
  strip.show(); 
  } 
  
if (sensorRPM > (RPMno + 220) && sensorRPM < (RPMno + 330)) 
 {
  strip.clear();
  strip.fill(gd, 10);  //gggggg----------
  strip.show(); 
  } 
  
if (sensorRPM > (RPMno + 330) && sensorRPM < (RPMno + 440)) 
 { 
  strip.clear();
  strip.fill(yd,8);   //yyyyyyyy--------         
  strip.show(); 
  } 
  
if (sensorRPM > (RPMno + 440) && sensorRPM < (RPMno + 550)) 
 {
  strip.clear();
  strip.fill(yd,6);   //yyyyyyyyyy------
  strip.show();
 }
 
if (sensorRPM > (RPMno + 550) && sensorRPM < (RPMno + 660)) 
 {
  strip.clear();
  strip.fill(yd,4);         //yyyyyyyyyyyy----
  strip.show();  
 }
 
if (sensorRPM > (RPMno + 660) && sensorRPM < (RPMno + 770)) 
 {
  strip.clear();
  strip.fill(rd,2);         //rrrrrrrrrrrrrr--         
  strip.show(); 
 }
 
if (sensorRPM > (RPMno + 770) && sensorRPM < (RPMno + 880)) 
 {
  strip.clear();
  strip.fill(rd,0);        //rrrrrrrrrrrrrr
  strip.show(); 
 } 
 
if (sensorRPM > (RPMno + 880) && sensorRPM < (RPMno + 1100)) 
 {
  strip.clear();
  strip.fill(wd);        //wwwwwwwwwwwwwwww 
  strip.show(); 
 }
}

//  _          _      __ _             _               
// | | ___  __| |___ / _\ |_ __ _ _ __| |_ _   _ _ __  
// | |/ _ \/ _` / __|\ \| __/ _` | '__| __| | | | '_ \ 
// | |  __/ (_| \__ \_\ \ || (_| | |  | |_| |_| | |_) |
// |_|\___|\__,_|___/\__/\__\__,_|_|   \__|\__,_| .__/ 
//                                             |_|    
void ledStartup(void)
{
  strip.fill(o);
  strip.show();
  delay(space);
  
  strip.fill(gd, 14);
  strip.show();
  delay(space);
  
  strip.fill(gd, 12);
  strip.show();
  delay(space);
  
  strip.fill(gd, 10); 
  strip.show();
  delay(space);
  
  strip.fill(yd,8);
  strip.show();
  delay(space);
  
  strip.fill(yd,6);
  strip.show();
  delay(space);
   
  strip.fill(yd,4);
  strip.show();
  delay(space);
  
  strip.fill(rd,2);
  strip.show();
  delay(space);
  
  strip.fill(rd);  
  strip.show();
  delay(space);
//---------------------------  
  strip.fill(wd);
  strip.show();
  delay(space*2);
//----------------------------
  strip.clear();
  strip.fill(rd);  
  strip.show();
  delay(space);

  strip.clear();
  strip.fill(rd,2);
  strip.show();
  delay(space);

  strip.clear();
  strip.fill(yd,4);
  strip.show();
  delay(space);

  strip.clear();
  strip.fill(yd,6);
  strip.show();
  delay(space);

  strip.clear();
  strip.fill(yd,8);
  strip.show();
  delay(space);
  
  strip.clear();
  strip.fill(gd, 10); 
  strip.show();
  delay(space);
  
  strip.clear();
  strip.fill(gd, 12);
  strip.show();
  delay(space);
  
  strip.clear();
  strip.fill(gd, 14);
  strip.show();
  delay(space);
  
  strip.fill(o);
  strip.show();
}