Merge branch 'master' into ADC-interrupt

This commit is contained in:
Josh Stewart 2016-11-10 07:48:47 +11:00
commit 7ca41a7355
8 changed files with 167 additions and 38 deletions

View File

@ -62,12 +62,12 @@ void command()
break;
case 'S': // send code version
Serial.print("Speeduino 2016.10-dev");
Serial.print("Speeduino 2016.10");
currentStatus.secl = 0; //This is required in TS3 due to its stricter timings
break;
case 'Q': // send code version
Serial.print("speeduino 201610-dev");
Serial.print("speeduino 201610");
break;
case 'V': // send VE table and constants in binary

View File

@ -49,6 +49,7 @@ int triggerToothAngle; //The number of crank degrees that elapse per tooth
unsigned long revolutionTime; //The time in uS that one revolution would take at current speed (The time tooth 1 was last seen, minus the time it was seen prior to that)
bool secondDerivEnabled; //The use of the 2nd derivative calculation is limited to certain decoders. This is set to either true or false in each decoders setup routine
bool decoderIsSequential; //Whether or not the decoder supports sequential operation
byte checkSyncToothCount; //How many teeth must've been seen on this revolution before we try to confirm sync (Useful for missing tooth type decoders)
int toothAngles[24]; //An array for storing fixed tooth angles. Currently sized at 24 for the GM 24X decoder, but may grow later if there are other decoders that use this style

View File

@ -91,6 +91,7 @@ void triggerSetup_missingTooth()
triggerFilterTime = (int)(1000000 / (MAX_RPM / 60 * configPage2.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
secondDerivEnabled = false;
decoderIsSequential = false;
checkSyncToothCount = (configPage2.triggerTeeth) >> 1; //50% of the total teeth.
MAX_STALL_TIME = (3333UL * triggerToothAngle * (configPage2.triggerMissingTeeth + 1)); //Minimum 50rpm. (3333uS is the time per degree at 50rpm)
}
@ -105,27 +106,30 @@ void triggerPri_missingTooth()
toothCurrentCount++; //Increment the tooth counter
addToothLogEntry(curGap);
//Begin the missing tooth detection
//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
if(configPage2.triggerMissingTeeth == 1) { targetGap = (3 * (toothLastToothTime - toothLastMinusOneToothTime)) >> 1; } //Multiply by 1.5 (Checks for a gap 1.5x greater than the last one) (Uses bitshift to multiply by 3 then divide by 2. Much faster than multiplying by 1.5)
else { targetGap = ((toothLastToothTime - toothLastMinusOneToothTime)) * 2; } //Multiply by 2 (Checks for a gap 2x greater than the last one)
if ( curGap > targetGap || toothCurrentCount > triggerActualTeeth)
{
if(toothCurrentCount < (triggerActualTeeth) && currentStatus.hasSync) { currentStatus.hasSync = false; return; } //This occurs when we're at tooth #1, but haven't seen all the other teeth. This indicates a signal issue so we flag lost sync so this will attempt to resync on the next revolution.
toothCurrentCount = 1;
revolutionOne = !revolutionOne; //Flip sequential revolution tracker
toothOneMinusOneTime = toothOneTime;
toothOneTime = curTime;
currentStatus.hasSync = true;
startRevolutions++; //Counter
triggerFilterTime = 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
//if(toothCurrentCount > checkSyncToothCount || !currentStatus.hasSync)
{
//Filter can only be recalc'd for the regular teeth, not the missing one.
setFilter(curGap);
//Begin the missing tooth detection
//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
if(configPage2.triggerMissingTeeth == 1) { targetGap = (3 * (toothLastToothTime - toothLastMinusOneToothTime)) >> 1; } //Multiply by 1.5 (Checks for a gap 1.5x greater than the last one) (Uses bitshift to multiply by 3 then divide by 2. Much faster than multiplying by 1.5)
else { targetGap = ((toothLastToothTime - toothLastMinusOneToothTime)) * 2; } //Multiply by 2 (Checks for a gap 2x greater than the last one)
if ( curGap > targetGap || toothCurrentCount > triggerActualTeeth)
{
if(toothCurrentCount < (triggerActualTeeth) && currentStatus.hasSync) { currentStatus.hasSync = false; return; } //This occurs when we're at tooth #1, but haven't seen all the other teeth. This indicates a signal issue so we flag lost sync so this will attempt to resync on the next revolution.
toothCurrentCount = 1;
revolutionOne = !revolutionOne; //Flip sequential revolution tracker
toothOneMinusOneTime = toothOneTime;
toothOneTime = curTime;
currentStatus.hasSync = true;
startRevolutions++; //Counter
triggerFilterTime = 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
{
//Filter can only be recalc'd for the regular teeth, not the missing one.
setFilter(curGap);
}
}
toothLastMinusOneToothTime = toothLastToothTime;
@ -134,7 +138,8 @@ void triggerPri_missingTooth()
void triggerSec_missingTooth()
{
if(!currentStatus.hasSync) { revolutionOne = 0; } //Sequential revolution reset
//TODO: This should really have filtering enabled on the secondary input.
revolutionOne = 1;
}
int getRPM_missingTooth()
@ -147,10 +152,12 @@ int getCrankAngle_missingTooth(int timePerDegree)
//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;
tempToothLastToothTime = toothLastToothTime;
tempRevolutionOne = revolutionOne;
interrupts();
int crankAngle = (tempToothCurrentCount - 1) * triggerToothAngle + configPage2.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.
@ -160,7 +167,7 @@ int getCrankAngle_missingTooth(int timePerDegree)
else { crankAngle += ldiv(elapsedTime, timePerDegree).quot; }
//Sequential check (simply sets whether we're on the first or 2nd revoltuion of the cycle)
if (revolutionOne) { crankAngle += 360; }
if (tempRevolutionOne) { crankAngle += 360; }
if (crankAngle >= 720) { crankAngle -= 720; }
else if (crankAngle > CRANK_ANGLE_MAX) { crankAngle -= CRANK_ANGLE_MAX; }
@ -230,7 +237,7 @@ void triggerSec_DualWheel()
currentStatus.hasSync = true;
}
if(!currentStatus.hasSync) { revolutionOne = 0; } //Sequential revolution reset
revolutionOne = 1; //Sequential revolution reset
}
int getRPM_DualWheel()
@ -245,10 +252,12 @@ int getCrankAngle_DualWheel(int timePerDegree)
//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;
tempToothLastToothTime = toothLastToothTime;
tempRevolutionOne = revolutionOne;
interrupts();
//Handle case where the secondary tooth was the last one seen
@ -261,7 +270,7 @@ int getCrankAngle_DualWheel(int timePerDegree)
else { crankAngle += ldiv(elapsedTime, timePerDegree).quot; }
//Sequential check (simply sets whether we're on the first or 2nd revoltuion of the cycle)
if (revolutionOne) { crankAngle += 360; }
if (tempRevolutionOne) { crankAngle += 360; }
if (crankAngle >= 720) { crankAngle -= 720; }
if (crankAngle > CRANK_ANGLE_MAX) { crankAngle -= CRANK_ANGLE_MAX; }

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<msq xmlns="http://www.msefi.com/:msq">
<bibliography author="TunerStudio MS(Beta) 3.0.10.04 - EFI Analytics, Inc." tuneComment="" writeDate="Fri Sep 30 22:35:03 AEST 2016"/>
<versionInfo fileFormat="5.0" firmwareInfo="Speeduino+2016.09" nPages="8" signature="speeduino 201609"/>
<bibliography author="TunerStudio MS 3.0.12 - EFI Analytics, Inc." tuneComment="" writeDate="Wed Nov 09 12:59:17 AEDT 2016"/>
<versionInfo fileFormat="5.0" firmwareInfo="Speeduino+2016.10" nPages="9" signature="speeduino 201610"/>
<page>
<pcVariable name="tsCanId">"0"</pcVariable>
</page>
@ -99,6 +99,11 @@
<constant name="alternate">"Alternating"</constant>
<constant name="multiplyMAP">"No"</constant>
<constant name="includeAFR">"No"</constant>
<constant name="unused2-26d">"No"</constant>
<constant name="unused2-26e">"No"</constant>
<constant name="unused2-26f">"No"</constant>
<constant name="unused2-26g">"No"</constant>
<constant name="unused2-26h">"No"</constant>
<constant digits="1" name="injOpen" units="ms">1.0</constant>
<constant digits="0" name="inj1Ang" units="deg">355.0</constant>
<constant digits="0" name="inj2Ang" units="deg">355.0</constant>
@ -115,11 +120,13 @@
<constant name="flexEnabled">"Off"</constant>
<constant name="algorithm">"Speed Density"</constant>
<constant name="baroCorr">"Off"</constant>
<constant name="injLayout">"Bank"</constant>
<constant name="injLayout">"Paired"</constant>
<constant name="canEnable">"Disable"</constant>
<constant name="unused2-38h">"No"</constant>
<constant digits="1" name="primePulse" units="ms">4.0</constant>
<constant digits="0" name="dutyLim" units="%">85.0</constant>
<constant digits="0" name="unused41" units="RPM">4200.0</constant>
<constant digits="3" name="egoSwitch" units="v">0.0</constant>
<constant digits="0" name="unused42" units="RPM">0.0</constant>
<constant digits="0" name="taeColdM" units="%">0.0</constant>
<constant digits="0" name="tpsMin" units="ADC">26.0</constant>
<constant digits="0" name="tpsMax" units="ADC">230.0</constant>
@ -127,9 +134,9 @@
<constant digits="0" name="mapMax" units="kpa">260.0</constant>
<constant digits="0" name="fpPrime" units="s">3.0</constant>
<constant digits="1" name="stoich" units=":1">14.7</constant>
<constant digits="0" name="oddfire2">0.0</constant>
<constant digits="0" name="oddfire3">0.0</constant>
<constant digits="0" name="oddfire4">0.0</constant>
<constant digits="0" name="oddfire2" units="deg">0.0</constant>
<constant digits="0" name="oddfire3" units="deg">0.0</constant>
<constant digits="0" name="oddfire4" units="deg">0.0</constant>
<constant digits="0" name="unused2-57" units="RPM">0.0</constant>
<constant digits="0" name="unused2-58" units="RPM">0.0</constant>
<constant digits="0" name="unused2-59" units="RPM">0.0</constant>
@ -204,6 +211,8 @@
<constant name="IgInv">"Going Low"</constant>
<constant name="oddfire">"Yes"</constant>
<constant name="TrigPattern">"Missing Tooth"</constant>
<constant digits="0" name="unused4-6" units="Deg">79.7632</constant>
<constant digits="0" name="unused4-7" units="ADC">255.0</constant>
<constant digits="0" name="IdleAdvRPM" units="RPM">3200.0</constant>
<constant digits="1" name="IdleAdvCLT" units="C">-21.0</constant>
<constant digits="0" name="IdleDelayTime" units="sec">38.0</constant>
@ -412,7 +421,12 @@
<constant digits="0" name="boostKI" units="%">0.0</constant>
<constant digits="0" name="boostKD" units="%">0.0</constant>
<constant name="lnchPullRes">"Float"</constant>
<constant name="unused6-60">"ONE"</constant>
<constant name="fuelTrimEnabled">"No"</constant>
<constant name="unused6-60d">"ONE"</constant>
<constant name="unused6-60e">"ONE"</constant>
<constant name="unused6-60f">"ONE"</constant>
<constant name="unused6-60g">"ONE"</constant>
<constant name="unused6-60h">"ONE"</constant>
<constant digits="0" name="unused6-61" units="RPM">4500.0</constant>
<constant digits="0" name="unused6-62" units="RPM">3000.0</constant>
<constant digits="0" name="unused6-63" units="RPM">6000.0</constant>
@ -570,10 +584,108 @@
100.0
</constant>
</page>
<page number="8" size="192">
<constant cols="6" digits="0" name="fuelTrim1Table" rows="6" units="%">
0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0
</constant>
<constant cols="1" digits="0" name="fuelTrim1rpmBins" rows="6" units="RPM">
700.0
1500.0
3000.0
4100.0
5500.0
7000.0
</constant>
<constant cols="1" digits="0" name="fuelTrim1loadBins" rows="6" units="kPa">
35.0
50.0
65.0
80.0
100.0
120.0
</constant>
<constant cols="6" digits="0" name="fuelTrim2Table" rows="6" units="%">
0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0
</constant>
<constant cols="1" digits="0" name="fuelTrim2rpmBins" rows="6" units="RPM">
700.0
1500.0
3000.0
4100.0
5500.0
7000.0
</constant>
<constant cols="1" digits="0" name="fuelTrim2loadBins" rows="6" units="kPa">
35.0
50.0
65.0
80.0
100.0
120.0
</constant>
<constant cols="6" digits="0" name="fuelTrim3Table" rows="6" units="%">
0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0
</constant>
<constant cols="1" digits="0" name="fuelTrim3rpmBins" rows="6" units="RPM">
700.0
1500.0
3000.0
4100.0
5500.0
7000.0
</constant>
<constant cols="1" digits="0" name="fuelTrim3loadBins" rows="6" units="kPa">
35.0
50.0
65.0
80.0
100.0
120.0
</constant>
<constant cols="6" digits="0" name="fuelTrim4Table" rows="6" units="%">
0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0
</constant>
<constant cols="1" digits="0" name="fuelTrim4rpmBins" rows="6" units="RPM">
700.0
1500.0
3000.0
4100.0
5500.0
7000.0
</constant>
<constant cols="1" digits="0" name="fuelTrim4loadBins" rows="6" units="kPa">
35.0
50.0
65.0
80.0
100.0
120.0
</constant>
</page>
<settings Comment="These setting are only used if this msq is opened without a project.">
<setting name="SPEED_DENSITY" value="SPEED_DENSITY"/>
<setting name="CAN_COMMANDS_OFF" value="CAN_COMMANDS_OFF"/>
<setting name="CELSIUS" value="CELSIUS"/>
</settings>
<userComments Comment="These are user comments that can be related to a particular setting or dialog."/>
</msq>
</msq>

View File

@ -6,7 +6,7 @@
queryCommand = "Q"
;signature = 20
signature = "speeduino 201610-dev"
signature = "speeduino 201610"
versionInfo = "S" ; Put this in the title bar.

View File

@ -328,6 +328,7 @@ void setup()
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_missingTooth, RISING);
break;
case 1:
@ -1065,6 +1066,7 @@ void loop()
int PWdivTimerPerDegree = div(currentStatus.PW1, timePerDegree).quot; //How many crank degrees the calculated PW will take at the current speed
injector1StartAngle = configPage1.inj1Ang - ( PWdivTimerPerDegree ); //This is a little primitive, but is based on the idea that all fuel needs to be delivered before the inlet valve opens. See http://www.extraefi.co.uk/sequential_fuel.html for more detail
if(injector1StartAngle < 0) {injector1StartAngle += CRANK_ANGLE_MAX_INJ;}
//Repeat the above for each cylinder
switch (configPage1.nCylinders)
{
@ -1247,7 +1249,7 @@ void loop()
/*-----------------------------------------------------------------------------------------
| A Note on tempCrankAngle and tempStartAngle:
| The use of tempCrankAngle/tempStartAngle is described below. It is then used in the same way for channels 2, 3 and 4 on both injectors and ignition
| Essentially, these 2 variables are used to realign the current crank and and the desired start angle around 0 degrees for the given cylinder/output
| Essentially, these 2 variables are used to realign the current crank angle and the desired start angle around 0 degrees for the given cylinder/output
| Eg: If cylinder 2 TDC is 180 degrees after cylinder 1 (Eg a standard 4 cylidner engine), then tempCrankAngle is 180* less than the current crank angle and
| tempStartAngle is the desired open time less 180*. Thus the cylinder is being treated relative to its own TDC, regardless of its offset
|
@ -1341,7 +1343,7 @@ void loop()
if (crankAngle > CRANK_ANGLE_MAX_IGN ) { crankAngle -= 360; }
//fixedCrankingOverride is used to extend the dwell during cranking so that the decoder can trigger the spark upon seeing a certain tooth. Currently only available on the basic distributor and 4g63 decoders.
if ( configPage2.ignCranklock && BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK)) { fixedCrankingOverride = currentStatus.dwell; }
if ( configPage2.ignCranklock && BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK)) { fixedCrankingOverride = currentStatus.dwell * 2; }
else { fixedCrankingOverride = 0; }
//Perform an initial check to see if the ignition is turned on (Ignition only turns on after a preset number of cranking revolutions and:

View File

@ -315,6 +315,7 @@ int get3DTableValue(struct table3D *fromTable, int Y, int X)
else
//If it's not caught by one of the above scenarios, give up and just run the loop
{
for (byte y = fromTable->ySize-1; y >= 0; y--)
{
//Checks the case where the Y value is exactly what was requested
@ -355,6 +356,9 @@ int get3DTableValue(struct table3D *fromTable, int Y, int X)
int B = fromTable->values[yMin][xMax];
int C = fromTable->values[yMax][xMin];
int D = fromTable->values[yMax][xMax];
//Check that all values aren't just the same (This regularly happens with things like the fuel trim maps)
if(A == B && A == C && A == D) { return A; }
//Create some normalised position values
//These are essentially percentages (between 0 and 1) of where the desired value falls between the nearest bins on each axis

View File

@ -45,6 +45,7 @@ void oneMSInterval() //Most ARM chips can simply call a function
//Increment Loop Counters
loop250ms++;
loopSec++;
//Overdwell check
targetOverdwellTime = micros() - (1000 * configPage2.dwellLimit); //Set a target time in the past that all coil charging must have begun after. If the coil charge began before this time, it's been running too long