diff --git a/reference/speeduino.ini b/reference/speeduino.ini index 8ae5fc46..57ea3d94 100644 --- a/reference/speeduino.ini +++ b/reference/speeduino.ini @@ -502,7 +502,7 @@ page = 4 fuelPumpPin= bits , U08, 6,[1:6], "Board Default", "INVALID", "INVALID", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "INVALID", "A8", "A9", "A10", "A11", "A12", "A13", "A14", "A15", "INVALID" useResync = bits, U08, 6,[7:7], "No", "Yes" sparkDur = scalar, U08, 7, "ms", 0.1, 0, 0, 25.5, 1 ; Spark duration - trigPatternSec = bits,U08, 8,[0:6], "Single tooth cam", "4-1 cam", "Poll level", "Rover 5-3-2 cam", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID" + trigPatternSec = bits,U08, 8,[0:6], "Single tooth cam", "4-1 cam", "Poll level", "Rover 5-3-2 cam", "Nissan 1-3-4-2", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID" PollLevelPol = bits, U08, 8,[7:7], "Low", "High", ;Reset Control @@ -665,7 +665,7 @@ page = 6 useExtBaro = bits, U08, 13, [6:6], "No", "Yes" boostMode = bits, U08, 13, [7:7], "Simple", "Full" boostPin = bits, U08, 14, [0:5], "Board Default", "INVALID", "INVALID", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID" - tachoMode = bits, U08, 14, [6:6], "Fixed Duration", "Match Dwell" + unused_bit = bits, U08, 14, [6:6], "No", "Yes" useEMAP = bits, U08, 14, [7:7], "No", "Yes" brvBins = array, U08, 15, [6], "V", 0.1, 0, 6, 24, 1 ; Bins for the battery reference voltage injBatRates = array, U08, 21, [6], "%", 1, 0, 0, 255, 0 ;Values for injector pulsewidth vs voltage @@ -2355,7 +2355,6 @@ menuDialog = main battVCorMode = "The Battery Voltage Correction value from the table below can either be applied on the whole injection Pulse Width value, or only on the Open Time value." dwellTable = "Sets the dwell time in milliseconds based on RPM/load. This can be used to reduce stress/wear on ignition system where long dwell is not needed. And other areas can use longer dwell value if needed for stronger spark. Battery voltage correction is applied for these dwell values." useDwellMap = "In normal operation mode this is set to No and speeduino will use fixed running dwell value. But if different dwell values are required across engine RPM/load range, this can be set to Yes and separate Dwell table defines running dwell value." - tachoMode = "The output mode for the tacho pulse. Fixed timing will produce a pulse that is always of the same duration, which works better with mode modern digital tachos. Dwell based output creates a pulse that is matched to the coil/s dwell time. If enabled the tacho pulse duration and timing is same as coil dwell and the number of pulses is same as number of ignition events. This can work better on some styles of tacho but note that the pulse duration might become problem on higher cylinder number engines." canBMWCluster = "Enables CAN broadcasting for BMW E46, E39 and E38 instrument clusters with message ID's 0x316, 0x329 and 0x545" canVAGCluster = "Enables CAN broadcasting for VAG instrument clusters with message ID's 0x280 and 0x5A0" caninputEndianess= "Byte ordering for values with two bytes." @@ -2835,7 +2834,7 @@ menuDialog = main field = "Trigger Pattern", TrigPattern field = "Primary base teeth", numTeeth, { TrigPattern == 0 || TrigPattern == 2 || TrigPattern == 11 || TrigPattern == 18 || TrigPattern == 19 || TrigPattern == 21 } field = "Primary trigger speed", TrigSpeed, { TrigPattern == 0 || TrigPattern == 2 } - field = "Missing teeth", missingTeeth, { TrigPattern == 0 } + field = "Missing teeth", missingTeeth, { TrigPattern == 0 || TrigPattern == 2 } field = "Trigger angle multiplier", TrigAngMul, { TrigPattern == 11 } field = "Trigger Angle ", TrigAng field = "This number represents the angle ATDC when " diff --git a/speeduino/decoders.ino b/speeduino/decoders.ino index 609d39ba..7ba2c997 100644 --- a/speeduino/decoders.ino +++ b/speeduino/decoders.ino @@ -784,20 +784,497 @@ Note: There can be no missing teeth on the primary wheel. /** Dual Wheel Setup. * * */ + + byte doubleGapHalfTeeth=0; + byte doubleGap1=0, doubleGap2=0; + void triggerSetup_DualWheel(void) { + // triggerToothAngle = 360 / configPage4.triggerTeeth; //The number of degrees that passes from tooth to tooth triggerToothAngle = 360 / configPage4.triggerTeeth; //The number of degrees that passes from tooth to tooth - if(configPage4.TrigSpeed == CAM_SPEED) { triggerToothAngle = 720 / configPage4.triggerTeeth; } //Account for cam speed + if(configPage4.TrigSpeed == CAM_SPEED) { triggerToothAngle = 720 / configPage4.triggerTeeth; } //Account for cam speed toothCurrentCount = 255; //Default value - triggerFilterTime = (1000000 / (MAX_RPM / 60 * configPage4.triggerTeeth)); //Trigger filter time is the shortest possible time (in uS) that there can be between crank teeth (ie at max RPM). Any pulses that occur faster than this time will be discarded as noise + secondaryToothCount = 0; + triggerFilterTime = (1000000 / (MAX_RPM / 60 * configPage4.triggerTeeth)); //Trigger filter time is the shortest possible time (in uS) that there can be between crank teeth (ie at max RPM). Any pulses that occur faster than this time will be disgarded as noise triggerSecFilterTime = (1000000 / (MAX_RPM / 60 * 2)) / 2; //Same as above, but fixed at 2 teeth on the secondary input and divided by 2 (for cam speed) BIT_CLEAR(decoderState, BIT_DECODER_2ND_DERIV); BIT_SET(decoderState, BIT_DECODER_IS_SEQUENTIAL); BIT_SET(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT); //This is always true for this pattern BIT_SET(decoderState, BIT_DECODER_HAS_SECONDARY); MAX_STALL_TIME = (3333UL * triggerToothAngle); //Minimum 50rpm. (3333uS is the time per degree at 50rpm) + + // MAX_STALL_TIME = 166667 * triggerToothAngle; //1 rpm for testing + + targetGap = 100000L; // random value larger than 0 to ensure we start off being less than target + toothLastToothTime = 0; + toothLastMinusOneToothTime = 0; + +//------------ + + checkSyncToothCount = (configPage4.triggerTeeth) >> 2; //25% of the total teeth. + + doubleGapHalfTeeth = configPage4.triggerTeeth / 2; + + // this is the tooth after the gap + doubleGap1 = doubleGapHalfTeeth+1; + doubleGap2 = configPage4.triggerTeeth+1; + + + // Serial3.begin (38400); + } +#define toothAfterGap curGap3 +void triggerPri_DualWheel_v2() +{ + curTime = micros(); + curGap = curTime - toothLastToothTime; + if ( curGap >= triggerFilterTime || toothLastMinusOneToothTime == 0) // ensure we do this code until we've seen 2 teeth + { + toothCurrentCount++; //Increment the tooth counter + BIT_SET(decoderState, BIT_DECODER_VALID_TRIGGER); //Flag this pulse as being a valid trigger (ie that it passed filters) + + // Serial3.print(" "); + // Serial3.print(toothCurrentCount); + + if( (toothLastToothTime > 0) && (toothLastMinusOneToothTime > 0) ) + { + //Begin the missing tooth detection + //If the time between the current tooth and the last is greater than 2x the time between the last tooth and the tooth before that, we make the assertion that we must be at the first tooth after the gap + + targetGap = ((toothLastToothTime - toothLastMinusOneToothTime)) * 2; //Multiply by 2 (Checks for a gap 2x greater than the last one) + + if ( curGap > targetGap ) + { + // Found a missing tooth, need to add additional missing teeth to toothCurrentCount & set missing tooth flag & triggerToothAngleIsCorrect to false + toothCurrentCount = toothCurrentCount + 2; + // Serial3.print(" GAP GAP"); + + + // fake the last gap to ensure when we get to tooth 2 after the gap we don't get a silly large gap due to the missing teeth being part of the maths + curGap = toothLastToothTime - toothLastMinusOneToothTime; + toothLastToothTime = curTime - curGap; + toothLastMinusOneToothTime = toothLastToothTime - curGap; + + BIT_CLEAR(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT); + + // does the tooth = tooth after gap Should do otherwise lost sync + + // all code could be simplifed to "if (toothCurrent == toothAfterGap) hassync else lost sync + + if( (configPage2.nCylinders == 4 && toothCurrentCount != 19 && toothCurrentCount != 37 ) + || (configPage2.nCylinders == 6 && toothCurrentCount != 13 && toothCurrentCount != 25 && toothCurrentCount != 37 ) + || (configPage2.nCylinders == 8 && toothCurrentCount != 10 && toothCurrentCount != 19 && toothCurrentCount != 28 && toothCurrentCount != 37 ) + ) + { + // lost Sync as gap should be at the tooth after gap1 or gap2 + // Serial3.print(" LostSYNC1 "); + // Serial3.print(toothCurrentCount); + currentStatus.hasSync = false; + currentStatus.syncLossCounter++; + triggerFilterTime = (1000000 / (MAX_RPM / 60 * configPage4.triggerTeeth)); //Trigger filter time is the shortest possible time (in uS) that there can be between crank teeth (ie at max RPM). Any pulses that occur faster than this time will be disgarded as noise + toothLastToothTime = 0; + toothLastMinusOneToothTime = 0; + toothCurrentCount = toothAfterGap; + } + else + { + // now we think we're at the right place on crank, check if the cam is correct as well before calling sync + if ( toothCurrentCount == toothAfterGap ) + { + currentStatus.hasSync = true; + } + else + { + // Serial3.print(" LostSYNC2 "); + // Serial3.print(toothAfterGap); + // Serial3.print(":"); + // Serial3.print(toothCurrentCount); + // Serial3.print("> "); + currentStatus.hasSync = false; + currentStatus.syncLossCounter++; + triggerFilterTime = (1000000 / (MAX_RPM / 60 * configPage4.triggerTeeth)); //Trigger filter time is the shortest possible time (in uS) that there can be between crank teeth (ie at max RPM). Any pulses that occur faster than this time will be disgarded as noise + toothLastToothTime = 0; + toothLastMinusOneToothTime = 0; + toothCurrentCount = toothAfterGap; + } + } + } + else + { + // no gap in trigger wheel, normal tooth + setFilter(curGap); //Recalc the new filter value + BIT_SET(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT); + } + + + if ( currentStatus.hasSync == true ) + { + if( toothCurrentCount > configPage4.triggerTeeth ) + { + // Serial3.println(" ROT "); + toothCurrentCount = toothCurrentCount - configPage4.triggerTeeth ; + if( toothCurrentCount != 1) + { + // Serial3.print(" LostSYNC3"); + currentStatus.hasSync = false; + currentStatus.syncLossCounter++; + BIT_SET(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT); + toothCurrentCount = 1; + } + + revolutionOne = !revolutionOne; //Flip sequential revolution tracker + toothOneMinusOneTime = toothOneTime; + toothOneTime = curTime; + currentStatus.startRevolutions++; //Counter + } + } + else + { + // no sync or not seen enough teeth - can't let trigger wheel tooth counter get greater than teeth on wheel + if (toothCurrentCount > configPage4.triggerTeeth) + { + toothCurrentCount = 1; + } + } + + } + + toothLastMinusOneToothTime = toothLastToothTime; + toothLastToothTime = curTime; + //NEW IGNITION MODE + if( (configPage2.perToothIgn == true) && (!BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK)) ) + { + int16_t crankAngle = ( (toothCurrentCount-1) * triggerToothAngle ) + configPage4.triggerAngle; + // crankAngle = ignitionLimits(crankAngle); + if( (configPage4.sparkMode == IGN_MODE_SEQUENTIAL) && (revolutionOne == true) && (configPage4.TrigSpeed == CRANK_SPEED) ) + { + crankAngle += 360; + checkPerToothTiming(crankAngle, (configPage4.triggerTeeth + toothCurrentCount)); + } + else{ checkPerToothTiming(crankAngle, toothCurrentCount); } + } + } //Trigger filter +} + +/** Dual Wheel Secondary. + * + * */ + + +void triggerSec_DualWheel_v2() +{ + curTime2 = micros(); + curGap2 = curTime2 - toothLastSecToothTime; + + if ( curGap2 >= triggerFilterTime) // filter at same rate as crank on assumption more teeth on crank than cam. Due to variable tooth gaps on cam this seems safer implementation of filtering + { + toothLastMinusOneSecToothTime = toothLastSecToothTime; + toothLastSecToothTime = curTime2; + + switch(configPage4.trigPatternSec) + { + case SEC_TRIGGER_SINGLE: + if( (currentStatus.hasSync == false) || (currentStatus.startRevolutions <= configPage4.StgCycles) ) + { + // no sync & only just started the engine and first time we've seen cam + toothLastToothTime = micros(); + toothLastMinusOneToothTime = micros() - (6000000 / configPage4.triggerTeeth); //Fixes RPM at 10rpm until a full revolution has taken place + toothCurrentCount = configPage4.triggerTeeth; + triggerFilterTime = 0; //Need to turn the filter off here otherwise the first primary tooth after achieving sync is ignored + + currentStatus.hasSync = true; + } + else + { + if ( (toothCurrentCount != configPage4.triggerTeeth) && (currentStatus.startRevolutions > 2)) { currentStatus.syncLossCounter++; } //Indicates likely sync loss. + if (configPage4.useResync == 1) { toothCurrentCount = configPage4.triggerTeeth; } + } + toothAfterGap = 1; + revolutionOne = 1; //Sequential revolution reset + //Record the VVT Angle + if( (configPage6.vvtEnabled > 0) && (revolutionOne == 1) ) + { + int16_t curAngle; + curAngle = getCrankAngle(); + while(curAngle > 360) { curAngle -= 360; } + curAngle -= configPage4.triggerAngle; //Value at TDC + if( configPage6.vvtMode == VVT_MODE_CLOSED_LOOP ) { curAngle -= configPage10.vvtCL0DutyAng; } + + currentStatus.vvt1Angle = ANGLE_FILTER( (curAngle << 1), configPage4.ANGLEFILTER_VVT, currentStatus.vvt1Angle); + } + break; + + + case SEC_TRIGGER_NISSAN_1_3_4_2: + targetGap2 = targetGap * 4; // target gap to identify large gap between teeth. Assumes 4 is a reasonable size. Works for Nissan engine with this trigger pattern + + if ( curGap2 >= targetGap2 ) + { + // had a large gap betwen teeth and then seen a tooth. Use the counter to work out which tooth we've seen after the gap then reset the gap counter + // remember this is the cam tooth AFTER the tooth counted. + switch( secondaryToothCount) + { + case 2: //315 degrees on 4 cylinder + // is detected at the first tooth of the 1 tooth cam + revolutionOne = 0; //Sequential revolution reset + switch (configPage2.nCylinders) + { + case 4: + case 6: + case 8: + toothAfterGap = 37; + break; + } + break; + + + case 1: //135 degrees on 4 cylinder + // is detected at the first tooth of the 3 tooth cam pattern + revolutionOne = 0; //Sequential revolution reset + switch (configPage2.nCylinders) + { + case 4: + case 8: + toothAfterGap = 19; + break; + case 6: + toothAfterGap = 17; + break; + } + break; + + case 3: //334.5 degrees on 4 cylinder + // is detected at the first tooth of the 4 tooth cam + revolutionOne = 1; //Sequential revolution reset + switch (configPage2.nCylinders) + { + case 4: + case 8: + case 6: + toothAfterGap = 37; + break; + } + + break; + + case 4: //155 degrees on 4 cylinder + // is detected at the first tooth of the 2 tooth cam + revolutionOne = 1; //Sequential revolution reset + switch (configPage2.nCylinders) + { + case 4: + case 8: + toothAfterGap = 19; + break; + case 6: + toothAfterGap = 17; + break; + } + if( (configPage6.vvtEnabled > 0) ) + { + int16_t curAngle; + curAngle = getCrankAngle(); + while(curAngle > 360) { curAngle -= 360; } + curAngle -= configPage4.triggerAngle; //Value at TDC + if( configPage6.vvtMode == VVT_MODE_CLOSED_LOOP ) { curAngle -= configPage10.vvtCL0DutyAng; } + + currentStatus.vvt1Angle = ANGLE_FILTER( (curAngle << 1), configPage4.ANGLEFILTER_VVT, currentStatus.vvt1Angle); + } + break; + } + secondaryToothCount = 1; + } + else + { + secondaryToothCount++; + } + break; + + default: + // have a cam selected that we don't have a decoder for. + currentStatus.hasSync = false; + currentStatus.syncLossCounter++; + break; + } + + + + } //Trigger filter +} + +void triggerSetEndTeeth_DualWheel_v2() +{ + //The toothAdder variable is used for when a setup is running sequentially, but the primary wheel is running at crank speed. This way the count of teeth will go up to 2* the number of primary teeth to allow for a sequential count. + byte toothAdder = 0; + if( (configPage4.sparkMode == IGN_MODE_SEQUENTIAL) && (configPage4.TrigSpeed == CRANK_SPEED) ) { toothAdder = configPage4.triggerTeeth; } + + int16_t tempIgnition1EndTooth; + tempIgnition1EndTooth = ( (ignition1EndAngle - configPage4.triggerAngle) / (int16_t)(triggerToothAngle) ); + if(tempIgnition1EndTooth > (configPage4.triggerTeeth + toothAdder)) { tempIgnition1EndTooth -= (configPage4.triggerTeeth + toothAdder); } + if(tempIgnition1EndTooth <= 0) { tempIgnition1EndTooth += (configPage4.triggerTeeth + toothAdder); } + + int16_t tempIgnition2EndTooth; + tempIgnition2EndTooth = ( (ignition2EndAngle - configPage4.triggerAngle) / (int16_t)(triggerToothAngle) ); + if(tempIgnition2EndTooth > (configPage4.triggerTeeth + toothAdder)) { tempIgnition2EndTooth -= (configPage4.triggerTeeth + toothAdder); } + if(tempIgnition2EndTooth <= 0) { tempIgnition2EndTooth += (configPage4.triggerTeeth + toothAdder); } + + int16_t tempIgnition3EndTooth; + tempIgnition3EndTooth = ( (ignition3EndAngle - configPage4.triggerAngle) / (int16_t)(triggerToothAngle) ); + if(tempIgnition3EndTooth > (configPage4.triggerTeeth + toothAdder)) { tempIgnition3EndTooth -= (configPage4.triggerTeeth + toothAdder); } + if(tempIgnition3EndTooth <= 0) { tempIgnition3EndTooth += (configPage4.triggerTeeth + toothAdder); } + + int16_t tempIgnition4EndTooth; + tempIgnition4EndTooth = ( (ignition4EndAngle - configPage4.triggerAngle) / (int16_t)(triggerToothAngle) ); + if(tempIgnition4EndTooth > (configPage4.triggerTeeth + toothAdder)) { tempIgnition4EndTooth -= (configPage4.triggerTeeth + toothAdder); } + if(tempIgnition4EndTooth <= 0) { tempIgnition4EndTooth += (configPage4.triggerTeeth + toothAdder); } + +#if IGN_CHANNELS >= 5 + int16_t tempIgnition5EndTooth; + tempIgnition5EndTooth = ( (ignition5EndAngle - configPage4.triggerAngle) / (int16_t)(triggerToothAngle) ); + if(tempIgnition5EndTooth > (configPage4.triggerTeeth + toothAdder)) { tempIgnition5EndTooth -= (configPage4.triggerTeeth + toothAdder); } + if(tempIgnition5EndTooth <= 0) { tempIgnition5EndTooth += (configPage4.triggerTeeth + toothAdder); } +#endif +#if IGN_CHANNELS >= 6 + int16_t tempIgnition6EndTooth; + tempIgnition6EndTooth = ( (ignition6EndAngle - configPage4.triggerAngle) / (int16_t)(triggerToothAngle) ); + if(tempIgnition6EndTooth > (configPage4.triggerTeeth + toothAdder)) { tempIgnition6EndTooth -= (configPage4.triggerTeeth + toothAdder); } + if(tempIgnition6EndTooth <= 0) { tempIgnition6EndTooth += (configPage4.triggerTeeth + toothAdder); } +#endif +#if IGN_CHANNELS >= 7 + int16_t tempIgnition7EndTooth; + tempIgnition7EndTooth = ( (ignition7EndAngle - configPage4.triggerAngle) / (int16_t)(triggerToothAngle) ); + if(tempIgnition7EndTooth > (configPage4.triggerTeeth + toothAdder)) { tempIgnition7EndTooth -= (configPage4.triggerTeeth + toothAdder); } + if(tempIgnition7EndTooth <= 0) { tempIgnition7EndTooth += (configPage4.triggerTeeth + toothAdder); } +#endif +#if IGN_CHANNELS >= 8 + int16_t tempIgnition8EndTooth; + tempIgnition8EndTooth = ( (ignition8EndAngle - configPage4.triggerAngle) / (int16_t)(triggerToothAngle) ); + if(tempIgnition8EndTooth > (configPage4.triggerTeeth + toothAdder)) { tempIgnition8EndTooth -= (configPage4.triggerTeeth + toothAdder); } + if(tempIgnition8EndTooth <= 0) { tempIgnition8EndTooth += (configPage4.triggerTeeth + toothAdder); } +#endif + +// take into account the missing teeth on the flywheels + + if( configPage4.triggerMissingTeeth == 0) + { + ignition1EndTooth = tempIgnition1EndTooth; + ignition2EndTooth = tempIgnition2EndTooth; + ignition3EndTooth = tempIgnition3EndTooth; + ignition4EndTooth = tempIgnition4EndTooth; + +#if IGN_CHANNELS >= 5 + ignition5EndTooth = tempIgnition5EndTooth; +#endif +#if IGN_CHANNELS >= 6 + ignition6EndTooth = tempIgnition6EndTooth; +#endif +#if IGN_CHANNELS >= 7 + ignition7EndTooth = tempIgnition7EndTooth; +#endif +#if IGN_CHANNELS >= 8 + ignition8EndTooth = tempIgnition8EndTooth; +#endif + } + else if (configPage4.sparkMode == IGN_MODE_SEQUENTIAL) + { + // check the calculated trigger tooth exists, if it doesn't use the previous tooth + // nb the toothAngles[x] holds the tooth after the gap, hence the '-1' to see if it matches a gap + + if( tempIgnition1EndTooth < configPage4.triggerTeeth) { ignition1EndTooth = triggerToothCalc_v2 (tempIgnition1EndTooth,0); } // 0 to 360 degrees + else { ignition1EndTooth = triggerToothCalc_v2 (tempIgnition1EndTooth,configPage4.triggerTeeth); } // tooth is on the 360 to 720 degrees + + if( tempIgnition2EndTooth < configPage4.triggerTeeth) { ignition2EndTooth = triggerToothCalc_v2 (tempIgnition2EndTooth,0); } // 0 to 360 degrees + else { ignition2EndTooth = triggerToothCalc_v2 (tempIgnition2EndTooth,configPage4.triggerTeeth); } // tooth is on the 360 to 720 degrees + + if( tempIgnition3EndTooth < configPage4.triggerTeeth) { ignition3EndTooth = triggerToothCalc_v2 (tempIgnition3EndTooth,0); } // 0 to 360 degrees + else { ignition3EndTooth = triggerToothCalc_v2 (tempIgnition3EndTooth,configPage4.triggerTeeth); } // tooth is on the 360 to 720 degrees + + if( tempIgnition4EndTooth < configPage4.triggerTeeth) { ignition4EndTooth = triggerToothCalc_v2 (tempIgnition4EndTooth,0); } // 0 to 360 degrees + else { ignition4EndTooth = triggerToothCalc_v2 (tempIgnition4EndTooth,configPage4.triggerTeeth); } // tooth is on the 360 to 720 degrees + +#if IGN_CHANNELS >= 5 + if( tempIgnition5EndTooth < configPage4.triggerTeeth) { ignition5EndTooth = triggerToothCalc_v2 (tempIgnition5EndTooth,0); } // 0 to 360 degrees + else { ignition5EndTooth = triggerToothCalc_v2 (tempIgnition5EndTooth,configPage4.triggerTeeth); } // tooth is on the 360 to 720 degrees +#endif + +#if IGN_CHANNELS >= 6 + if( tempIgnition6EndTooth < configPage4.triggerTeeth) { ignition6EndTooth = triggerToothCalc_v2 (tempIgnition6EndTooth,0); } // 0 to 360 degrees + else { ignition6EndTooth = triggerToothCalc_v2 (tempIgnition6EndTooth,configPage4.triggerTeeth); } // tooth is on the 360 to 720 degrees +#endif + +#if IGN_CHANNELS >= 7 + if( tempIgnition7EndTooth < configPage4.triggerTeeth) { ignition7EndTooth = triggerToothCalc_v2 (tempIgnition7EndTooth,0); } // 0 to 360 degrees + else { ignition7EndTooth = triggerToothCalc_v2 (tempIgnition7EndTooth,configPage4.triggerTeeth); } // tooth is on the 360 to 720 degrees +#endif + +#if IGN_CHANNELS >= 8 + if( tempIgnition8EndTooth < configPage4.triggerTeeth) { ignition8EndTooth = triggerToothCalc_v2 (tempIgnition8EndTooth,0); } // 0 to 360 degrees + else { ignition8EndTooth = triggerToothCalc_v2 (tempIgnition8EndTooth,configPage4.triggerTeeth); } // tooth is on the 360 to 720 degrees +#endif + } + else + { + ignition1EndTooth = triggerToothCalc_v2 (tempIgnition1EndTooth,0); + ignition2EndTooth = triggerToothCalc_v2 (tempIgnition2EndTooth,0); + ignition3EndTooth = triggerToothCalc_v2 (tempIgnition3EndTooth,0); + ignition4EndTooth = triggerToothCalc_v2 (tempIgnition4EndTooth,0); +#if IGN_CHANNELS >= 5 + ignition5EndTooth = triggerToothCalc_v2 (tempIgnition5EndTooth,0); // 0 to 360 degrees +#endif + +#if IGN_CHANNELS >= 6 + ignition6EndTooth = triggerToothCalc_v2 (tempIgnition6EndTooth,0); // 0 to 360 degrees +#endif + +#if IGN_CHANNELS >= 7 + ignition7EndTooth = triggerToothCalc_v2 (tempIgnition7EndTooth,0); // 0 to 360 degrees +#endif + +#if IGN_CHANNELS >= 8 + ignition8EndTooth = triggerToothCalc_v2 (tempIgnition8EndTooth,0); // 0 to 360 degrees +#endif + } + + lastToothCalcAdvance = currentStatus.advance; +} + +char triggerToothCalc_v2(int16_t tempIgnitionEndTooth, byte tempSequentialTooth) +{ + switch(configPage2.nCylinders) + { + case 4: + if(tempIgnitionEndTooth == 17 || tempIgnitionEndTooth == 18) + { tempIgnitionEndTooth = 16;} + else if (tempIgnitionEndTooth == 35 || tempIgnitionEndTooth == 36) + { tempIgnitionEndTooth = 34;} + break; + + case 6: + if(tempIgnitionEndTooth == 11 || tempIgnitionEndTooth == 12) + { tempIgnitionEndTooth = 10;} + else if (tempIgnitionEndTooth == 23 || tempIgnitionEndTooth == 24) + { tempIgnitionEndTooth = 22;} + else if (tempIgnitionEndTooth == 35 || tempIgnitionEndTooth == 36) + { tempIgnitionEndTooth = 34;} + break; + + case 8: + if(tempIgnitionEndTooth == 8 || tempIgnitionEndTooth == 9) + { tempIgnitionEndTooth = 7;} + else if (tempIgnitionEndTooth == 17 || tempIgnitionEndTooth == 18) + { tempIgnitionEndTooth = 16;} + else if (tempIgnitionEndTooth == 26 || tempIgnitionEndTooth == 27) + { tempIgnitionEndTooth = 25;} + else if (tempIgnitionEndTooth == 35 || tempIgnitionEndTooth == 36) + { tempIgnitionEndTooth = 34;} + break; + } + return tempIgnitionEndTooth; +} + + + /** Dual Wheel Primary. * * */ @@ -4808,7 +5285,6 @@ void triggerPri_Vmax(void) toothOneTime = curTime; currentStatus.hasSync = true; setFilter((curGap/1.75));//Angle to this tooth is 70, next is in 40, compensating. - currentStatus.startRevolutions++; //Counter } else if (toothCurrentCount==2) { @@ -4842,6 +5318,7 @@ void triggerPri_Vmax(void) } toothLastMinusOneToothTime = toothLastToothTime; toothLastToothTime = curTime; + currentStatus.startRevolutions++; //Counter if (triggerFilterTime > 50000){//The first pulse seen triggerFilterTime = 0; } diff --git a/speeduino/globals.h b/speeduino/globals.h index eb03ee91..7e7460dc 100644 --- a/speeduino/globals.h +++ b/speeduino/globals.h @@ -288,6 +288,7 @@ #define SEC_TRIGGER_4_1 1 #define SEC_TRIGGER_POLL 2 #define SEC_TRIGGER_5_3_2 3 +#define SEC_TRIGGER_NISSAN_1_3_4_2 4 #define ROTARY_IGN_FC 0 #define ROTARY_IGN_FD 1 @@ -1056,7 +1057,7 @@ struct config6 { byte useExtBaro : 1; byte boostMode : 1; /// Boost control mode: 0=Simple (BOOST_MODE_SIMPLE) or 1=full (BOOST_MODE_FULL) byte boostPin : 6; - byte tachoMode : 1; /// Whether to use fixed tacho pulse duration or match to dwell duration + byte unused_bit : 1; //Previously was VVTasOnOff byte useEMAP : 1; ///< Enable EMAP byte voltageCorrectionBins[6]; //X axis bins for voltage correction tables byte injVoltageCorrectionValues[6]; //Correction table for injector PW vs battery voltage diff --git a/speeduino/init.ino b/speeduino/init.ino index c256845e..8d95efe9 100644 --- a/speeduino/init.ino +++ b/speeduino/init.ino @@ -1953,7 +1953,6 @@ void setPinMapping(byte boardID) pinTrigger3 = 20; //The Cam sensor 2 pin pinTPS = A2;//TPS input pin pinMAP = A3; //MAP sensor pin - pinEMAP = A15; //EMAP sensor pin pinIAT = A0; //IAT sensor pin pinCLT = A1; //CLT sensor pin pinO2 = A8; //O2 Sensor pin @@ -1975,11 +1974,6 @@ void setPinMapping(byte boardID) pinFlex = 2; // Flex sensor pinResetControl = 43; //Reset control output pinVSS = 3; //VSS input pin - pinWMIEmpty = 31; //(placeholder) - pinWMIIndicator = 33; //(placeholder) - pinWMIEnabled = 35; //(placeholder) - pinIdleUp = 37; //(placeholder) - pinCTPS = A6; //(placeholder) #elif defined(STM32F407xx) pinInjector1 = PB15; //Output pin injector 1 pinInjector2 = PB14; //Output pin injector 2 @@ -2001,7 +1995,6 @@ void setPinMapping(byte boardID) pinTrigger2 = PD4; //The Cam Sensor pin pinTPS = PA2;//TPS input pin pinMAP = PA3; //MAP sensor pin - pinEMAP = PC5; //EMAP sensor pin pinIAT = PA0; //IAT sensor pin pinCLT = PA1; //CLS sensor pin pinO2 = PB0; //O2 Sensor pin @@ -2023,11 +2016,6 @@ void setPinMapping(byte boardID) pinFlex = PD7; // Flex sensor pinResetControl = PB7; //Reset control output pinVSS = PB6; //VSS input pin - pinWMIEmpty = PD15; //(placeholder) - pinWMIIndicator = PD13; //(placeholder) - pinWMIEnabled = PE15; //(placeholder) - pinIdleUp = PE14; //(placeholder) - pinCTPS = PA6; //(placeholder) #endif break; @@ -2388,52 +2376,6 @@ void setPinMapping(byte boardID) - #endif - break; - - case 56: - #if defined(CORE_TEENSY) - //Pin mappings for the Bear Cub (Teensy 4.1) - pinInjector1 = 6; - pinInjector2 = 7; - pinInjector3 = 9; - pinInjector4 = 8; - pinInjector5 = 0; //Not used - pinCoil1 = 2; - pinCoil2 = 3; - pinCoil3 = 4; - pinCoil4 = 5; - - pinTrigger = 20; //The CAS pin - pinTrigger2 = 21; //The Cam Sensor pin - pinFlex = 37; // Flex sensor - pinMAP = A5; //MAP sensor pin - pinBaro = A4; //Baro sensor pin - pinBat = A15; //Battery reference voltage pin - pinTPS = A3; //TPS input pin - pinIAT = A0; //IAT sensor pin - pinCLT = A1; //CLS sensor pin - pinO2 = A2; //O2 Sensor pin - pinLaunch = 36; - - pinSpareTemp1 = A16; //spare Analog input 1 - pinSpareTemp2 = A17; //spare Analog input 2 - pinTachOut = 38; //Tacho output pin - pinIdle1 = 27; //Single wire idle control - pinIdle2 = 26; //2 wire idle control. Shared with Spare 1 output - pinFuelPump = 10; //Fuel pump output - pinVVT_1 = 28; //Default VVT output - pinStepperDir = 32; //Direction pin for DRV8825 driver - pinStepperStep = 31; //Step pin for DRV8825 driver - pinStepperEnable = 30; //Enable pin for DRV8825 driver - pinBoost = 24; //Boost control - pinSpareLOut1 = 29; //low current output spare1 - pinSpareLOut2 = 26; //low current output spare2 - pinSpareLOut3 = 28; //low current output spare3 - pinSpareLOut4 = 29; //low current output spare4 - pinFan = 25; //Pin for the fan output - pinResetControl = 46; //Reset control output PLACEHOLDER value for now - #endif break; @@ -3186,13 +3128,13 @@ void initialiseTriggers(void) attachInterrupt(triggerInterrupt, triggerHandler, primaryTriggerEdge); break; - case 2: + case DECODER_DUAL_WHEEL: triggerSetup_DualWheel(); - triggerHandler = triggerPri_DualWheel; - triggerSecondaryHandler = triggerSec_DualWheel; - getRPM = getRPM_DualWheel; + triggerHandler = triggerPri_DualWheel_v2; + triggerSecondaryHandler = triggerSec_DualWheel_v2; getCrankAngle = getCrankAngle_DualWheel; - triggerSetEndTeeth = triggerSetEndTeeth_DualWheel; + triggerSetEndTeeth = triggerSetEndTeeth_DualWheel_v2; + getRPM = getRPM_DualWheel; if(configPage4.TrigEdge == 0) { primaryTriggerEdge = RISING; } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering) else { primaryTriggerEdge = FALLING; } diff --git a/speeduino/sensors.h b/speeduino/sensors.h index 6f9ff29b..665af418 100644 --- a/speeduino/sensors.h +++ b/speeduino/sensors.h @@ -52,6 +52,9 @@ unsigned long EMAPrunningValue; //As above but for EMAP unsigned int MAPcount; //Number of samples taken in the current MAP cycle uint32_t MAPcurRev; //Tracks which revolution we're sampling on bool auxIsEnabled; +byte TPSlast; /**< The previous TPS reading */ +unsigned long TPS_time; //The time the TPS sample was taken +unsigned long TPSlast_time; //The time the previous TPS sample was taken uint16_t MAPlast; /**< The previous MAP reading */ unsigned long MAP_time; //The time the MAP sample was taken unsigned long MAPlast_time; //The time the previous MAP sample was taken diff --git a/speeduino/sensors.ino b/speeduino/sensors.ino index fcc407af..3a81646a 100644 --- a/speeduino/sensors.ino +++ b/speeduino/sensors.ino @@ -399,7 +399,8 @@ static inline void readMAP(void) void readTPS(bool useFilter) { - currentStatus.TPSlast = currentStatus.TPS; + TPSlast = currentStatus.TPS; + TPSlast_time = TPS_time; #if defined(ANALOG_ISR) byte tempTPS = fastMap1023toX(AnChannel[pinTPS-A0], 255); //Get the current raw TPS ADC value and map it into a byte #else @@ -440,6 +441,7 @@ void readTPS(bool useFilter) else { currentStatus.CTPSActive = digitalRead(pinCTPS); } //Inverted mode (5v activates closed throttle position sensor) } else { currentStatus.CTPSActive = 0; } + TPS_time = micros(); } void readCLT(bool useFilter) diff --git a/speeduino/updates.ino b/speeduino/updates.ino index 4a658a76..d77791dc 100644 --- a/speeduino/updates.ino +++ b/speeduino/updates.ino @@ -491,7 +491,7 @@ void doUpdates(void) configPage10.TrigEdgeThrd = 0; //Old use as On/Off selection is removed, so change VVT mode to On/Off based on that - if(configPage6.tachoMode == 1) { configPage6.vvtMode = VVT_MODE_ONOFF; } + if(configPage6.unused_bit == 1) { configPage6.vvtMode = VVT_MODE_ONOFF; } //Closed loop VVT improvements. Set safety limits to max/min working values and filter to minimum. configPage10.vvtCLMinAng = 0; @@ -619,7 +619,6 @@ void doUpdates(void) } configPage9.hardRevMode = 1; //Set hard rev limiter to Fixed mode - configPage6.tachoMode = 0; //CAN broadcast introduced configPage2.canBMWCluster = 0; diff --git a/test/test_decoders/test_decoders.cpp b/test/test_decoders/test_decoders.cpp index b7459fd0..9c0cb1ce 100644 --- a/test/test_decoders/test_decoders.cpp +++ b/test/test_decoders/test_decoders.cpp @@ -1,6 +1,5 @@ #include -#include #include #include "missing_tooth/missing_tooth.h" diff --git a/test/test_fuel/test_corrections.cpp b/test/test_fuel/test_corrections.cpp index b0ab6eb0..08f0fa0d 100644 --- a/test/test_fuel/test_corrections.cpp +++ b/test/test_fuel/test_corrections.cpp @@ -8,7 +8,6 @@ void testCorrections() { test_corrections_WUE(); test_corrections_dfco(); - test_corrections_TAE(); //TPS based accel enrichment corrections /* RUN_TEST(test_corrections_cranking); //Not written yet RUN_TEST(test_corrections_ASE); //Not written yet @@ -141,7 +140,7 @@ void setup_DFCO_on() correctionDFCO(); dfcoTaper = 20; } -//********************************************************************************************************************** + void test_corrections_dfco_on(void) { //Test under ideal conditions that DFCO goes active @@ -186,11 +185,6 @@ void test_corrections_dfco() RUN_TEST(test_corrections_dfco_off_TPS); RUN_TEST(test_corrections_dfco_off_delay); } -//********************************************************************************************************************** -//Setup a basic TAE enrichment curve, threshold etc that are common to all tests. Specifica values maybe updated in each individual test -void test_corrections_TAE_setup() -{ - configPage2.aeMode = AE_MODE_TPS; //Set AE to TPS configPage4.taeValues[0] = 70; configPage4.taeValues[1] = 103; diff --git a/test/test_fuel/test_corrections.h b/test/test_fuel/test_corrections.h index d9ef1bb1..0f148915 100644 --- a/test/test_fuel/test_corrections.h +++ b/test/test_fuel/test_corrections.h @@ -9,5 +9,4 @@ void test_corrections_bat(void); void test_corrections_iatdensity(void); void test_corrections_baro(void); void test_corrections_launch(void); -void test_corrections_dfco(void); -void test_corrections_TAE(void); \ No newline at end of file +void test_corrections_dfco(void); \ No newline at end of file