Jiggy-Ninja:
What's the engine rotation speed? What sort of timing precision do you need? What's the pulse width you're looking for?
You might not even need an interrupt to do this.
~4500 RPM or so maximum, but I eventually plan to move it to a twin cylinder engine that goes to about 11,000 RPM. The twin will need to utilize two sensors, one for each cylinder. The single cylinder engine triggers off the crank, so around a maximum of 75Hz or so. The twin will trigger off the camshaft, which rotates at half engine speed, so call it about 90-100Hz.
Since I'm not using the arduino to control the spark, not too much timing accuracy is needed (many OEM EFI systems inject against closed valves)
Pulsewidth will range probably between 1-3 ms at idle, to around 15-25ms at the max.
Here's the code I'm currently using, it also implements an RPM display on my VFD.
#include <GU7000_Interface.h>
#include <GU7000_Serial_Async.h>
#include <Noritake_VFD_GU7000.h>
GU7000_Serial_Async interface(38400, 4, 5, 6);
Noritake_VFD_GU7000 vfd;
volatile long lastPulseTime = 0;
volatile long rpm = 0;
int PW = 25;
volatile int flag = 0;
void setup() {
pinMode(2, INPUT);
digitalWrite(2, HIGH);
pinMode(11, OUTPUT);
pinMode(10, OUTPUT);
digitalWrite(10, LOW);
attachInterrupt(0, inject, FALLING);
_delay_ms(500);
vfd.begin(140, 32);
vfd.isModelClass(7000);
vfd.interface(interface);
vfd.GU7000_reset();
vfd.GU7000_init();
vfd.print("Pulse Width: 2.5ms");
}
void loop() {
if (rpm < 4500){
if (flag == 1) {
flag = 0;
digitalWrite(11, HIGH);
delay(PW / 10);
digitalWrite(11, LOW);
}
}
}
void inject()
{ unsigned long now = micros();
unsigned long interval = now - lastPulseTime;
if (interval > 2000)
{
rpm = 60000000UL / (interval * 1);
lastPulseTime = now;
}
vfd.GU7000_setCursor(0, 30);
vfd.print("RPM:");
if (rpm < 1000) {
vfd.print(" ");
}
if (rpm < 100) {
vfd.print(" ");
}
vfd.print(rpm, 10);
flag = 1;
}
This is another program that implements a rotary encoder so i can manually adjust the pulsewidth:
#include <GU7000_Interface.h>
#include <GU7000_Serial_Async.h>
#include <Noritake_VFD_GU7000.h>
GU7000_Serial_Async interface(38400, 4, 5, 6);
Noritake_VFD_GU7000 vfd;
const int switchPin = 13;
const int switch2Pin = 12;
int switchState = 0;
int switch2State = 0;
int prevSwitchState = 0;
int prevSwitch2State = 0;
volatile long lastPulseTime = 0;
volatile long rpm = 0;
int PW = 0;
volatile int flag = 0;
void setup() {
pinMode(switchPin, INPUT);
pinMode(switch2Pin, INPUT);
pinMode(2, INPUT);
digitalWrite(2, HIGH);
pinMode(11, OUTPUT);
pinMode(10, OUTPUT);
digitalWrite(10, LOW);
attachInterrupt(0, inject, FALLING);
_delay_ms(500);
vfd.begin(140, 32);
vfd.isModelClass(7000);
vfd.interface(interface);
vfd.GU7000_reset();
vfd.GU7000_init();
vfd.print("Pulse Width: 0.0ms");
}
void loop() {
if (rpm < 4500){
if (flag == 1) {
flag = 0;
digitalWrite(11, HIGH);
delay(PW / 10);
digitalWrite(11, LOW);
}
}
switchState = digitalRead(switchPin);
switch2State = digitalRead(switch2Pin);
if (switch2State != prevSwitch2State) {
if (switch2State == LOW) {
PW = PW + 2;
vfd.GU7000_setCursor(112, 0);
vfd.GU7000_setCursor(0, 0);
vfd.print("Pulse Width:");
vfd.GU7000_setCursor(84, 0);
if (PW / 10 < 10) {
vfd.print(" ");
}
vfd.print(PW / 10, 10);
vfd.print(".");
vfd.print(PW % 10, 10);
vfd.print("ms");
}
prevSwitch2State = switch2State;
}
if (switchState != prevSwitchState) {
if (switchState == LOW) {
PW = PW - 2;
if (PW < 0) {
PW = 0;
}
vfd.GU7000_setCursor(84, 0);
vfd.GU7000_setCursor(0, 0);
vfd.print("Pulse Width:");
vfd.GU7000_setCursor(84, 0);
if (PW / 10 < 10) {
vfd.print(" ");
}
vfd.print(PW / 10, 10);
vfd.print(".");
vfd.print(PW % 10, 10);
vfd.print("ms");
}
prevSwitchState = switchState;
}
}
void inject()
{ unsigned long now = micros();
unsigned long interval = now - lastPulseTime;
if (interval > 2000)
{
rpm = 60000000UL / (interval * 1);
lastPulseTime = now;
}
vfd.GU7000_setCursor(0, 30);
vfd.print("RPM:");
if (rpm < 1000) {
vfd.print(" ");
}
if (rpm < 100) {
vfd.print(" ");
}
vfd.print(rpm, 10);
flag = 1;
}