diff --git a/reference/speeduino.ini b/reference/speeduino.ini index 89dd0a3a..c4b64cdc 100644 --- a/reference/speeduino.ini +++ b/reference/speeduino.ini @@ -130,6 +130,8 @@ #define trigger_ThirtySixMinus222 = 16 #define trigger_ThirtySixMinus21 = 17 #define trigger_420a = 18 + #define trigger_Webber = 19 + #define trigger_FordST170 = 20 [Constants] @@ -339,7 +341,8 @@ page = 1 fanWhenOff = bits, U08, 70, [0:0], "No", "Yes" fanWhenCranking = bits, U08, 70, [1:1], "No", "Yes" - unused_fan_bits = bits, U08, 70, [2:4] + useDwellMap = bits, U08, 70, [2:2], "No", "Yes" + unused_fan_bits = bits, U08, 70, [3:4] rtc_mode = bits, U08, 70, [5:6], "Off", "On-board", "INVALID", "INVALID" incorporateAFR = bits, U08, 70, [7:7], "No", "Yes" @@ -432,7 +435,7 @@ page = 4 TrigEdge = bits, U08, 5,[0:0], "RISING", "FALLING" TrigSpeed = bits, U08, 5,[1:1], "Crank Speed", "Cam Speed" IgInv = bits, U08, 5,[2:2], "Going Low", "Going High" - TrigPattern= bits, U08, 5,[3:7], "Missing Tooth", "Basic Distributor", "Dual Wheel", "GM 7X", "4G63 / Miata / 3000GT", "GM 24X", "Jeep 2000", "Audi 135", "Honda D17", "Miata 99-05", "Mazda AU", "Non-360 Dual", "Nissan 360", "Subaru 6/7", "Daihatsu +1", "Harley EVO", "36-2-2-2", "36-2-1", "DSM 420a", "Weber-Marelli", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID" + TrigPattern= bits, U08, 5,[3:7], "Missing Tooth", "Basic Distributor", "Dual Wheel", "GM 7X", "4G63 / Miata / 3000GT", "GM 24X", "Jeep 2000", "Audi 135", "Honda D17", "Miata 99-05", "Mazda AU", "Non-360 Dual", "Nissan 360", "Subaru 6/7", "Daihatsu +1", "Harley EVO", "36-2-2-2", "36-2-1", "DSM 420a", "Weber-Marelli", "Ford ST170", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID" TrigEdgeSec= bits, U08, 6,[0:0], "RISING", "FALLING" 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" @@ -1138,9 +1141,13 @@ page = 11 ;Water methanol inejction maps (Page 12) ;-------------------------------------------------- page = 12 - wmiTable = array, U08, 0,[8x8], "%", 1.0, 0.0, 0.0, 255.0, 0 - rpmBinsWMI = array, U08, 64,[ 8], "RPM", 100.0, 0.0, 100, 25500, 0 - mapBinsWMI = array, U08, 72,[ 8], "kPa", 2.0, 0.0, 0.0, 511.0, 0 + wmiTable = array, U08, 0,[8x8], "%", 1.0, 0.0, 0.0, 255.0, 0 + rpmBinsWMI = array, U08, 64,[ 8], "RPM", 100.0, 0.0, 100, 25500, 0 + mapBinsWMI = array, U08, 72,[ 8], "kPa", 2.0, 0.0, 0.0, 511.0, 0 + ;VVT2 map should be here in the middle + dwellTable = array, U08, 160,[4x4], "ms", 0.1, 0.0, 0.1, 8.0, 1 + rpmBinsDwell = array, U08, 176,[ 4], "RPM", 100.0, 0.0, 100, 25500, 0 + mapBinsDwell = array, U08, 180,[ 4], "kPa", 2.0, 0.0, 0.0, 511.0, 0 ;Page 13 is the programmable outputs page = 13 @@ -1573,6 +1580,7 @@ menuDialog = main subMenu = sparkTbl, "Spark Table", 2 subMenu = dwellSettings, "Dwell settings" subMenu = dwell_correction_curve, "Dwell Compensation" + subMenu = dwell_map, "Dwell Map", { useDwellMap } subMenu = iat_retard_curve, "IAT Retard" subMenu = clt_advance_curve, "Cold Advance" ;subMenu = knockSettings, "Knock Settings" @@ -2073,6 +2081,8 @@ menuDialog = main resetControlPin = "The Arduino pin used to control resets." 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." [UserDefined] @@ -2487,7 +2497,7 @@ menuDialog = main field = "Note: This is the number of revolutions that will be skipped during" field = "cranking before the injectors and coils are fired" field = "Trigger edge", TrigEdge { TrigPattern != 4 } ;4G63 uses both edges - field = "Secondary trigger edge", TrigEdgeSec, { (TrigPattern == 0 && TrigSpeed == 0) || TrigPattern == 2 || TrigPattern == 9 || TrigPattern == 12 || TrigPattern == 18 || TrigPattern == 19 } ;Missing tooth, dual wheel and Miata 9905, weber-marelli + field = "Secondary trigger edge", TrigEdgeSec, { (TrigPattern == 0 && TrigSpeed == 0) || TrigPattern == 2 || TrigPattern == 9 || TrigPattern == 12 || TrigPattern == 18 || TrigPattern == 19 || TrigPattern == 20 } ;Missing tooth, dual wheel and Miata 9905, weber-marelli, ST170 field = "Missing Tooth Secondary type" trigPatternSec, { (TrigPattern == 0&& TrigSpeed == 0) } field = "Trigger Filter", TrigFilter, { TrigPattern != 13 } field = "Re-sync every cycle", useResync, { TrigPattern == 2 || TrigPattern == 4 || TrigPattern == 7 || TrigPattern == 12 || TrigPattern == 9 || TrigPattern == 13 || TrigPattern == 18 || TrigPattern == 19 } ;Dual wheel, 4G63, Audi 135, Nissan 360, Miata 99-05, weber-marelli @@ -2515,7 +2525,8 @@ menuDialog = main dialog = dwellSettings, "Dwell Settings", 4 topicHelp = "https://wiki.speeduino.com/en/configuration/Dwell" field = " Cranking dwell", dwellcrank - field = " Running dwell", dwellrun + field = " Use dwell map", useDwellMap + field = " Running dwell", dwellrun, { useDwellMap == 0 } field = " Spark duration", sparkDur field = "" field = "#Note" @@ -4368,6 +4379,14 @@ cmdVSSratio6 = "E\x99\x06" gridOrient = 250, 0, 340 upDownLabel = "(RICHER)", "(LEANER)" + table = dwell_map, dwell_tblMap, "Dwell map", 4 + xBins = rpmBinsDwell, rpm + yBins = mapBinsDwell, map + zBins = dwellTable + xyLabels = "RPM", "Load: " + gridHeight = 3.0 + upDownLabel = "HIGHER", "LOWER" + ;------------------------------------------------------------------------------- diff --git a/speeduino/comms.ino b/speeduino/comms.ino index c3cb7e80..96aba1f0 100644 --- a/speeduino/comms.ino +++ b/speeduino/comms.ino @@ -1299,10 +1299,29 @@ void receiveValue(uint16_t valueOffset, byte newValue) { wmiTable.axisX[(valueOffset - 64)] = int(newValue) * TABLE_RPM_MULTIPLIER; } - else if (valueOffset < 80) //New value is on the Y (MAP) axis of the boost table + else if (valueOffset < 80) //New value is on the Y (MAP) axis of the wmi table { wmiTable.axisY[(7 - (valueOffset - 72))] = int(newValue) * TABLE_LOAD_MULTIPLIER; } + //End of wmi table + else if (valueOffset < 176) //New value is part of the dwell map + { + tempOffset = valueOffset - 160; + dwellTable.values[3 - (tempOffset / 4)][tempOffset % 4] = newValue; + } + else if (valueOffset < 180) //New value is on the X (RPM) axis of the dwell table + { + tempOffset = valueOffset - 176; + dwellTable.axisX[tempOffset] = int(newValue) * TABLE_RPM_MULTIPLIER; + } + else if (valueOffset < 184) //New value is on the Y (Load) axis of the dwell table + { + tempOffset = valueOffset - 180; + dwellTable.axisY[(3 - tempOffset)] = int(newValue) * TABLE_LOAD_MULTIPLIER; + } + //End of dwell table + wmiTable.cacheIsValid = false; //Invalid the tables cache to ensure a lookup of new values + dwellTable.cacheIsValid = false; //Invalid the tables cache to ensure a lookup of new values break; case progOutsPage: @@ -1446,11 +1465,17 @@ void sendPage() //Need to perform a translation of the values[MAP/TPS][RPM] into the MS expected format byte response[80]; //Bit hacky, but send 1 map at a time (Each map is 8x8, so 64 + 8 + 8) - //Boost table + //WMI table for (int x = 0; x < 64; x++) { response[x] = wmiTable.values[7 - (x / 8)][x % 8]; } for (int x = 64; x < 72; x++) { response[x] = byte(wmiTable.axisX[(x - 64)] / TABLE_RPM_MULTIPLIER); } for (int y = 72; y < 80; y++) { response[y] = byte(wmiTable.axisY[7 - (y - 72)] / TABLE_LOAD_MULTIPLIER); } Serial.write((byte *)&response, 80); + + //Dwell table + for (int x = 0; x < 16; x++) { response[x] = dwellTable.values[3 - (x / 4)][x % 4]; } + for (int x = 16; x < 20; x++) { response[x] = byte(dwellTable.axisX[(x - 16)] / TABLE_RPM_MULTIPLIER); } + for (int y = 20; y < 24; y++) { response[y] = byte(dwellTable.axisY[3 - (y - 20)] / TABLE_LOAD_MULTIPLIER); } + Serial.write((byte *)&response, 24); break; } @@ -1999,6 +2024,14 @@ byte getPageValue(byte page, uint16_t valueAddress) else if(valueAddress < 72) { returnValue = byte(wmiTable.axisX[(valueAddress - 64)] / TABLE_RPM_MULTIPLIER); } else if(valueAddress < 80) { returnValue = byte(wmiTable.axisY[7 - (valueAddress - 72)] / TABLE_LOAD_MULTIPLIER); } } + else if(valueAddress < 184) + { + tempAddress = valueAddress - 160; + //Dwell table + if(tempAddress < 16) { returnValue = dwellTable.values[3 - (tempAddress / 4)][tempAddress % 4]; } + else if(tempAddress < 20) { returnValue = byte(dwellTable.axisX[(tempAddress - 16)] / TABLE_RPM_MULTIPLIER); } + else if(tempAddress < 24) { returnValue = byte(dwellTable.axisY[3 - (tempAddress - 20)] / TABLE_LOAD_MULTIPLIER); } + } break; case progOutsPage: diff --git a/speeduino/decoders.h b/speeduino/decoders.h index b233a64d..1a5eab99 100644 --- a/speeduino/decoders.h +++ b/speeduino/decoders.h @@ -31,6 +31,7 @@ #define DECODER_36_2_1 17 #define DECODER_420A 18 #define DECODER_WEBER 19 +#define DECODER_ST170 20 static inline void addToothLogEntry(unsigned long, bool); void loggerPrimaryISR(); @@ -178,6 +179,13 @@ void triggerSetEndTeeth_420a(); void triggerPri_Webber(); void triggerSec_Webber(); +void triggerSetup_FordST170(); +void triggerSec_FordST170(); +uint16_t getRPM_FordST170(); +int getCrankAngle_FordST170(); +void triggerSetEndTeeth_FordST170(); + + extern void (*triggerHandler)(); //Pointer for the trigger function (Gets pointed to the relevant decoder) extern void (*triggerSecondaryHandler)(); //Pointer for the secondary trigger function (Gets pointed to the relevant decoder) extern uint16_t (*getRPM)(); //Pointer to the getRPM function (Gets pointed to the relevant decoder) diff --git a/speeduino/decoders.ino b/speeduino/decoders.ino index 5cf93be7..7091f9e9 100644 --- a/speeduino/decoders.ino +++ b/speeduino/decoders.ino @@ -3864,3 +3864,164 @@ void triggerSec_Webber() checkSyncToothCount = 1; //Reset tooth counter } //Trigger filter } + +/* +Name: Ford ST170 +Desc: A dedicated decoder for 01-04 Ford Focus ST170/SVT engine. +Note: Standard 36-1 trigger wheel running at crank speed and 8-3 trigger wheel running at cam speed +*/ +void triggerSetup_FordST170() +{ + //Set these as we are using the existing missing tooth primary decoder and these will never change. + configPage4.triggerTeeth = 36; + configPage4.triggerMissingTeeth = 1; + configPage4.TrigSpeed = CRANK_SPEED; + + triggerToothAngle = 360 / configPage4.triggerTeeth; //The number of degrees that passes from tooth to tooth + triggerActualTeeth = configPage4.triggerTeeth - configPage4.triggerMissingTeeth; //The number of physical teeth on the wheel. Doing this here saves us a calculation each time in the interrupt + 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 * 60 / MAX_RPM / 8 / 2; //Cam pattern is 8-3, so 2 nearest teeth are 90 deg crank angle apart. Cam can be advanced by 60 deg, so going from fully retarded to fully advanced closes the gap to 30 deg. Zetec cam pulleys aren't keyed from factory, so I substracted additional 10 deg to avoid filter to be too agressive. And there you have it 720/20=36. + + secondDerivEnabled = false; + decoderIsSequential = true; + checkSyncToothCount = (36) >> 1; //50% of the total teeth. + toothLastMinusOneToothTime = 0; + toothCurrentCount = 0; + secondaryToothCount = 0; + toothOneTime = 0; + toothOneMinusOneTime = 0; + MAX_STALL_TIME = (3333UL * triggerToothAngle * (1 + 1)); //Minimum 50rpm. (3333uS is the time per degree at 50rpm) +} + +void triggerSec_FordST170() +{ + curTime2 = micros(); + curGap2 = curTime2 - toothLastSecToothTime; + + //Safety check for initial startup + if( (toothLastSecToothTime == 0) ) + { + curGap2 = 0; + toothLastSecToothTime = curTime2; + } + + if ( curGap2 >= triggerSecFilterTime ) + { + targetGap2 = (3 * (toothLastSecToothTime - toothLastMinusOneSecToothTime)) >> 1; //If the time between the current tooth and the last is greater than 1.5x 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 + toothLastMinusOneSecToothTime = toothLastSecToothTime; + if ( (curGap2 >= targetGap2) || (secondaryToothCount == 5) ) + { + secondaryToothCount = 1; + revolutionOne = 1; //Sequential revolution reset + triggerSecFilterTime = 0; //This is used to prevent a condition where serious intermitent signals (Eg someone furiously plugging the sensor wire in and out) can leave the filter in an unrecoverable state + } + else + { + triggerSecFilterTime = curGap2 >> 2; //Set filter at 25% of the current speed. Filter can only be recalc'd for the regular teeth, not the missing one. + secondaryToothCount++; + } + + toothLastSecToothTime = curTime2; + + //Record the VVT Angle + //We use the first tooth after the long gap as our reference, this remains in the same engine + //cycle even when the VVT is at either end of its full swing. + if( (configPage6.vvtEnabled > 0) && (revolutionOne == 1) && (secondaryToothCount == 1) ) + { + int16_t curAngle; + curAngle = getCrankAngle(); + while(curAngle > 360) { curAngle -= 360; } + if( configPage6.vvtMode == VVT_MODE_CLOSED_LOOP ) + { + currentStatus.vvt1Angle = 360 - curAngle - configPage10.vvtCLMinAng; + } + } + } //Trigger filter +} + +uint16_t getRPM_FordST170() +{ + uint16_t tempRPM = 0; + if( currentStatus.RPM < currentStatus.crankRPM ) + { + if(toothCurrentCount != 1) + { + tempRPM = crankingGetRPM(36); + } + else { tempRPM = currentStatus.RPM; } //Can't do per tooth RPM if we're at tooth #1 as the missing tooth messes the calculation + } + else + { + tempRPM = stdGetRPM(360); + } + return tempRPM; +} + +int getCrankAngle_FordST170() +{ + //This is the current angle ATDC the engine is at. This is the last known position based on what tooth was last 'seen'. It is only accurate to the resolution of the trigger wheel (Eg 36-1 is 10 degrees) + unsigned long tempToothLastToothTime; + int tempToothCurrentCount; + bool tempRevolutionOne; + //Grab some variables that are used in the trigger code and assign them to temp variables. + noInterrupts(); + tempToothCurrentCount = toothCurrentCount; + tempRevolutionOne = revolutionOne; + tempToothLastToothTime = toothLastToothTime; + interrupts(); + + int crankAngle = ((tempToothCurrentCount - 1) * triggerToothAngle) + configPage4.triggerAngle; //Number of teeth that have passed since tooth 1, multiplied by the angle each tooth represents, plus the angle that tooth 1 is ATDC. This gives accuracy only to the nearest tooth. + + //Sequential check (simply sets whether we're on the first or 2nd revoltuion of the cycle) + if ( (tempRevolutionOne == true) && (configPage4.TrigSpeed == CRANK_SPEED) ) { crankAngle += 360; } + + lastCrankAngleCalc = micros(); + elapsedTime = (lastCrankAngleCalc - tempToothLastToothTime); + crankAngle += timeToAngle(elapsedTime, CRANKMATH_METHOD_INTERVAL_REV); + + if (crankAngle >= 720) { crankAngle -= 720; } + else if (crankAngle > CRANK_ANGLE_MAX) { crankAngle -= CRANK_ANGLE_MAX; } + if (crankAngle < 0) { crankAngle += CRANK_ANGLE_MAX; } + + return crankAngle; +} + +void triggerSetEndTeeth_FordST170() +{ + byte toothAdder = 0; + if( (configPage4.sparkMode == IGN_MODE_SEQUENTIAL) && (configPage4.TrigSpeed == CRANK_SPEED) ) { toothAdder = 36; } + + //Temp variables are used here to avoid potential issues if a trigger interrupt occurs part way through this function + + int16_t tempIgnition1EndTooth; + tempIgnition1EndTooth = ( (ignition1EndAngle - configPage4.triggerAngle) / (int16_t)(triggerToothAngle) ) - 1; + if(tempIgnition1EndTooth > (36 + toothAdder)) { tempIgnition1EndTooth -= (36 + toothAdder); } + if(tempIgnition1EndTooth <= 0) { tempIgnition1EndTooth += (36 + toothAdder); } + if((uint16_t)tempIgnition1EndTooth > (triggerActualTeeth + toothAdder)) { tempIgnition1EndTooth = (triggerActualTeeth + toothAdder); } + ignition1EndTooth = tempIgnition1EndTooth; + + int16_t tempIgnition2EndTooth; + tempIgnition2EndTooth = ( (ignition2EndAngle - configPage4.triggerAngle) / (int16_t)(triggerToothAngle) ) - 1; + if(tempIgnition2EndTooth > (36 + toothAdder)) { tempIgnition2EndTooth -= (36 + toothAdder); } + if(tempIgnition2EndTooth <= 0) { tempIgnition2EndTooth += (36 + toothAdder); } + if((uint16_t)tempIgnition2EndTooth > (triggerActualTeeth + toothAdder)) { tempIgnition2EndTooth = (triggerActualTeeth + toothAdder); } + ignition2EndTooth = tempIgnition2EndTooth; + + int16_t tempIgnition3EndTooth; + tempIgnition3EndTooth = ( (ignition3EndAngle - configPage4.triggerAngle) / (int16_t)(triggerToothAngle) ) - 1; + if(tempIgnition3EndTooth > (36 + toothAdder)) { tempIgnition3EndTooth -= (36 + toothAdder); } + if(tempIgnition3EndTooth <= 0) { tempIgnition3EndTooth += (36 + toothAdder); } + if((uint16_t)tempIgnition3EndTooth > (triggerActualTeeth + toothAdder)) { tempIgnition3EndTooth = (triggerActualTeeth + toothAdder); } + ignition3EndTooth = tempIgnition3EndTooth; + + int16_t tempIgnition4EndTooth; + tempIgnition4EndTooth = ( (ignition4EndAngle - configPage4.triggerAngle) / (int16_t)(triggerToothAngle) ) - 1; + if(tempIgnition4EndTooth > (36 + toothAdder)) { tempIgnition4EndTooth -= (36 + toothAdder); } + if(tempIgnition4EndTooth <= 0) { tempIgnition4EndTooth += (36 + toothAdder); } + if((uint16_t)tempIgnition4EndTooth > (triggerActualTeeth + toothAdder)) { tempIgnition4EndTooth = (triggerActualTeeth + toothAdder); } + ignition4EndTooth = tempIgnition4EndTooth; + // Removed ign channels >4 as an ST170 engine is a 4 cylinder + + lastToothCalcAdvance = currentStatus.advance; +} diff --git a/speeduino/globals.h b/speeduino/globals.h index ca798782..cd42d021 100644 --- a/speeduino/globals.h +++ b/speeduino/globals.h @@ -373,6 +373,7 @@ extern struct table3D trim1Table; //6x6 Fuel trim 1 map extern struct table3D trim2Table; //6x6 Fuel trim 2 map extern struct table3D trim3Table; //6x6 Fuel trim 3 map extern struct table3D trim4Table; //6x6 Fuel trim 4 map +extern struct table3D dwellTable; //4x4 Dwell map extern struct table2D taeTable; //4 bin TPS Acceleration Enrichment map (2D) extern struct table2D maeTable; extern struct table2D WUETable; //10 bin Warm Up Enrichment map (2D) @@ -746,7 +747,8 @@ struct config2 { byte fanWhenOff : 1; // Only run fan when engine is running byte fanWhenCranking : 1; //**< Setting whether the fan output will stay on when the engine is cranking */ - byte fanUnused : 3; + byte useDwellMap : 1; // Setting to change between fixed dwell value and dwell map + byte fanUnused : 2; byte rtc_mode : 2; byte incorporateAFR : 1; //Incorporate AFR byte asePct[4]; //Afterstart enrichment (%) diff --git a/speeduino/globals.ino b/speeduino/globals.ino index 54275df5..c744b8cc 100644 --- a/speeduino/globals.ino +++ b/speeduino/globals.ino @@ -18,6 +18,7 @@ struct table3D trim1Table; //6x6 Fuel trim 1 map struct table3D trim2Table; //6x6 Fuel trim 2 map struct table3D trim3Table; //6x6 Fuel trim 3 map struct table3D trim4Table; //6x6 Fuel trim 4 map +struct table3D dwellTable; //4x4 Dwell map struct table2D taeTable; //4 bin TPS Acceleration Enrichment map (2D) struct table2D maeTable; struct table2D WUETable; //10 bin Warm Up Enrichment map (2D) diff --git a/speeduino/init.ino b/speeduino/init.ino index 5b1125ba..4f757f6e 100644 --- a/speeduino/init.ino +++ b/speeduino/init.ino @@ -42,6 +42,7 @@ void initialiseAll() table3D_setSize(&trim2Table, 6); table3D_setSize(&trim3Table, 6); table3D_setSize(&trim4Table, 6); + table3D_setSize(&dwellTable, 4); #if defined(CORE_STM32) configPage9.intcan_available = 1; // device has internal canbus @@ -3028,6 +3029,25 @@ void initialiseTriggers() attachInterrupt(triggerInterrupt2, triggerSecondaryHandler, secondaryTriggerEdge); break; + case DECODER_ST170: + //Ford ST170 + triggerSetup_FordST170(); + triggerHandler = triggerPri_missingTooth; + triggerSecondaryHandler = triggerSec_FordST170; + decoderHasSecondary = true; + getRPM = getRPM_FordST170; + getCrankAngle = getCrankAngle_FordST170; + triggerSetEndTeeth = triggerSetEndTeeth_FordST170; + + if(configPage4.TrigEdge == 0) { primaryTriggerEdge = RISING; } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering) + else { primaryTriggerEdge = FALLING; } + if(configPage4.TrigEdgeSec == 0) { secondaryTriggerEdge = RISING; } + else { secondaryTriggerEdge = FALLING; } + + attachInterrupt(triggerInterrupt, triggerHandler, primaryTriggerEdge); + attachInterrupt(triggerInterrupt2, triggerSecondaryHandler, secondaryTriggerEdge); + + break; default: triggerHandler = triggerPri_missingTooth; diff --git a/speeduino/speeduino.ino b/speeduino/speeduino.ino index 51287ec0..e92d25c7 100644 --- a/speeduino/speeduino.ino +++ b/speeduino/speeduino.ino @@ -652,8 +652,20 @@ void loop() //Set dwell //Dwell is stored as ms * 10. ie Dwell of 4.3ms would be 43 in configPage4. This number therefore needs to be multiplied by 100 to get dwell in uS - if ( BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK) ) { currentStatus.dwell = (configPage4.dwellCrank * 100); } - else { currentStatus.dwell = (configPage4.dwellRun * 100); } + if ( BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK) ) { + currentStatus.dwell = (configPage4.dwellCrank * 100); //use cranking dwell + } + else + { + if ( configPage2.useDwellMap == true ) + { + currentStatus.dwell = (get3DTableValue(&dwellTable, currentStatus.MAP, currentStatus.RPM) * 100); //use running dwell from map + } + else + { + currentStatus.dwell = (configPage4.dwellRun * 100); //use fixed running dwell + } + } currentStatus.dwell = correctionsDwell(currentStatus.dwell); int dwellAngle = timeToAngle(currentStatus.dwell, CRANKMATH_METHOD_INTERVAL_REV); //Convert the dwell time to dwell angle based on the current engine speed diff --git a/speeduino/storage.h b/speeduino/storage.h index a442e482..0bbc23f7 100644 --- a/speeduino/storage.h +++ b/speeduino/storage.h @@ -159,7 +159,17 @@ Current layout of EEPROM data (Version 3) is as follows (All sizes are in bytes) #define EEPROM_CONFIG12_MAP 2387 #define EEPROM_CONFIG12_XBINS 2451 #define EEPROM_CONFIG12_YBINS 2459 -#define EEPROM_CONFIG12_END 2467 +#define EEPROM_CONFIG12_XSIZE2 2467 +//#define EEPROM_CONFIG12_YSIZE2 2468 +//#define EEPROM_CONFIG12_MAP2 2469 +//#define EEPROM_CONFIG12_XBINS2 2533 +//#define EEPROM_CONFIG12_YBINS2 2541 +#define EEPROM_CONFIG12_XSIZE3 2549 +#define EEPROM_CONFIG12_YSIZE3 2550 +#define EEPROM_CONFIG12_MAP3 2551 +#define EEPROM_CONFIG12_XBINS3 2567 +#define EEPROM_CONFIG12_YBINS3 2571 +#define EEPROM_CONFIG12_END 2575 #define EEPROM_CONFIG13_START 2580 #define EEPROM_CONFIG13_END 2708 #define EEPROM_CONFIG14_XSIZE 2708 diff --git a/speeduino/storage.ino b/speeduino/storage.ino index 37d14636..d06993b5 100644 --- a/speeduino/storage.ino +++ b/speeduino/storage.ino @@ -425,11 +425,14 @@ void writeConfig(byte tableNum) case wmiMapPage: /*--------------------------------------------------- - | WMI tables (See storage.h for data layout) - Page 12 - | 8x8 table itself + the 8 values along each of the axis + | WMI and Dwell tables (See storage.h for data layout) - Page 12 + | 8x8 WMI table itself + the 8 values along each of the axis + | 4x4 Dwell table itself + the 4 values along each of the axis -----------------------------------------------------*/ if(EEPROM.read(EEPROM_CONFIG12_XSIZE) != wmiTable.xSize) { EEPROM.write(EEPROM_CONFIG12_XSIZE,wmiTable.xSize); writeCounter++; } //Write the wmi Table RPM dimension size if(EEPROM.read(EEPROM_CONFIG12_YSIZE) != wmiTable.ySize) { EEPROM.write(EEPROM_CONFIG12_YSIZE,wmiTable.ySize); writeCounter++; } //Write the wmi Table MAP dimension size + if(EEPROM.read(EEPROM_CONFIG12_XSIZE3) != dwellTable.xSize) { EEPROM.write(EEPROM_CONFIG12_XSIZE3,dwellTable.xSize); writeCounter++; } //Write the Dwell Table RPM dimension size + if(EEPROM.read(EEPROM_CONFIG12_YSIZE3) != dwellTable.ySize) { EEPROM.write(EEPROM_CONFIG12_YSIZE3,dwellTable.ySize); writeCounter++; } //Write the Dwell Table MAP dimension size for(int x=EEPROM_CONFIG12_MAP; x EEPROM_MAX_WRITE_BLOCK) ) { break; } + offset = x - EEPROM_CONFIG12_MAP3; + if(EEPROM.read(x) != (dwellTable.values[3-(offset/4)][offset%4]) ) { EEPROM.write(x, dwellTable.values[3-(offset/4)][offset%4]); writeCounter++; } //Write the 4x4 map + } //RPM bins for(int x=EEPROM_CONFIG12_XBINS; x EEPROM_MAX_WRITE_BLOCK) ) { break; } + offset = x - EEPROM_CONFIG12_XBINS3; + if(EEPROM.read(x) != byte(dwellTable.axisX[offset]/TABLE_RPM_MULTIPLIER)) { EEPROM.write(x, byte(dwellTable.axisX[offset]/TABLE_RPM_MULTIPLIER)); writeCounter++; } //RPM bins are divided by 100 and converted to a byte + } //MAP bins - for(int x=EEPROM_CONFIG12_YBINS; x EEPROM_MAX_WRITE_BLOCK) ) { break; } offset = x - EEPROM_CONFIG12_YBINS; if(EEPROM.read(x) != byte(wmiTable.axisY[offset]/TABLE_LOAD_MULTIPLIER)) { EEPROM.write(x, byte(wmiTable.axisY[offset]/TABLE_LOAD_MULTIPLIER)); writeCounter++; } } + for(int x=EEPROM_CONFIG12_YBINS3; x EEPROM_MAX_WRITE_BLOCK) ) { break; } + offset = x - EEPROM_CONFIG12_YBINS3; + if(EEPROM.read(x) != byte(dwellTable.axisY[offset]/TABLE_LOAD_MULTIPLIER)) { EEPROM.write(x, byte(dwellTable.axisY[offset]/TABLE_LOAD_MULTIPLIER)); writeCounter++; } + } if(writeCounter > EEPROM_MAX_WRITE_BLOCK) { eepromWritesPending = true; } else { eepromWritesPending = false; } @@ -756,12 +777,18 @@ void loadConfig() } //********************************************************************************************************************************************************************************* - // WMI table load + // WMI and Dwell table load for(int x=EEPROM_CONFIG12_MAP; x=EEPROM_CONFIG13_START; x--) { EEPROM.update(x, EEPROM.read(x-112)); } + + configPage2.useDwellMap = 0; //Dwell map added, use old fixed value as default + writeAllConfig(); - EEPROM.write(EEPROM_DATA_VERSION, 16); + EEPROM.write(EEPROM_DATA_VERSION, 17); } //Final check is always for 255 and 0 (Brand new arduino)