Car ignition - Need to make this code faster :(

Hello, i am making car ignition system, witch i could manage, all is ok, but is have a glithes of speed. Source input is trigger wheel 36 teeths without 1 of them. It is like 35x - HIGH, LOW and last 36th pulse is like LOW,LOW, like 2 times longer than before. Max speed of interrupt signal is about 80 microssecond. Could you understand me and try to help me!

unsigned long dwell = 7000; // dwell time in uS
int tableMechAdv[] = { 5, 10, 15, 20, 25, 30, 35, 40, 45, 50 };  
int tableRpm[]  = {0,1000,2000,3000,4000,5000,6000,7000,8000,9000};
int tableVacAdv[] = { 5, 5, 5, 5, 4, 3, 1, 0, 0, 0, 0 };  
int tableVac[]  = {0,10,20,30,40,50,60,70,80,90,100};

int i = 1;
int r = 1;

int r1;

int ign1;

int zobs;
int bezzobs;

unsigned long ignitionTime1;

unsigned long dwellTime;

unsigned long dwellTime1;

int ignitionDwellTime1;

unsigned long dzirkstele1;

unsigned long lenkisDzirkstele1;

unsigned long microsDzirkstele1;

  
volatile unsigned long pulseTimeNew; //Pēdejā iegūtā pulsa laiks
volatile unsigned long pulseTime2; // Otrā iegūtā pulsa laiks
volatile unsigned long pulseTime3; // Trešā iegūtā pulsa laiks
volatile unsigned long pulseTime4; // Ceturtā iegūtā pulsa laiks
unsigned long pulseTimeAvg; // Videājā iegūtā pulsa laiks
unsigned long pulseTimeAvgFalse; //Vidējais nepatiesais iegūtais pulsa laiks
int pulseTimeAcc; // Paātrinājums starp zobiem

volatile unsigned long HallTimeNew;
volatile unsigned long HallTimeOld;
unsigned long rpm = 0;
long rpmcalc;
long advTime ; // advance time. in uS 
int totalAdv;  //should advance be a float?
int vacIn;
int mechAdv;
int vacAdv;
int aizdedze = 0;
unsigned long laiks = 0;


int multiMap(int val, int* _in, int* _out, uint8_t size)
{
  if (val <= _in[0]) return _out[0];
  if (val >= _in[size-1]) return _out[size-1];
  uint8_t pos = 1;
  while(val > _in[pos]) pos++;
  if (val == _in[pos]) return _out[pos];
  return map(val, _in[pos-1], _in[pos], _out[pos-1], _out[pos]);
}

void setup()
{
  pinMode(2, INPUT);
  pinMode(6, OUTPUT);
  attachInterrupt(0, halltrigger, FALLING );
  pulseTimeAvg = 6000000;
  
  ignitionTime1 = 640;
 
}

void aizdedzeSetup(){
  //vacIn = analogRead(A0);
  //vacIn = map(vacIn, 0, 1023, 0, 100);

   if (micros() > HallTimeNew + 60000) { rpm = 0; }
   else { rpm = 60000000/pulseTimeNew/36; } 
   mechAdv = multiMap(rpm, tableRpm, tableMechAdv, 10); 

   dwellTime = dwell / (pulseTimeAvg) * 10;
   if (rpm < 1) { dwellTime = 0; }

   ignitionDwellTime1 = ignitionTime1 - mechAdv - dwellTime - 10;
   if (zobs >= ignitionDwellTime1 && r1 == 0) {digitalWrite(6, HIGH); r1++; }

   dzirkstele1 = ignitionTime1 - mechAdv - 10;
  if (dzirkstele1 == zobs && r1 == 1) {digitalWrite(6, LOW); r1++; }
  if (zobs > dzirkstele1 && r1 == 1)
  { 
    lenkisDzirkstele1 = dzirkstele1 - zobs;
    microsDzirkstele1 = (pulseTimeNew - pulseTimeAcc) / lenkisDzirkstele1;
    if (micros() > HallTimeNew + microsDzirkstele1 ){ digitalWrite(6, LOW); r1++; } 
  }
  

   
}
  

void loop(){

  aizdedzeSetup();
  //Serial.println(dzirkstele1);

}


void halltrigger()
{
  zobs = zobs + 10;

  HallTimeOld = HallTimeNew;
  HallTimeNew = micros(); 
  pulseTime4 = pulseTime3;
  pulseTime3 = pulseTime2;
  pulseTime2 = pulseTimeNew;
  pulseTimeAvg = (pulseTime2 + pulseTime3 + pulseTime4)/3;
  pulseTimeAvgFalse = ((pulseTime2*3) + (pulseTime3*2) + pulseTime4)/6*1.5;
  pulseTimeNew = HallTimeNew - HallTimeOld;
  if (pulseTimeNew > pulseTimeAvgFalse) { zobs = zobs + 10; bezzobs++; pulseTimeNew = pulseTimeNew/2; if (bezzobs >= 2) { zobs = 0; bezzobs = 0; } }
  if (zobs == 0) { r1 = 0; }
  pulseTimeAcc = pulseTime2 - pulseTimeNew;

}

And critial place is this, it cant calculate so fast as i need :frowning:

if (zobs > dzirkstele1 && r1 == 1)
  { 
    lenkisDzirkstele1 = dzirkstele1 - zobs;
    microsDzirkstele1 = (pulseTimeNew - pulseTimeAcc) / lenkisDzirkstele1;
    if (micros() > HallTimeNew + microsDzirkstele1 ){ digitalWrite(6, LOW); r1++; } 
  }

I hope you can help me!

Sincerely, Reinis!

Start by replacing digitialWrite() with Direct Port Manipulation.

Also, eliminate division and multiplication from your code. Use only addition.

Perehama:
Also, eliminate division and multiplication from your code. Use only addition.

Hmm, how can it be possible? Maybe show me some little example!

What processor are you using?

Blackfin:
What processor are you using?

I am using ATmega2560. Maybe need some faster, like in Arduino Due?

runis6:
Hmm, how can it be possible? Maybe show me some little example!

http://forum.arduino.cc/index.php/topic,60924.0.html

I think you have a fundamental problem with the structure of your code that will result in considerable jitter no matter what you do to "optimize" it. First, you're doing WAY too much calculation. You need to seriously reduce the number of arithmetic operations, especially multiplies and divides. You need to completely eliminate floating point. You can eliminate a number of operations by working in terms of time intervals, instead of RPM. e.g. - instead of working in terms of 6000 RPM, work in terms of a 278 uSec interval between 36-1 trigger wheel pulses. Your RPM lookup table should be re-coded to work in terms of time intervals rather than RPM. In calculations, find short-cuts and approximations. For example, don't multiply by three, do two adds. In calculating the average pulse width (IF that even needs to be done), instead use a digital filter, with a simple binary co-efficient (like 1/16), so you can use shifts and adds instead of multiplies and divides.

Finally, and perhaps most importantly, your spark trigger output needs to be VERY closely timed to the trigger wheel interrupt. Right now, it is VERY loosely coupled, which will always result in a lot of jitter. Outputting the spark trigger pulse the THE HIGHEST priority task. Calculating the trigger wheel timing is FAR less important. Your interrupt handler should make note of the fact that a pulse has been detected, record WHEN it was detected, then return. Your foreground (loop()) task should then do the necessary spark advance delay, output the appropriate spark trigger, THEN do the calculations in the time BETWEEN spark trigger outputs. Right now, you're generating the spark trigger output pretty much blind, with not idea how much time has elapsed between the last trigger pulse and the spark trigger output, with a timing variation equal to the time it takes to do all the calculations taking place in your aizdedzeSetup function. That is never going to work well.

Regards,
Ray L.