I wrote previously here about wanting to build a small ignition unit for my motorbike. The key element with these units is generating a method of knowing where the crankshaft is so as to be able to generate a spark at the appropriate time.
One method used by car manufacturers is to have a toothed wheel on the crankshaft in the form of 36-1. That is the wheel has 36 teeth with one tooth missing so generates a gap. Using a suitable sensor then generates a square wave where each cycle=10 deg of crankshaft rotation.
I already had a simulator to generate a 36-1 waveform so wrote a short piece of code to capture the gaps and check on the Arduino's performance. Sadly before I reached my required max rpm figure (9000) it was missing gaps. The software generates a pulse on seeing a gap, this makes it easy to compare with the original on my oscilloscope.
One though was that the simulator I had was perhaps troublesome. So I bought another Arduino and used that to generate the 36-1 waveform.
Following further tests I have discovered that the system is stable up to 4100 rpm which equates to a pulse width of 204uS. At 4150 rpm 201uS it starts missing gaps. This would mean in the real world that the board wouldn't generate all the rquired ignition pulses.
The board will detect up to 9000 rpm but increasing misses more gaps.
The software below writes an asterisk to the serial port when a gap is missed. Interestingly there is a cycle of initially 12 seconds to the missed gaps ie several asterisks will appear and then no more for about 12 seconds. As the rpm is increased this delay reduces so by about 4500 rpm the delay is 6 seconds. By about 5000 rpm there is no delay and continuous but irregularly spaced asterisks are generated.
So it looks like I have hit a limitation with the Arduino software and need to go to assembler to regain performance required.
The software I used is:
/* This routine takes a 36-1 signal in pin7
and puts a pulse out on pin 13 when the gap passes by
*/
int inpin=7, outpin=13;
unsigned long old,new1,oldtime,newtime,savedtime;
void setup()
{
pinMode(inpin,INPUT);
pinMode(outpin,OUTPUT);
old=1; //size of last gap
new1=1; //size of current gap
oldtime=millis(); //get time since program start
newtime,savedtime=1;
Serial.begin(9600);
}
void loop()
{
new1=pulseIn(inpin,LOW); //get pulsewidth in usec
if (new1 != 0) //if no signal within 1 sec counter timed out so zero
{
if (new1 > 2.9old && new1 < 3.1old) //if within 10% of 3xoldgap we must be at large gap
{
digitalWrite(outpin,HIGH); //write an out pulse
new1=pulseIn(inpin,LOW); //wait til next pulse passes - this defines outpulse width
digitalWrite(outpin,LOW);
newtime=millis()-oldtime;
if (newtime > 1.5savedtime) {
Serial.print("");}
oldtime=millis();
savedtime=newtime;
}
else
{
old=new1; //else just save the gap size - this allows for a change in gap size
} //during accel/deaccel
}
else
{
old=1; //if no signal reset old to prevent random activity
}
}