*/
// 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;
}
noInterrupts();
if (millis() >= millisLeds + 50)
{
if (dimmer = LOW){
leds(); }
else {
ledsDimmed(); }
millisLeds = millis();
}
interrupts();
}
//__ ______ _____ _____
// \ \ / / __ \_ _| __ \
// \ \ / / | | || | | | | |
// \ \/ /| | | || | | | | |
// \ / | |__| || |_| |__| |
// \/ \____/_____|_____/
// _ _
// __| (_)_ __ ___ _ __ ___ ___ _ __
// / _` | | '_ ` _ \| '_ ` _ \ / _ \ '__|
//| (_| | | | | | | | | | | | | __/ |
// \__,_|_|_| |_| |_|_| |_| |_|\___|_|
//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();
}
- Pin 8 is not connected to anything, but pin 11/D8 is connected to the ECM ignition trigger wire IGT. See the schematic in my first post. That wire is still connected to D3, as thats where it was originally soldered to and I just added a jumper wire for testing of the timing code.
- Ground is connected to both the chassis (on the left side of nano), and also the ground of the 5v dc-dc converter on the right side (on the 5v side - 12v side of the converter is connected to chassis).
- See above.
- A bare nano, powered by a 5v dc-dc converter, connected to the ECM, the neopixels, and also the wire coming from the stereo headlight-trigger wire, voltage divided. Again, see schematic.
- Aside from a sole 250k resistor, no.
I reiterate that the RPM reading is working correctly now, and that the problem is no longer therein. Without any code for neopixels or headlights, it functions perfectly without issue.