*/
// 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 = 4000; // base rpm for led activation
int space = 100; //delays for led startup sequence
//Input for headlight circuit
#define headlights 10
bool dimmer = LOW;
unsigned long millisDimmer = 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;
unsigned long millisLeds = 0;
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 ();
millisLeds = millis();
millisDimmer = millis();
}
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;
if ( millis() >= millisDimmer + 250)
{
dimmer = digitalRead(headlights);
millisDimmer = millis();
}
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 >= 0.75*previousMedian)
{
// 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);
//Serial.println(thisMedian);
previousMedian = thisMedian;
}
if (millis() >= millisLeds + 50)
{
if (dimmer = LOW){
leds(); }
else {
ledsDimmed(); }
millisLeds = millis();
}
}
//__ ______ _____ _____
// \ \ / / __ \_ _| __ \
// \ \ / / | | || | | | | |
// \ \/ /| | | || | | | | |
// \ / | |__| || |_| |__| |
// \/ \____/_____|_____/
// _ _
// __| (_)_ __ ___ _ __ ___ ___ _ __
// / _` | | '_ ` _ \| '_ ` _ \ / _ \ '__|
//| (_| | | | | | | | | | | | | __/ |
// \__,_|_|_| |_| |_|_| |_| |_|\___|_|
//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.show();
}
else if (sensorRPM > RPMno && sensorRPM < (RPMno + 90))
{
strip.clear();
strip.fill(g, 14); //gg--------------
strip.show();
}
else if (sensorRPM > (RPMno + 90) && sensorRPM < (RPMno + 220))
{
strip.clear();
strip.fill(g, 12); //gggg------------
strip.show();
}
else if (sensorRPM > (RPMno + 220) && sensorRPM < (RPMno + 330))
{
strip.clear();
strip.fill(g, 10); //gggggg----------
strip.show();
}
else if (sensorRPM > (RPMno + 330) && sensorRPM < (RPMno + 440))
{
strip.clear();
strip.fill(y,8); //yyyyyyyy--------
strip.show();
}
else if (sensorRPM > (RPMno + 440) && sensorRPM < (RPMno + 550))
{
strip.clear();
strip.fill(y,6); //yyyyyyyyyy------
strip.show();
}
else if (sensorRPM > (RPMno + 550) && sensorRPM < (RPMno + 660))
{
strip.clear();
strip.fill(y,4); //yyyyyyyyyyyy----
strip.show();
}
else if (sensorRPM > (RPMno + 660) && sensorRPM < (RPMno + 770))
{
strip.clear();strip.fill(r,2); //rrrrrrrrrrrrrr--
strip.show();
}
else if (sensorRPM > (RPMno + 770) && sensorRPM < (RPMno + 880))
{
strip.clear();
strip.fill(r); //rrrrrrrrrrrrrr
strip.show();
}
else if (sensorRPM > (RPMno + 880) && sensorRPM < (RPMno + 1100))
{
strip.clear();
strip.fill(w); //wwwwwwwwwwwwwwww
strip.show();
}
else 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.show();
}
else if (sensorRPM > RPMno && sensorRPM < (RPMno + 90))
{
strip.clear();
strip.fill(gd, 14); //gg--------------
strip.show();
}
else if (sensorRPM > (RPMno + 90) && sensorRPM < (RPMno + 220))
{
strip.clear();
strip.fill(gd, 12); //gggg------------
strip.show();
}
else if (sensorRPM > (RPMno + 220) && sensorRPM < (RPMno + 330))
{
strip.clear();
strip.fill(gd, 10); //gggggg----------
strip.show();
}
else if (sensorRPM > (RPMno + 330) && sensorRPM < (RPMno + 440))
{
strip.clear();
strip.fill(yd,8); //yyyyyyyy--------
strip.show();
}
else if (sensorRPM > (RPMno + 440) && sensorRPM < (RPMno + 550))
{
strip.clear();
strip.fill(yd,6); //yyyyyyyyyy------
strip.show();
}
else if (sensorRPM > (RPMno + 550) && sensorRPM < (RPMno + 660))
{
strip.clear();
strip.fill(yd,4); //yyyyyyyyyyyy----
strip.show();
}
else if (sensorRPM > (RPMno + 660) && sensorRPM < (RPMno + 770))
{
strip.clear();
strip.fill(rd,2); //rrrrrrrrrrrrrr--
strip.show();
}
else if (sensorRPM > (RPMno + 770) && sensorRPM < (RPMno + 880))
{
strip.clear();
strip.fill(rd); //rrrrrrrrrrrrrr
strip.show();
}
else if (sensorRPM > (RPMno + 880) && sensorRPM < (RPMno + 1100))
{
strip.clear();
strip.fill(wd); //wwwwwwwwwwwwwwww
strip.show();
}
else if (sensorRPM > (RPMno + 1100))
{
strip.clear();
strip.fill(o);
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();
}