diff --git a/reference/speeduino.ini b/reference/speeduino.ini index 254bb729..368b622c 100644 --- a/reference/speeduino.ini +++ b/reference/speeduino.ini @@ -196,7 +196,7 @@ page = 3 page = 4 TrigAng = scalar, S16, 0, "Deg", 1, 0, -360, 360, 0 FixAng = scalar, U08, 2, "Deg", 1, 0, 0, 80, 0 - CrankAng = scalar, U08, 3, "Deg", 1, -28.4, -10, 80, 0 + CrankAng = scalar, U08, 3, "Deg", 1, 0, -10, 80, 0 IgHold = scalar, U08, 4, "", 1, 0, 0, 100, 0 TrigEdge = bits, U08, 5[0:0], "Leading", "Trailing" TrigSpeed = bits, U08, 5[1:1], "Crank Speed", "Cam Speed" diff --git a/scheduler.ino b/scheduler.ino index 99ceb336..649dba87 100644 --- a/scheduler.ino +++ b/scheduler.ino @@ -259,10 +259,12 @@ ISR(TIMER5_COMPA_vect, ISR_NOBLOCK) //ignitionSchedule1 { if (ignitionSchedule1.Status == PENDING) //Check to see if this schedule is turn on { + if ( ign1LastRev == startRevolutions ) { return; } ignitionSchedule1.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback) ignitionSchedule1.startTime = currentLoopTime; ignitionSchedule1.StartCallback(); unsigned int absoluteTimeout = TCNT5 + (ignitionSchedule1.duration >> 4); + ign1LastRev = startRevolutions; //unsigned int absoluteTimeout = TCNT5 + (ignitionSchedule1.duration >> 2); //Divide by 4 OCR5A = absoluteTimeout; } @@ -278,10 +280,12 @@ ISR(TIMER5_COMPB_vect, ISR_NOBLOCK) //ignitionSchedule2 { if (ignitionSchedule2.Status == PENDING) //Check to see if this schedule is turn on { + if ( ign2LastRev == startRevolutions ) { return; } ignitionSchedule2.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback) ignitionSchedule2.startTime = currentLoopTime; ignitionSchedule2.StartCallback(); unsigned int absoluteTimeout = TCNT5 + (ignitionSchedule2.duration >> 4); + ign2LastRev = startRevolutions; //unsigned int absoluteTimeout = TCNT5 + (ignitionSchedule2.duration >> 2); //Divide by 4 OCR5B = absoluteTimeout; } @@ -297,10 +301,12 @@ ISR(TIMER5_COMPC_vect, ISR_NOBLOCK) //ignitionSchedule3 { if (ignitionSchedule3.Status == PENDING) //Check to see if this schedule is turn on { + if ( ign3LastRev == startRevolutions ) { return; } ignitionSchedule3.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback) ignitionSchedule3.startTime = currentLoopTime; ignitionSchedule3.StartCallback(); unsigned int absoluteTimeout = TCNT5 + (ignitionSchedule2.duration >> 4); + ign3LastRev = startRevolutions; //unsigned int absoluteTimeout = TCNT5 + (ignitionSchedule3.duration >> 2); //Divide by 4 OCR5C = absoluteTimeout; } @@ -316,11 +322,13 @@ ISR(TIMER4_COMPA_vect, ISR_NOBLOCK) //ignitionSchedule4 { if (ignitionSchedule4.Status == PENDING) //Check to see if this schedule is turn on { + if ( ign4LastRev == startRevolutions ) { return; } ignitionSchedule4.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback) ignitionSchedule4.startTime = currentLoopTime; ignitionSchedule4.StartCallback(); //unsigned int absoluteTimeout = TCNT5 + (ignitionSchedule2.duration / 16); unsigned int absoluteTimeout = TCNT4 + (ignitionSchedule4.duration >> 4); //Divide by 16 + ign4LastRev = startRevolutions; OCR4A = absoluteTimeout; } else if (ignitionSchedule4.Status == RUNNING) @@ -328,6 +336,6 @@ ISR(TIMER4_COMPA_vect, ISR_NOBLOCK) //ignitionSchedule4 ignitionSchedule4.Status = OFF; //Turn off the schedule ignitionSchedule4.EndCallback(); ignitionCount += 1; //Increment the igintion counter - TIMSK4 &= ~(1 << OCIE4A); //Turn off this output compare unit (This simply writes 0 to the OCIE3A bit of TIMSK3) + TIMSK4 &= ~(1 << OCIE4A); //Turn off this output compare unit (This simply writes 0 to the OCIE4A bit of TIMSK4) } } diff --git a/speeduino.ino b/speeduino.ino index 432df847..134398b6 100644 --- a/speeduino.ino +++ b/speeduino.ino @@ -53,6 +53,10 @@ int req_fuel_uS, inj_opentime_uS; #define MAX_RPM 10000 //This is the maximum rpm that the ECU will attempt to run at. It is NOT related to the rev limiter, but is instead dictates how fast certain operations will be allowed to run. Lower number gives better performance volatile byte startRevolutions = 0; //A counter for how many revolutions have been completed since sync was achieved. +volatile byte ign1LastRev; +volatile byte ign2LastRev; +volatile byte ign3LastRev; +volatile byte ign4LastRev; bool ignitionOn = false; //The current state of the ignition system bool fuelOn = false; //The current state of the ignition system bool fuelPumpOn = false; //The current status of the fuel pump @@ -527,21 +531,19 @@ void loop() //Speed Density currentStatus.VE = get3DTableValue(&fuelTable, currentStatus.MAP, currentStatus.RPM); //Perform lookup into fuel map for RPM vs MAP value currentStatus.PW = PW_SD(req_fuel_uS, currentStatus.VE, currentStatus.MAP, currentStatus.corrections, inj_opentime_uS); - if (configPage2.FixAng == 0) //Check whether the user has set a fixed timing angle - { currentStatus.advance = get3DTableValue(&ignitionTable, currentStatus.MAP, currentStatus.RPM); } //As above, but for ignition advance - else - { currentStatus.advance = configPage2.FixAng; } + currentStatus.advance = get3DTableValue(&ignitionTable, currentStatus.MAP, currentStatus.RPM); //As above, but for ignition advance } else { //Alpha-N currentStatus.VE = get3DTableValue(&fuelTable, currentStatus.TPS, currentStatus.RPM); //Perform lookup into fuel map for RPM vs TPS value currentStatus.PW = PW_AN(req_fuel_uS, currentStatus.VE, currentStatus.TPS, currentStatus.corrections, inj_opentime_uS); //Calculate pulsewidth using the Alpha-N algorithm (in uS) - if (configPage2.FixAng == 0) //Check whether the user has set a fixed timing angle - { currentStatus.advance = get3DTableValue(&ignitionTable, currentStatus.TPS, currentStatus.RPM); } //As above, but for ignition advance - else - { currentStatus.advance = configPage2.FixAng; } + currentStatus.advance = get3DTableValue(&ignitionTable, currentStatus.TPS, currentStatus.RPM); //As above, but for ignition advance } + + //Check for fixed ignition angles + if (configPage2.FixAng != 0) { currentStatus.advance = configPage2.FixAng; } //Check whether the user has set a fixed timing angle + if ( BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK) ) { currentStatus.advance = configPage2.CrankAng; } //Use the fixed cranking ignition angle int injector1StartAngle = 0; int injector2StartAngle = 0; @@ -559,9 +561,12 @@ void loop() //How fast are we going? Need to know how long (uS) it will take to get from one tooth to the next. We then use that to estimate how far we are between the last tooth and the next one timePerDegree = ldiv( 166666L, currentStatus.RPM ).quot; //There is a small amount of rounding in this calculation, however it is less than 0.001 of a uS (Faster as ldiv than / ) - //Check that the duty cycle of the chosen pulsewidth isn't too high - unsigned int pwLimit = percentage(configPage1.dutyLim, revolutionTime); //The pulsewidth limit is determined to be the duty cycle limit (Eg 85%) by the total time it takes to perform 1 revolution - if (currentStatus.PW > pwLimit) { currentStatus.PW = pwLimit; } + //Check that the duty cycle of the chosen pulsewidth isn't too high. This is disabled at cranking + if( !BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK) ) + { + unsigned int pwLimit = percentage(configPage1.dutyLim, revolutionTime); //The pulsewidth limit is determined to be the duty cycle limit (Eg 85%) by the total time it takes to perform 1 revolution + if (currentStatus.PW > pwLimit) { currentStatus.PW = pwLimit; } + } //*********************************************************************************************** @@ -773,7 +778,7 @@ void loop() if(ignitionOn && (currentStatus.RPM < ((unsigned int)(configPage2.HardRevLim) * 100) )) { if ( (ignition1StartAngle > crankAngle) ) - { + { setIgnitionSchedule1(beginCoil1Charge, ((unsigned long)(ignition1StartAngle - crankAngle) * (unsigned long)timePerDegree), currentStatus.dwell,