diff --git a/decoders.h b/decoders.h index 7ff95ea5..cf89c74f 100644 --- a/decoders.h +++ b/decoders.h @@ -1,13 +1,15 @@ #include volatile unsigned long curTime; -volatile unsigned int curGap; +volatile unsigned long curGap; volatile unsigned long curTime2; -volatile unsigned int curGap2; -volatile unsigned int lastGap; -volatile unsigned int targetGap; +volatile unsigned long curGap2; +volatile unsigned long lastGap; +volatile unsigned long targetGap; volatile int toothCurrentCount = 0; //The current number of teeth (Onec sync has been achieved, this can never actually be 0 +volatile byte toothSystemCount = 0; //Used for decoders such as Audi 135 where not every tooth is used for calculating crank angle. This variable stores the actual number of teeth, not the number being used to calculate crank angle +volatile unsigned long toothSystemLastToothTime = 0; //As below, but used for decoders where not every tooth count is used for calculation volatile unsigned long toothLastToothTime = 0; //The time (micros()) that the last tooth was registered volatile unsigned long toothLastSecToothTime = 0; //The time (micros()) that the last tooth was registered on the secondary input volatile unsigned long toothLastMinusOneToothTime = 0; //The time (micros()) that the tooth before the last tooth was registered diff --git a/decoders.ino b/decoders.ino index f6edce5e..d99c8f39 100644 --- a/decoders.ino +++ b/decoders.ino @@ -417,9 +417,11 @@ void triggerPri_4G63() addToothLogEntry(curGap); //Whilst this is an uneven tooth pattern, if the specific angle between the last 2 teeth is specified, 1st deriv prediction can be used - if(toothCurrentCount == 1 || toothCurrentCount == 3) { triggerToothAngle = 70; } - else { triggerToothAngle = 110; } - + if(toothCurrentCount == 1 || toothCurrentCount == 3) { triggerToothAngle = 70; triggerFilterTime = curGap; } //Trigger filter is set to whatever time it took to do 70 degrees (Next trigger is 110 degrees away) + else { triggerToothAngle = 110; triggerFilterTime = (curGap * 3) >> 3; } //Trigger filter is set to (110*3)/8=41.25=41 degrees (Next trigger is 70 degrees away). + + curGap = curGap >> 1; + toothLastMinusOneToothTime = toothLastToothTime; toothLastToothTime = curTime; } @@ -432,6 +434,7 @@ void triggerSec_4G63() if(BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK) || !currentStatus.hasSync) { + triggerFilterTime = 1500; //Check the status of the crank trigger bool crank = digitalRead(pinTrigger); if(crank == HIGH) @@ -440,7 +443,7 @@ void triggerSec_4G63() toothCurrentCount = 4; //If the crank trigger is currently HIGH, it means we're on tooth #1 } } - else { triggerFilterTime = 1500; } //reset filter time (ugly) + //else { triggerFilterTime = 1500; } //reset filter time (ugly) return; } @@ -448,18 +451,21 @@ void triggerSec_4G63() int getRPM_4G63() { //During cranking, RPM is calculated 4 times per revolution, once for each rising/falling of the crank signal. - //Because these signals aren't even (Alternativing 110 and 70 degrees), this needs a special function + //Because these signals aren't even (Alternating 110 and 70 degrees), this needs a special function if(currentStatus.RPM < configPage2.crankRPM) { - noInterrupts(); - revolutionTime = (toothLastToothTime - toothLastMinusOneToothTime); //Note that trigger tooth angle changes between 70 and 110 depending on the last tooth that was seen - interrupts(); - revolutionTime = revolutionTime * 36; - return (triggerToothAngle * 60000000L) / revolutionTime; + int tempToothAngle; + noInterrupts(); + tempToothAngle = triggerToothAngle; + revolutionTime = (toothLastToothTime - toothLastMinusOneToothTime); //Note that trigger tooth angle changes between 70 and 110 depending on the last tooth that was seen + interrupts(); + revolutionTime = revolutionTime * 36; + return (tempToothAngle * 60000000L) / revolutionTime; } else { return stdGetRPM(); } } - int getCrankAngle_4G63(int timePerDegree) + +int getCrankAngle_4G63(int timePerDegree) { if(!currentStatus.hasSync) { return 0;} //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) @@ -473,11 +479,11 @@ int getRPM_4G63() int crankAngle = toothAngles[(tempToothCurrentCount - 1)] + configPage2.triggerAngle; //Perform a lookup of the fixed toothAngles array to find what the angle of the last tooth passed was. //Estimate the number of degrees travelled since the last tooth} + long elapsedTime = micros() - tempToothLastToothTime; if(elapsedTime < SHRT_MAX ) { crankAngle += div((int)elapsedTime, timePerDegree).quot; } //This option is much faster, but only available for smaller values of elapsedTime else { crankAngle += ldiv(elapsedTime, timePerDegree).quot; } - if (crankAngle >= 720) { crankAngle -= 720; } if (crankAngle > 360) { crankAngle -= 360; } if (crankAngle < 0) { crankAngle += 360; } @@ -669,3 +675,68 @@ int getCrankAngle_Jeep2000(int timePerDegree) return crankAngle; } +/* +Name: Audi 135 +Desc: 135 teeth on the crank and 1 tooth on the cam. +Note: This is very similar to the dual wheel decoder, however due to the 135 teeth not dividing evenly into 360, only every 3rd crank tooth is used in calculating the crank angle. This effectively makes it a 45 tooth dual wheel setup +*/ +void triggerSetup_Audi135() +{ + triggerToothAngle = 8; //135/3 = 45, 360/45 = 8 degrees every 3 teeth + toothCurrentCount = 255; //Default value + toothSystemCount = 0; + triggerFilterTime = (unsigned long)(1000000 / (MAX_RPM / 60 * 135UL)); //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 = (int)(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) + secondDerivEnabled = false; +} + +void triggerPri_Audi135() +{ + curTime = micros(); + curGap = curTime - toothSystemLastToothTime; + if ( curGap < triggerFilterTime ) { return; } //Debounce check. Pulses should never be less than triggerFilterTime, so if they are it means a false trigger. (A 36-1 wheel at 8000pm will have triggers approx. every 200uS) + toothSystemCount++; + toothSystemLastToothTime = curTime; + addToothLogEntry(curGap); + if ( toothSystemCount != 3 ) { return; } //We only proceed for every third tooth + toothSystemCount = 0; + toothCurrentCount++; //Increment the tooth counter + + if ( toothCurrentCount == 1 || toothCurrentCount > 45) + { + toothCurrentCount = 1; + toothOneMinusOneTime = toothOneTime; + toothOneTime = curTime; + startRevolutions++; //Counter + currentStatus.hasSync = true; + } + + toothLastMinusOneToothTime = toothLastToothTime; + toothLastToothTime = curTime; +} + +void triggerSec_Audi135() +{ + curTime2 = micros(); + curGap2 = curTime2 - toothLastSecToothTime; + if ( curGap2 < triggerSecFilterTime ) { return; } + toothLastSecToothTime = curTime2; + + if(!currentStatus.hasSync) + { + toothCurrentCount = 0; + toothSystemCount = 0; + currentStatus.hasSync = true; + } +} + +int getRPM_Audi135() +{ + return stdGetRPM(); +} + +int getCrankAngle_Audi135(int timePerDegree) +{ + return getCrankAngle_DualWheel(timePerDegree); +} + diff --git a/globals.h b/globals.h index 6f1b89ef..03b0d695 100644 --- a/globals.h +++ b/globals.h @@ -33,6 +33,9 @@ const int map_page_size = 288; #define BIT_SQUIRT_TOOTHLOG1READY 6 //Used to flag if tooth log 1 is ready #define BIT_SQUIRT_TOOTHLOG2READY 7 //Used to flag if tooth log 2 is ready (Log is not currently used) +#define VALID_MAP_MAX 1022 //The largest ADC value that is valid for the MAP sensor +#define VALID_MAP_MIN 2 //The smallest ADC value that is valid for the MAP sensor + #define TOOTH_LOG_SIZE 128 #define TOOTH_LOG_BUFFER 256 @@ -118,8 +121,8 @@ struct statuses { //This mostly covers off variables that are required for fuel struct config1 { - byte crankCold; //Cold cranking pulsewidth modifier. This is added to the fuel pulsewidth when cranking under a certain temp threshold (ms) - byte crankHot; //Warm cranking pulsewidth modifier. This is added to the fuel pulsewidth when cranking (ms) + byte unused1; //Cold cranking pulsewidth modifier. This is added to the fuel pulsewidth when cranking under a certain temp threshold (ms) + byte unused2; //Warm cranking pulsewidth modifier. This is added to the fuel pulsewidth when cranking (ms) byte asePct; //Afterstart enrichment (%) byte aseCount; //Afterstart enrichment cycles. This is the number of ignition cycles that the afterstart enrichment % lasts for byte wueValues[10]; //Warm up enrichment array (10 bytes) @@ -166,7 +169,7 @@ struct config1 { //config3 in ini byte engineType : 1; - byte egoType : 1; + byte egoType_old : 1; byte algorithm : 1; //"Speed Density", "Alpha-N" byte baroCorr : 1; byte injTiming : 2; @@ -180,7 +183,7 @@ struct config1 { byte tpsMax; byte mapMin; unsigned int mapMax; - byte unused49; + byte fpPrime; //Time (In seconds) that the fuel pump should be primed for on power up byte unused50; byte unused51; byte unused52; @@ -340,6 +343,11 @@ struct config4 { byte unused : 6; byte fanSP; // Cooling fan start temperature byte fanHyster; // Fan hysteresis + byte unused59; + byte unused60; + byte unused61; + byte unused62; + byte unused63; }; byte pinInjector1; //Output pin injector 1 diff --git a/math.h b/math.h index 8a8be524..8577a84b 100644 --- a/math.h +++ b/math.h @@ -22,7 +22,7 @@ Ref: http://www.hackersdelight.org/divcMore.pdf //Unsigned divide by 10 unsigned int divu10(unsigned int n) { - unsigned int q, r; + unsigned long q, r; q = (n >> 1) + (n >> 2); q = q + (q >> 4); q = q + (q >> 8); @@ -34,8 +34,8 @@ unsigned int divu10(unsigned int n) { } //Signed divide by 10 -int divs10(int n) { - int q, r; +int divs10(long n) { + long q, r; n = n + (n>>31 & 9); q = (n >> 1) + (n >> 2); q = q + (q >> 4); @@ -48,8 +48,8 @@ int divs10(int n) { } //Signed divide by 100 -int divs100(int n) { - int q, r; +int divs100(long n) { + long q, r; n = n + (n>>31 & 99); q = (n >> 1) + (n >> 3) + (n >> 6) - (n >> 10) + (n >> 12) + (n >> 13) - (n >> 16); diff --git a/reference/hardware/v0.3/v0.3.2_bom.xlsx b/reference/hardware/v0.3/v0.3.2_bom.xlsx index a963cf5e..68497984 100644 Binary files a/reference/hardware/v0.3/v0.3.2_bom.xlsx and b/reference/hardware/v0.3/v0.3.2_bom.xlsx differ diff --git a/reference/hardware/v0.4/Interface boards/48 Pin NA Miata/NA Miata 48 pin.fzz b/reference/hardware/v0.4/Interface boards/48 Pin NA Miata/NA Miata 48 pin.fzz index 0420c4ed..e03bb5f3 100644 Binary files a/reference/hardware/v0.4/Interface boards/48 Pin NA Miata/NA Miata 48 pin.fzz and b/reference/hardware/v0.4/Interface boards/48 Pin NA Miata/NA Miata 48 pin.fzz differ diff --git a/reference/hardware/v0.5/schematic v0.5.fzz b/reference/hardware/v0.5/schematic v0.5.fzz index 51dd1437..6a7ce454 100644 Binary files a/reference/hardware/v0.5/schematic v0.5.fzz and b/reference/hardware/v0.5/schematic v0.5.fzz differ diff --git a/reference/speeduino.ini b/reference/speeduino.ini index 6c3ac716..62d8b2fe 100644 --- a/reference/speeduino.ini +++ b/reference/speeduino.ini @@ -93,8 +93,8 @@ page = 1 ;Page 2 is all general settings (Previously part of page 1) ;-------------------------------------------------- page = 2 - crankCold = scalar, U08, 0, "ms", 0.1, 0.0, 0.0, 25.5, 1 - crankHot = scalar, U08, 1, "ms", 0.1, 0.0, 0.0, 25.5, 1 + unused2-1 = scalar, U08, 0, "ms", 0.1, 0.0, 0.0, 25.5, 1 + unused2-2 = scalar, U08, 1, "ms", 0.1, 0.0, 0.0, 25.5, 1 asePct = scalar, U08, 2, "%", 1.0, 0.0, 0.0, 95.0, 0 aseCount = scalar, U08, 3, "s", 1.0, 0.0, 0.0, 255, 0 wueBins = array, U08, 4, [ 10], "%", 1.0, 0.0, 0.0, 255, 0 @@ -140,7 +140,7 @@ page = 2 ; Config3 engineType = bits, U08, 38, [0:0], "Even fire", "Odd fire" - egoType1 = bits, U08, 38, [1:1], "Narrow band", "Wide band" + egoTypeOLD = bits, U08, 38, [1:1], "Narrow band", "Wide band" algorithm = bits, U08, 38, [2:2], "Speed Density", "Alpha-N" baroCorr = bits, U08, 38, [3:3], "Off", "On" injTiming = bits, U08, 38, [4:5], "Bank", "Semi-Sequential", "INVALID", "INVALID" @@ -154,21 +154,21 @@ page = 2 tpsMax = scalar, U08, 45, "ADC", 1.0, 0.0, 0.0, 255.0, 0 mapMin = scalar, U08, 46, "kpa", 1.0, 0.0, 0.0, 255.0, 0 mapMax = scalar, U16, 47, "kpa", 1.0, 0.0, 0.0, 25500, 0 - unused49 = scalar, U08, 49, "RPM", 100.0, 0.0, 100, 25500, 0 - unused50 = scalar, U08, 50, "RPM", 100.0, 0.0, 100, 25500, 0 - unused51 = scalar, U08, 51, "RPM", 100.0, 0.0, 100, 25500, 0 - unused52 = scalar, U08, 52, "RPM", 100.0, 0.0, 100, 25500, 0 - unused53 = scalar, U08, 53, "RPM", 100.0, 0.0, 100, 25500, 0 - unused54 = scalar, U08, 54, "RPM", 100.0, 0.0, 100, 25500, 0 - unused55 = scalar, U08, 55, "RPM", 100.0, 0.0, 100, 25500, 0 - unused56 = scalar, U08, 56, "RPM", 100.0, 0.0, 100, 25500, 0 - unused57 = scalar, U08, 57, "RPM", 100.0, 0.0, 100, 25500, 0 - unused58 = scalar, U08, 58, "RPM", 100.0, 0.0, 100, 25500, 0 - unused59 = scalar, U08, 59, "RPM", 100.0, 0.0, 100, 25500, 0 - unused60 = scalar, U08, 60, "RPM", 100.0, 0.0, 100, 25500, 0 - unused61 = scalar, U08, 61, "RPM", 100.0, 0.0, 100, 25500, 0 - unused62 = scalar, U08, 62, "RPM", 100.0, 0.0, 100, 25500, 0 - unused63 = scalar, U08, 63, "RPM", 100.0, 0.0, 100, 25500, 0 + fpPrime = scalar, U08, 49, "s", 1.0, 0.0, 0.0, 255.0, 0 + unused2-50 = scalar, U08, 50, "RPM", 100.0, 0.0, 100, 25500, 0 + unused2-51 = scalar, U08, 51, "RPM", 100.0, 0.0, 100, 25500, 0 + unused2-52 = scalar, U08, 52, "RPM", 100.0, 0.0, 100, 25500, 0 + unused2-53 = scalar, U08, 53, "RPM", 100.0, 0.0, 100, 25500, 0 + unused2-54 = scalar, U08, 54, "RPM", 100.0, 0.0, 100, 25500, 0 + unused2-55 = scalar, U08, 55, "RPM", 100.0, 0.0, 100, 25500, 0 + unused2-56 = scalar, U08, 56, "RPM", 100.0, 0.0, 100, 25500, 0 + unused2-57 = scalar, U08, 57, "RPM", 100.0, 0.0, 100, 25500, 0 + unused2-58 = scalar, U08, 58, "RPM", 100.0, 0.0, 100, 25500, 0 + unused2-59 = scalar, U08, 59, "RPM", 100.0, 0.0, 100, 25500, 0 + unused2-60 = scalar, U08, 60, "RPM", 100.0, 0.0, 100, 25500, 0 + unused2-61 = scalar, U08, 61, "RPM", 100.0, 0.0, 100, 25500, 0 + unused2-62 = scalar, U08, 62, "RPM", 100.0, 0.0, 100, 25500, 0 + unused2-63 = scalar, U08, 63, "RPM", 100.0, 0.0, 100, 25500, 0 ;-------------------------------------------------- ;Start Ignition table (Page 3) @@ -199,14 +199,14 @@ page = 4 TrigSpeed = bits, U08, 5[1:1], "Crank Speed", "Cam Speed" IgInv = bits, U08, 5[2:2], "Going Low", "Going High" oddfire = bits, U08, 5[3:3], "No", "Yes" - TrigPattern= bits, U08, 5[4:7], "Missing Tooth", "Basic Distributor", "Dual Wheel", "GM 7X", "4G63 / Miata", "GM 24X", "Jeep 2000", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID" + TrigPattern= bits, U08, 5[4:7], "Missing Tooth", "Basic Distributor", "Dual Wheel", "GM 7X", "4G63 / Miata", "GM 24X", "Jeep 2000", "Audi 135", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID" IdleAdv = scalar, U08, 6, "Deg", 0.352,-28.4, -10, 80, 0 IdleAdvTPS = scalar, U08, 7, "ADC", 1, 0, 0, 255, 0 IdleAdvRPM = scalar, U08, 8, "RPM", 100, 0, 0, 1200, 0 #if CELSIUS - IdleAdvCLT = scalar, U08, 9, "C", 0.555, -72, -40, 102, 1 + IdleAdvCLT = scalar, U08, 9, "C", 1, -40, -40, 102, 1 #else - IdleAdvCLT = scalar, U08, 9, "F", 1, -40, -40, 215, 0 + IdleAdvCLT = scalar, U08, 9, "F", 0.555, -8, -40, 215, 0 #endif IdleDelayTime = scalar, U08, 10, "sec", 1, 0, 0, 5, 0 StgCycles = scalar, U08, 11, "cycles", 1, 0, 0, 255, 0 @@ -240,22 +240,22 @@ page = 4 dwellLim = scalar, U08, 41, "ms", 1, 0, 0, 32, 0 dwellRates = array, U08, 42, [6], "%", 1.0, 0.0, 0.00, 255.0, 0 - unused48 = scalar, U08, 48, "RPM", 100.0, 0.0, 100, 25500, 0 - unused49 = scalar, U08, 49, "RPM", 100.0, 0.0, 100, 25500, 0 - unused50 = scalar, U08, 50, "RPM", 100.0, 0.0, 100, 25500, 0 - unused51 = scalar, U08, 51, "RPM", 100.0, 0.0, 100, 25500, 0 - unused52 = scalar, U08, 52, "RPM", 100.0, 0.0, 100, 25500, 0 - unused53 = scalar, U08, 53, "RPM", 100.0, 0.0, 100, 25500, 0 - unused54 = scalar, U08, 54, "RPM", 100.0, 0.0, 100, 25500, 0 - unused55 = scalar, U08, 55, "RPM", 100.0, 0.0, 100, 25500, 0 - unused56 = scalar, U08, 56, "RPM", 100.0, 0.0, 100, 25500, 0 - unused57 = scalar, U08, 57, "RPM", 100.0, 0.0, 100, 25500, 0 - unused58 = scalar, U08, 58, "RPM", 100.0, 0.0, 100, 25500, 0 - unused59 = scalar, U08, 59, "RPM", 100.0, 0.0, 100, 25500, 0 - unused60 = scalar, U08, 60, "RPM", 100.0, 0.0, 100, 25500, 0 - unused61 = scalar, U08, 61, "RPM", 100.0, 0.0, 100, 25500, 0 - unused62 = scalar, U08, 62, "RPM", 100.0, 0.0, 100, 25500, 0 - unused63 = scalar, U08, 63, "RPM", 100.0, 0.0, 100, 25500, 0 + unused4-48 = scalar, U08, 48, "RPM", 100.0, 0.0, 100, 25500, 0 + unused4-49 = scalar, U08, 49, "RPM", 100.0, 0.0, 100, 25500, 0 + unused4-50 = scalar, U08, 50, "RPM", 100.0, 0.0, 100, 25500, 0 + unused4-51 = scalar, U08, 51, "RPM", 100.0, 0.0, 100, 25500, 0 + unused4-52 = scalar, U08, 52, "RPM", 100.0, 0.0, 100, 25500, 0 + unused4-53 = scalar, U08, 53, "RPM", 100.0, 0.0, 100, 25500, 0 + unused4-54 = scalar, U08, 54, "RPM", 100.0, 0.0, 100, 25500, 0 + unused4-55 = scalar, U08, 55, "RPM", 100.0, 0.0, 100, 25500, 0 + unused4-56 = scalar, U08, 56, "RPM", 100.0, 0.0, 100, 25500, 0 + unused4-57 = scalar, U08, 57, "RPM", 100.0, 0.0, 100, 25500, 0 + unused4-58 = scalar, U08, 58, "RPM", 100.0, 0.0, 100, 25500, 0 + unused4-59 = scalar, U08, 59, "RPM", 100.0, 0.0, 100, 25500, 0 + unused4-60 = scalar, U08, 60, "RPM", 100.0, 0.0, 100, 25500, 0 + unused4-61 = scalar, U08, 61, "RPM", 100.0, 0.0, 100, 25500, 0 + unused4-62 = scalar, U08, 62, "RPM", 100.0, 0.0, 100, 25500, 0 + unused4-63 = scalar, U08, 63, "RPM", 100.0, 0.0, 100, 25500, 0 ;-------------------------------------------------- @@ -282,8 +282,8 @@ page = 6 egoType = bits , U08, 0, [2:3], "Disabled", "Narrow Band", "Wide Band", "INVALID" ; egoOption boostEnabled= bits, U08, 0, [4:4], "Off", "On" vvtEnabled = bits, U08, 0, [5:5], "Off", "On" -; vvtEnabled = bits, U08, 0, [5:6], "Off", "On/Off", "PWM","Centred PID" -; vvtChannels = bits, U08, 0, [7:7], "1", "2"; + unused = bits, U08, 0, [6:7], "Off", "On/Off", "PWM","Centred PID" + egoKP = scalar, U08, 1, "%", 1.0, 0.0, 0.0, 200.0, 0 ; * ( 1 byte) egoKI = scalar, U08, 2, "%", 1.0, 0.0, 0.0, 200.0, 0 ; * ( 1 byte) egoKD = scalar, U08, 3, "%", 1.0, 0.0, 0.0, 200.0, 0 ; * ( 1 byte) @@ -322,17 +322,17 @@ page = 6 lnchHardLim = scalar, U08, 51, "rpm", 100, 0.0, 100, 25500, 0 lnchFuelAdd = scalar, U08, 52, "%", 1.0, 0.0, 0.0, 80, 0 - unused53 = scalar, U08, 53, "RPM", 100.0, 0.0, 100, 25500, 0 - unused54 = scalar, U08, 54, "RPM", 100.0, 0.0, 100, 25500, 0 - unused55 = scalar, U08, 55, "RPM", 100.0, 0.0, 100, 25500, 0 - unused56 = scalar, U08, 56, "RPM", 100.0, 0.0, 100, 25500, 0 - unused57 = scalar, U08, 57, "RPM", 100.0, 0.0, 100, 25500, 0 - unused58 = scalar, U08, 58, "RPM", 100.0, 0.0, 100, 25500, 0 - unused59 = scalar, U08, 59, "RPM", 100.0, 0.0, 100, 25500, 0 - unused60 = scalar, U08, 60, "RPM", 100.0, 0.0, 100, 25500, 0 - unused61 = scalar, U08, 61, "RPM", 100.0, 0.0, 100, 25500, 0 - unused62 = scalar, U08, 62, "RPM", 100.0, 0.0, 100, 25500, 0 - unused63 = scalar, U08, 63, "RPM", 100.0, 0.0, 100, 25500, 0 + unused6-53 = scalar, U08, 53, "RPM", 100.0, 0.0, 100, 25500, 0 + unused6-54 = scalar, U08, 54, "RPM", 100.0, 0.0, 100, 25500, 0 + unused6-55 = scalar, U08, 55, "RPM", 100.0, 0.0, 100, 25500, 0 + unused6-56 = scalar, U08, 56, "RPM", 100.0, 0.0, 100, 25500, 0 + unused6-57 = scalar, U08, 57, "RPM", 100.0, 0.0, 100, 25500, 0 + unused6-58 = scalar, U08, 58, "RPM", 100.0, 0.0, 100, 25500, 0 + unused6-59 = scalar, U08, 59, "RPM", 100.0, 0.0, 100, 25500, 0 + unused6-60 = scalar, U08, 60, "RPM", 100.0, 0.0, 100, 25500, 0 + unused6-61 = scalar, U08, 61, "RPM", 100.0, 0.0, 100, 25500, 0 + unused6-62 = scalar, U08, 62, "RPM", 100.0, 0.0, 100, 25500, 0 + unused6-63 = scalar, U08, 63, "RPM", 100.0, 0.0, 100, 25500, 0 ;-------------------------------------------------- ;Start idle and fan controls (Page 7) @@ -348,12 +348,12 @@ page = 7 iacAlgorithm = bits , U08, 52, [0:2], "None", "On/Off", "PWM", "INVALID", "Stepper", "INVALID", "INVALID", "INVALID" iacStepTime = bits , U08, 52, [3:5], "1", "2", "3", "4", "5", "6" - unused52 = bits , U08, 52, [6:7], "One", "INVALID", "INVALID", "INVALID" + unused7-52 = bits , U08, 52, [6:7], "One", "INVALID", "INVALID", "INVALID" #if CELSIUS iacFastTemp = scalar, U08, 53, "C", 1.0, -40, -40, 215, 0 #else - iacFastTemp = scalar, U08, 53, "F", 1.0, -40, -40, 215, 0 + iacFastTemp = scalar, U08, 53, "F", 1.8, -4.44, -40, 215, 0 #endif iacStepHome = scalar, U08, 54, "Steps", 3, 0, 0, 765, 0 @@ -362,12 +362,12 @@ page = 7 ; Begin fan control vairables fanInv = bits, U08, 56, [0:0], "No", "Yes" fanEnable = bits, U08, 56, [1:1], "No", "Yes" - unused55a = bits, U08, 56, [2:2], "No", "Yes" - unused55b = bits, U08, 56, [3:3], "No", "Yes" - unused55c = bits, U08, 56, [4:4], "No", "Yes" - unused55d = bits, U08, 56, [5:5], "No", "Yes" - unused55e = bits, U08, 56, [6:6], "No", "Yes" - unused55f = bits, U08, 56, [7:7], "No", "Yes" + unused7-55a = bits, U08, 56, [2:2], "No", "Yes" + unused7-55b = bits, U08, 56, [3:3], "No", "Yes" + unused7-55c = bits, U08, 56, [4:4], "No", "Yes" + unused7-55d = bits, U08, 56, [5:5], "No", "Yes" + unused7-55e = bits, U08, 56, [6:6], "No", "Yes" + unused7-55f = bits, U08, 56, [7:7], "No", "Yes" #if CELSIUS fanSP = scalar, U08, 57, "°C", 1.0, -40, -40, 215.0, 0 fanHyster = scalar, U08, 58, "°C", 1.0, -40, -40, 215.0, 0 @@ -375,11 +375,11 @@ page = 7 fanSP = scalar, U08, 57, "°F", 1.0, -40, -40, 215.0, 0 fanHyster = scalar, U08, 58, "°F", 1.0, -40, -40, 215.0, 0 #endif - unused59 = scalar, U08, 59, "RPM", 100.0, 0.0, 100, 25500, 0 - unused60 = scalar, U08, 60, "RPM", 100.0, 0.0, 100, 25500, 0 - unused61 = scalar, U08, 61, "RPM", 100.0, 0.0, 100, 25500, 0 - unused62 = scalar, U08, 62, "RPM", 100.0, 0.0, 100, 25500, 0 - unused63 = scalar, U08, 63, "RPM", 100.0, 0.0, 100, 25500, 0 + unused7-59 = scalar, U08, 59, "RPM", 100.0, 0.0, 100, 25500, 0 + unused7-60 = scalar, U08, 60, "RPM", 100.0, 0.0, 100, 25500, 0 + unused7-61 = scalar, U08, 61, "RPM", 100.0, 0.0, 100, 25500, 0 + unused7-62 = scalar, U08, 62, "RPM", 100.0, 0.0, 100, 25500, 0 + unused7-63 = scalar, U08, 63, "RPM", 100.0, 0.0, 100, 25500, 0 ;-------------------------------------------------- ;Boost and vvt maps (Page 8) @@ -422,6 +422,7 @@ page = 8 defaultValue = dutyLim, 100 defaultValue = mapMin, 10 defaultValue = mapMax, 260 + defaultValue = fpPrime, 3 [Menu] @@ -648,25 +649,13 @@ page = 8 dialog = crankPW, "Cranking Pulsewidths (ms)" - #if CELSIUS field = "Cranking RPM (Max)", crankRPM field = "Flood Clear level", tpsflood field = "" + field = "Fuel pump prime duration", fpPrime field = "Priming Pulsewidth", primePulse - field = "Pulsewidth at -40°C", crankCold - field = "Pulsewidth at 77°C", crankHot field = "" field = "Cranking Enrichment %", crankingPct - #else - field = "Cranking RPM (Max)", crankRPM - field = "Flood Clear level", tpsflood - field = "" - field = "Priming Pulsewidth", primePulse - field = "Pulsewidth at -40°F", crankCold - field = "Pulsewidth at 170°F", crankHot - field = "" - field = "Cranking Enrichment %", crankingPct - #endif dialog = aseSettings, "Afterstart Enrichment" field = "Enrichment %", asePct @@ -1128,8 +1117,8 @@ page = 8 iatRaw = scalar, U08, 5, "°C", 1.000, 0.000 coolantRaw = scalar, U08, 6, "°C", 1.000, 0.000 #else - iatRaw = scalar, U08, 5, "°F", 1.000, 0.000 - coolantRaw = scalar, U08, 6, "°F", 1.000, 0.000 + iatRaw = scalar, U08, 5, "°F", 1.800, 32.000 + coolantRaw = scalar, U08, 6, "°F", 1.800, 32.000 #endif tpsADC = scalar, U08, 7, "ADC", 1.000, 0.000 batteryVoltage = scalar, U08, 8, "V", 0.100, 0.000 diff --git a/reference/wiki/decoders/4g63_trace.png b/reference/wiki/decoders/4g63_trace.png index 424b779c..d96113ca 100644 Binary files a/reference/wiki/decoders/4g63_trace.png and b/reference/wiki/decoders/4g63_trace.png differ diff --git a/reference/wiki/v0_3_2_board_annotated.jpg b/reference/wiki/v0_3_2_board_annotated.jpg new file mode 100644 index 00000000..2935074d Binary files /dev/null and b/reference/wiki/v0_3_2_board_annotated.jpg differ diff --git a/reference/wiki/v0_3_2_proto_annotated.jpg b/reference/wiki/v0_3_2_proto_annotated.jpg new file mode 100644 index 00000000..a422c655 Binary files /dev/null and b/reference/wiki/v0_3_2_proto_annotated.jpg differ diff --git a/speeduino.ino b/speeduino.ino index fe16aee5..b7a8a898 100644 --- a/speeduino.ino +++ b/speeduino.ino @@ -81,6 +81,12 @@ byte cltCalibrationTable[CALIBRATION_TABLE_SIZE]; byte iatCalibrationTable[CALIBRATION_TABLE_SIZE]; byte o2CalibrationTable[CALIBRATION_TABLE_SIZE]; +//These variables are used for tracking the number of running sensors values that appear to be errors. Once a threshold is reached, the sensor reading will go to default value and assume the sensor is faulty +byte mapErrorCount = 0; +byte iatErrorCount = 0; +byte cltErrorCount = 0; + + unsigned long counter; unsigned long currentLoopTime; //The time the current loop started (uS) unsigned long previousLoopTime; //The time the previous loop started (uS) @@ -122,6 +128,7 @@ void (*ign4EndFunction)(); int timePerDegree; byte degreesPerLoop; //The number of crank degrees that pass for each mainloop of the program +volatile bool fpPrimed = false; //Tracks whether or not the fuel pump priming has been completed yet void setup() { @@ -340,6 +347,17 @@ void setup() else { attachInterrupt(triggerInterrupt, trigger, FALLING); } // Primary trigger connects to attachInterrupt(triggerInterrupt2, triggerSec_Jeep2000, CHANGE); break; + + case 7: + triggerSetup_Audi135(); + trigger = triggerPri_Audi135; + getRPM = getRPM_Audi135; + getCrankAngle = getCrankAngle_Audi135; + + if(configPage2.TrigEdge == 0) { attachInterrupt(triggerInterrupt, trigger, RISING); } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering) + else { attachInterrupt(triggerInterrupt, trigger, FALLING); } + attachInterrupt(triggerInterrupt2, triggerSec_Audi135, RISING); + break; default: trigger = triggerPri_missingTooth; @@ -526,6 +544,9 @@ void setup() break; } + //Begin priming the fuel pump. This is turned off in the low resolution, 1s interrupt in timers.ino + digitalWrite(pinFuelPump, HIGH); + fuelPumpOn = true; //Perform the priming pulses. Set these to run at an arbitrary time in the future (100us). The prime pulse value is in ms*10, so need to multiple by 100 to get to uS setFuelSchedule1(openInjector1and4, 100, (unsigned long)(configPage1.primePulse * 100), closeInjector1and4); setFuelSchedule2(openInjector2and3, 100, (unsigned long)(configPage1.primePulse * 100), closeInjector2and3); @@ -569,10 +590,11 @@ void loop() currentStatus.runSecs = 0; //Reset the counter for number of seconds running. secCounter = 0; //Reset our seconds counter. startRevolutions = 0; + MAPcurRev = 0; currentStatus.rpmDOT = 0; ignitionOn = false; fuelOn = false; - digitalWrite(pinFuelPump, LOW); //Turn off the fuel pump + if (fpPrimed) { digitalWrite(pinFuelPump, LOW); } //Turn off the fuel pump, but only if the priming is complete fuelPumpOn = false; } @@ -586,11 +608,17 @@ void loop() //----------------------------------------------------------------------------------------------------- //MAP Sampling system + int tempReading; switch(configPage1.mapSample) { case 0: //Instantaneous MAP readings - currentStatus.mapADC = analogRead(pinMAP); + tempReading = analogRead(pinMAP); + + //Error checking + if(tempReading >= VALID_MAP_MAX || tempReading <= VALID_MAP_MIN) { mapErrorCount += 1; } + else { currentStatus.mapADC = tempReading; mapErrorCount = 0; } + currentStatus.MAP = map(currentStatus.mapADC, 0, 1023, configPage1.mapMin, configPage1.mapMax); //Get the current MAP value break; @@ -598,8 +626,15 @@ void loop() //Average of a cycle if( (MAPcurRev == startRevolutions) || (MAPcurRev == startRevolutions+1) ) //2 revolutions are looked at for 4 stroke. 2 stroke not currently catered for. { - MAPrunningValue = MAPrunningValue + analogRead(pinMAP); //Add the current reading onto the total - MAPcount++; + tempReading = analogRead(pinMAP); + + //Error check + if(tempReading < VALID_MAP_MAX && tempReading > VALID_MAP_MIN) + { + MAPrunningValue = MAPrunningValue + tempReading; //Add the current reading onto the total + MAPcount++; + } + else { mapErrorCount += 1; } } else { @@ -616,9 +651,14 @@ void loop() //Minimum reading in a cycle if( (MAPcurRev == startRevolutions) || (MAPcurRev == startRevolutions+1) ) //2 revolutions are looked at for 4 stroke. 2 stroke not currently catered for. { - int tempValue = analogRead(pinMAP); - if( tempValue < MAPrunningValue) { MAPrunningValue = tempValue; } //Check whether the current reading is lower than the running minimum - MAPcount++; + tempReading = analogRead(pinMAP); + + //Error check + if(tempReading < VALID_MAP_MAX && tempReading > VALID_MAP_MIN) + { + if( tempReading < MAPrunningValue) { MAPrunningValue = tempReading; } //Check whether the current reading is lower than the running minimum + } + else { mapErrorCount += 1; } } else { @@ -731,10 +771,10 @@ 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 //We use a 1st Deriv accleration prediction, but only when there is an even spacing between primary sensor teeth //Any decoder that has uneven spacing has its triggerToothAngle set to 0 - if(secondDerivEnabled && toothHistoryIndex >= 3 && currentStatus.RPM < 2000 ) //toothHistoryIndex must be greater than or equal to 3 as we need the last 3 entries. Currently this mode only runs below 3000 rpm + if(secondDerivEnabled && toothHistoryIndex >= 3 && currentStatus.RPM < 2000) //toothHistoryIndex must be greater than or equal to 3 as we need the last 3 entries. Currently this mode only runs below 3000 rpm { //Only recalculate deltaV if the tooth has changed since last time (DeltaV stays the same until the next tooth) - if (deltaToothCount != toothCurrentCount) + //if (deltaToothCount != toothCurrentCount) { deltaToothCount = toothCurrentCount; int angle1, angle2; //These represent the crank angles that are travelled for the last 2 pulses @@ -895,7 +935,7 @@ void loop() //Determine the current crank angle int crankAngle = getCrankAngle(timePerDegree); - if (fuelOn) + if (fuelOn && currentStatus.PW > 0) { if (injector1StartAngle > crankAngle) { @@ -990,9 +1030,9 @@ void loop() //if ((ignition1StartAngle > crankAngle) == 0) //if ((ignition1StartAngle < crankAngle)) { - long ignition1StartTime; + unsigned long ignition1StartTime = 0; if(ignition1StartAngle > crankAngle) { ignition1StartTime = ((unsigned long)(ignition1StartAngle - crankAngle) * (unsigned long)timePerDegree); } - else if (ignition1StartAngle < crankAngle) { ignition1StartTime = ((long)(360 - crankAngle + ignition1StartAngle) * (long)timePerDegree); } + //else if (ignition1StartAngle < crankAngle) { ignition1StartTime = ((unsigned long)(360 - crankAngle + ignition1StartAngle) * (unsigned long)timePerDegree); } else { ignition1StartTime = 0; } if(ignition1StartTime > 0) { @@ -1008,44 +1048,62 @@ void loop() if( tempCrankAngle < 0) { tempCrankAngle += 360; } tempStartAngle = ignition2StartAngle - channel2IgnDegrees; if ( tempStartAngle < 0) { tempStartAngle += 360; } - if ( (tempStartAngle > tempCrankAngle) && ign2LastRev != startRevolutions) + //if ( (tempStartAngle > tempCrankAngle) && ign2LastRev != startRevolutions) //if ( ign2LastRev != startRevolutions ) { - unsigned long ignition2StartTime; + long ignition2StartTime = 0; if(tempStartAngle > tempCrankAngle) { ignition2StartTime = ((unsigned long)(tempStartAngle - tempCrankAngle) * (unsigned long)timePerDegree); } - else { ignition2StartTime = ((unsigned long)(360 - tempCrankAngle + tempStartAngle) * (unsigned long)timePerDegree); } + //else if (tempStartAngle < tempCrankAngle) { ignition2StartTime = ((long)(360 - tempCrankAngle + tempStartAngle) * (long)timePerDegree); } + else { ignition2StartTime = 0; } + if(ignition2StartTime > 0) { setIgnitionSchedule2(ign2StartFunction, - ((unsigned long)(tempStartAngle - tempCrankAngle) * (unsigned long)timePerDegree), + ignition2StartTime, currentStatus.dwell, ign2EndFunction ); + } } tempCrankAngle = crankAngle - channel3IgnDegrees; if( tempCrankAngle < 0) { tempCrankAngle += 360; } tempStartAngle = ignition3StartAngle - channel3IgnDegrees; - if ( tempStartAngle < 0) { tempStartAngle += 360; } - if (tempStartAngle > tempCrankAngle) + //if ( tempStartAngle < 0) { tempStartAngle += 360; } + //if (tempStartAngle > tempCrankAngle) { + long ignition3StartTime = 0; + if(tempStartAngle > tempCrankAngle) { ignition3StartTime = ((unsigned long)(tempStartAngle - tempCrankAngle) * (unsigned long)timePerDegree); } + //else if (tempStartAngle < tempCrankAngle) { ignition4StartTime = ((long)(360 - tempCrankAngle + tempStartAngle) * (long)timePerDegree); } + else { ignition3StartTime = 0; } + + if(ignition3StartTime > 0) { setIgnitionSchedule3(ign3StartFunction, - ((unsigned long)(tempStartAngle - tempCrankAngle) * (unsigned long)timePerDegree), + ignition3StartTime, currentStatus.dwell, ign3EndFunction ); + } } tempCrankAngle = crankAngle - channel4IgnDegrees; if( tempCrankAngle < 0) { tempCrankAngle += 360; } tempStartAngle = ignition4StartAngle - channel4IgnDegrees; - if ( tempStartAngle < 0) { tempStartAngle += 360; } - if (tempStartAngle > tempCrankAngle) + //if ( tempStartAngle < 0) { tempStartAngle += 360; } + //if (tempStartAngle > tempCrankAngle) { + + long ignition4StartTime = 0; + if(tempStartAngle > tempCrankAngle) { ignition4StartTime = ((unsigned long)(tempStartAngle - tempCrankAngle) * (unsigned long)timePerDegree); } + //else if (tempStartAngle < tempCrankAngle) { ignition4StartTime = ((long)(360 - tempCrankAngle + tempStartAngle) * (long)timePerDegree); } + else { ignition4StartTime = 0; } + + if(ignition4StartTime > 0) { setIgnitionSchedule4(ign4StartFunction, - ((unsigned long)(tempStartAngle - tempCrankAngle) * (unsigned long)timePerDegree), + ignition4StartTime, currentStatus.dwell, ign4EndFunction ); + } } } diff --git a/timers.ino b/timers.ino index dec407be..b8ee535e 100644 --- a/timers.ino +++ b/timers.ino @@ -82,6 +82,16 @@ ISR(TIMER2_OVF_vect, ISR_NOBLOCK) { fanControl(); // Fucntion to turn the cooling fan on/off } + + //Check whether fuel pump priming is complete + if(!fpPrimed) + { + if(currentStatus.secl >= configPage1.fpPrime) + { + fpPrimed = true; //Mark the priming as being completed + if(currentStatus.RPM == 0) { digitalWrite(pinFuelPump, LOW); fuelPumpOn = false; } //If we reach here then the priming is complete, however only turn off the fuel pump if the engine isn't running + } + } } //Reset Timer2 to trigger in another ~1ms diff --git a/utils.ino b/utils.ino index fdd782f0..f4f4b501 100644 --- a/utils.ino +++ b/utils.ino @@ -301,6 +301,8 @@ unsigned int PW(int REQ_FUEL, byte VE, byte MAP, int corrections, int injOpen, b //intermediate = (intermediate * iMAP) >> 7; intermediate = (intermediate * iCorrections) >> 7; //intermediate = (intermediate * iTPS) >> 7; + if(intermediate == 0) { return 0; } //If the pulsewidth is 0, we return here before the opening time gets added + intermediate += injOpen; //Add the injector opening time if ( intermediate > 65535) { intermediate = 65535; //Make sure this won't overflow when we convert to uInt. This means the maximum pulsewidth possible is 65.535mS