Add initial Daihatsu +1 decoder (also 3 cylinder sequential ignition)

This commit is contained in:
Josh Stewart 2017-06-26 17:34:10 +10:00
parent 6f14959c5c
commit 652624b288
3 changed files with 202 additions and 41 deletions

View File

@ -272,7 +272,7 @@ page = 4
TrigSpeed = bits, U08, 5,[1:1], "Crank Speed", "Cam Speed" TrigSpeed = bits, U08, 5,[1:1], "Crank Speed", "Cam Speed"
IgInv = bits, U08, 5,[2:2], "Going Low", "Going High" IgInv = bits, U08, 5,[2:2], "Going Low", "Going High"
oddfire = bits, U08, 5,[3:3], "No", "Yes" oddfire = bits, U08, 5,[3:3], "No", "Yes"
TrigPattern= bits, U08, 5,[4: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", "INVALID", "INVALID" TrigPattern= bits, U08, 5,[4: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", "INVALID"
TrigEdgeSec= bits, U08, 6,[0:0], "Leading", "Trailing" TrigEdgeSec= bits, U08, 6,[0:0], "Leading", "Trailing"
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", "54", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID" 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", "54", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
useResync = bits, U08, 6,[7:7], "No", "Yes" useResync = bits, U08, 6,[7:7], "No", "Yes"

View File

@ -42,7 +42,9 @@ static inline void addToothLogEntry(unsigned long toothTime)
/* /*
As nearly all the decoders use a common method of determining RPM (The time the last full revolution took) As nearly all the decoders use a common method of determining RPM (The time the last full revolution took)
A common function is simpler A common function is simpler
degreesOver is the number of crank degrees between tooth #1s. Some patterns have a tooth #1 every crank rev, others are every cam rev.
*/ */
//static inline uint16_t stdGetRPM(uin16_t degreesOver)
static inline uint16_t stdGetRPM() static inline uint16_t stdGetRPM()
{ {
uint16_t tempRPM = 0; uint16_t tempRPM = 0;
@ -55,6 +57,7 @@ static inline uint16_t stdGetRPM()
noInterrupts(); noInterrupts();
revolutionTime = (toothOneTime - toothOneMinusOneTime); //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) revolutionTime = (toothOneTime - toothOneMinusOneTime); //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)
interrupts(); interrupts();
//if(degreesOver == 720) { revolutionTime / 2; }
tempRPM = (US_IN_MINUTE / revolutionTime); //Calc RPM based on last full revolution time (Faster as /) tempRPM = (US_IN_MINUTE / revolutionTime); //Calc RPM based on last full revolution time (Faster as /)
if(tempRPM >= MAX_RPM) { tempRPM = currentStatus.RPM; } //Sanity check if(tempRPM >= MAX_RPM) { tempRPM = currentStatus.RPM; } //Sanity check
} }
@ -1806,3 +1809,162 @@ int getCrankAngle_Subaru67(int timePerDegree)
return crankAngle; return crankAngle;
} }
/* -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Name: Daihatsu +1 trigger for 3 and 4 cylinder engines
Desc: Tooth equal to the number of cylinders are evenly spaced on the cam. No position sensing (Distributor is retained) so crank angle is a made up figure based purely on the first teeth to be seen
Note: This is a very simple decoder. See http://www.megamanual.com/ms2/GM_7pinHEI.htm
*/
void triggerSetup_Daihatsu()
{
triggerActualTeeth = configPage1.nCylinders + 1;
triggerToothAngle = 720 / triggerActualTeeth; //The number of degrees that passes from tooth to tooth
triggerFilterTime = 60000000L / MAX_RPM / configPage1.nCylinders; // Minimum time required between teeth
triggerFilterTime = triggerFilterTime / 2; //Safety margin
secondDerivEnabled = false;
decoderIsSequential = false;
MAX_STALL_TIME = (1851UL * triggerToothAngle)*4;//Minimum 90rpm. (1851uS is the time per degree at 90rpm). This uses 90rpm rather than 50rpm due to the potentially very high stall time on a 4 cylinder if we wait that long.
if(configPage1.nCylinders == 3)
{
toothAngles[0] = 0; //tooth #1
toothAngles[1] = 30; //tooth #2 (Extra tooth)
toothAngles[2] = 240; //tooth #3
toothAngles[3] = 480; //tooth #4
}
else
{
//Should be 4 cylinders here
toothAngles[0] = 0; //tooth #1
toothAngles[1] = 30; //tooth #2 (Extra tooth)
toothAngles[2] = 180; //tooth #3
toothAngles[3] = 360; //tooth #4
toothAngles[4] = 540; //tooth #5
}
}
void triggerPri_Daihatsu()
{
curTime = micros();
curGap = curTime - toothLastToothTime;
//if ( curGap >= triggerFilterTime )
{
toothSystemCount++;
if (currentStatus.hasSync == true)
{
if( (toothCurrentCount == triggerActualTeeth) ) //Check if we're back to the beginning of a revolution
{
toothCurrentCount = 1; //Reset the counter
toothOneMinusOneTime = toothOneTime;
toothOneTime = curTime;
currentStatus.hasSync = true;
currentStatus.startRevolutions++; //Counter
//Need to set a special filter time for the next tooth
triggerFilterTime = 20; //Fix this later
}
else
{
toothCurrentCount++; //Increment the tooth counter
setFilter(curGap); //Recalc the new filter value
}
//addToothLogEntry(curGap);
if ( configPage2.ignCranklock && BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK) )
{
//This locks the cranking timing to 0 degrees BTDC (All the triggers allow for)
if(toothCurrentCount == 1) { endCoil1Charge(); }
else if(toothCurrentCount == 2) { endCoil2Charge(); }
else if(toothCurrentCount == 3) { endCoil3Charge(); }
else if(toothCurrentCount == 4) { endCoil4Charge(); }
}
}
else //NO SYNC
{
//
if(toothSystemCount >= 3) //Need to have seen at least 3 teeth to determine SYNC
{
unsigned long targetTime;
//We need to try and find the extra tooth (#2) which is located 30 degrees after tooth #1
//Aim for tooth times less than about 60 degrees
if(configPage1.nCylinders == 3)
{
targetTime = (toothLastToothTime - toothLastMinusOneToothTime) >> 2; //Teeth are 240 degrees apart for 3 cylinder. 240/3 = 60
}
else
{
targetTime = ((toothLastToothTime - toothLastMinusOneToothTime) * 3) >> 4; //Teeth are 180 degrees apart for 4 cylinder. (180*3)/8 = 67
}
if(curGap < targetTime)
{
//Means we're on the extra tooth here
toothCurrentCount = 2; //Reset the counter
currentStatus.hasSync = true;
triggerFilterTime = targetTime; //Lazy, but it works
}
}
}
toothLastMinusOneToothTime = toothLastToothTime;
toothLastToothTime = curTime;
} //Trigger filter
}
void triggerSec_Daihatsu() { return; } //Not required (Should never be called in the first place)
uint16_t getRPM_Daihatsu()
{
uint16_t tempRPM;
if( currentStatus.RPM < (unsigned int)(configPage2.crankRPM * 100) && false)
{
//Cn't use standard cranking RPM functin due to extra tooth
uint16_t tempRPM = 0;
if( currentStatus.hasSync == true )
{
byte multiplier = 1;
if(toothCurrentCount == 2) { tempRPM = currentStatus.RPM; }
else if (toothCurrentCount == 3) { tempRPM = currentStatus.RPM; }
else
{
noInterrupts();
revolutionTime = (toothLastToothTime - toothLastMinusOneToothTime) * (triggerActualTeeth-1);
interrupts();
tempRPM = (US_IN_MINUTE / revolutionTime);
if(tempRPM >= MAX_RPM) { tempRPM = currentStatus.RPM; } //Sanity check
} //is tooth #2
}
else { tempRPM = 0; } //No sync
}
else
{ tempRPM = stdGetRPM() << 1; } //Multiply RPM by 2 due to tracking over 720 degrees now rather than 360
return tempRPM;
}
int getCrankAngle_Daihatsu(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;
int crankAngle;
//Grab some variables that are used in the trigger code and assign them to temp variables.
noInterrupts();
tempToothCurrentCount = toothCurrentCount;
tempToothLastToothTime = toothLastToothTime;
interrupts();
crankAngle = toothAngles[tempToothCurrentCount-1] + configPage2.triggerAngle; //Crank angle of the last tooth seen
//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 > CRANK_ANGLE_MAX) { crankAngle -= CRANK_ANGLE_MAX; }
if (crankAngle < 0) { crankAngle += CRANK_ANGLE_MAX; }
return crankAngle;
}

View File

@ -86,8 +86,6 @@ unsigned long previousLoopTime; //The time the previous loop started (uS)
int CRANK_ANGLE_MAX = 720; int CRANK_ANGLE_MAX = 720;
int CRANK_ANGLE_MAX_IGN = 360, CRANK_ANGLE_MAX_INJ = 360; // The number of crank degrees that the system track over. 360 for wasted / timed batch and 720 for sequential int CRANK_ANGLE_MAX_IGN = 360, CRANK_ANGLE_MAX_INJ = 360; // The number of crank degrees that the system track over. 360 for wasted / timed batch and 720 for sequential
//bool useSequentialFuel; // Whether sequential fueling is to be used (1 squirt per cycle)
//bool useSequentialIgnition; // Whether sequential ignition is used (1 spark per cycle)
static byte coilHIGH = HIGH; static byte coilHIGH = HIGH;
static byte coilLOW = LOW; static byte coilLOW = LOW;
@ -129,6 +127,7 @@ void (*ign5EndFunction)();
int timePerDegree; int timePerDegree;
byte degreesPerLoop; //The number of crank degrees that pass for each mainloop of the program 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 volatile bool fpPrimed = false; //Tracks whether or not the fuel pump priming has been completed yet
bool initialisationComplete = false; //Tracks whether the setup() functino has run completely
void setup() void setup()
{ {
@ -504,6 +503,17 @@ void setup()
attachInterrupt(triggerInterrupt2, triggerSec_Subaru67, FALLING); attachInterrupt(triggerInterrupt2, triggerSec_Subaru67, FALLING);
break; break;
case 14:
triggerSetup_Daihatsu();
trigger = triggerPri_Daihatsu;
getRPM = getRPM_Daihatsu;
getCrankAngle = getCrankAngle_Daihatsu;
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); }
//No secondary input required for this pattern
break;
default: default:
trigger = triggerPri_missingTooth; trigger = triggerPri_missingTooth;
getRPM = getRPM_missingTooth; getRPM = getRPM_missingTooth;
@ -560,8 +570,18 @@ void setup()
if (configPage1.engineType == EVEN_FIRE ) if (configPage1.engineType == EVEN_FIRE )
{ {
channel2IgnDegrees = 120; if(configPage2.sparkMode == IGN_MODE_SEQUENTIAL)
channel3IgnDegrees = 240; {
channel2IgnDegrees = 240;
channel3IgnDegrees = 480;
CRANK_ANGLE_MAX_IGN = 720;
}
else
{
channel2IgnDegrees = 120;
channel3IgnDegrees = 240;
}
} }
else else
{ {
@ -573,8 +593,8 @@ void setup()
if(configPage1.injLayout == INJ_SEMISEQUENTIAL || configPage1.injLayout == INJ_PAIRED) if(configPage1.injLayout == INJ_SEMISEQUENTIAL || configPage1.injLayout == INJ_PAIRED)
{ {
channel1InjDegrees = 0; channel1InjDegrees = 0;
channel2InjDegrees = channel2IgnDegrees; channel2InjDegrees = 120;
channel3InjDegrees = channel3IgnDegrees; channel3InjDegrees = 240;
} }
else if (configPage1.injLayout == INJ_SEQUENTIAL) else if (configPage1.injLayout == INJ_SEQUENTIAL)
{ {
@ -681,19 +701,13 @@ void setup()
channel5InjEnabled = true; channel5InjEnabled = true;
break; break;
case 6: case 6:
channel1IgnDegrees = channel1InjDegrees = 0; channel1IgnDegrees = 0;
channel2IgnDegrees = channel2InjDegrees = 120; channel1InjDegrees = 0;
channel3IgnDegrees = channel3InjDegrees = 240; channel2IgnDegrees = 120;
channel2InjDegrees = 120;
channel3IgnDegrees = 240;
channel3InjDegrees = 240;
//For alternatiing injection, the squirt occurs at different times for each channel
/*
if(configPage1.injLayout == INJ_SEMISEQUENTIAL || configPage1.injLayout == INJ_SEQUENTIAL || configPage1.injLayout == INJ_PAIRED) //No full sequential for more than 4 cylinders
{
channel1InjDegrees = 0;
channel2InjDegrees = 120;
channel3InjDegrees = 240;
}
*/
if (!configPage1.injTiming) { channel1InjDegrees = channel2InjDegrees = channel3InjDegrees = 0; } //For simultaneous, all squirts happen at the same time if (!configPage1.injTiming) { channel1InjDegrees = channel2InjDegrees = channel3InjDegrees = 0; } //For simultaneous, all squirts happen at the same time
configPage1.injLayout = 0; //This is a failsafe. We can never run semi-sequential with more than 4 cylinders configPage1.injLayout = 0; //This is a failsafe. We can never run semi-sequential with more than 4 cylinders
@ -708,16 +722,6 @@ void setup()
channel3IgnDegrees = channel3InjDegrees = 180; channel3IgnDegrees = channel3InjDegrees = 180;
channel4IgnDegrees = channel4InjDegrees = 270; channel4IgnDegrees = channel4InjDegrees = 270;
//For alternatiing injection, the squirt occurs at different times for each channel
/*
if(configPage1.injLayout == INJ_SEMISEQUENTIAL || configPage1.injTiming == INJ_SEQUENTIAL) //No full sequential for more than 4 cylinders
{
channel1InjDegrees = 0;
channel2InjDegrees = 90;
channel3InjDegrees = 180;
channel4InjDegrees = 270;
}
*/
if (!configPage1.injTiming) { channel1InjDegrees = channel2InjDegrees = channel3InjDegrees = channel4InjDegrees = 0; } //For simultaneous, all squirts happen at the same time if (!configPage1.injTiming) { channel1InjDegrees = channel2InjDegrees = channel3InjDegrees = channel4InjDegrees = 0; } //For simultaneous, all squirts happen at the same time
configPage1.injLayout = 0; //This is a failsafe. We can never run semi-sequential with more than 4 cylinders configPage1.injLayout = 0; //This is a failsafe. We can never run semi-sequential with more than 4 cylinders
@ -830,6 +834,8 @@ void setup()
setFuelSchedule2(100, (unsigned long)(configPage1.primePulse * 100)); setFuelSchedule2(100, (unsigned long)(configPage1.primePulse * 100));
setFuelSchedule3(100, (unsigned long)(configPage1.primePulse * 100)); setFuelSchedule3(100, (unsigned long)(configPage1.primePulse * 100));
setFuelSchedule4(100, (unsigned long)(configPage1.primePulse * 100)); setFuelSchedule4(100, (unsigned long)(configPage1.primePulse * 100));
initialisationComplete = true;
} }
void loop() void loop()
@ -897,7 +903,8 @@ void loop()
} }
#endif #endif
// if (configPage1.displayType && (mainLoopCount & 255) == 1) { updateDisplay();} //Displays currently disabled //Displays currently disabled
// if (configPage1.displayType && (mainLoopCount & 255) == 1) { updateDisplay();}
previousLoopTime = currentLoopTime; previousLoopTime = currentLoopTime;
currentLoopTime = micros(); currentLoopTime = micros();
@ -918,6 +925,7 @@ void loop()
currentStatus.runSecs = 0; //Reset the counter for number of seconds running. currentStatus.runSecs = 0; //Reset the counter for number of seconds running.
secCounter = 0; //Reset our seconds counter. secCounter = 0; //Reset our seconds counter.
currentStatus.startRevolutions = 0; currentStatus.startRevolutions = 0;
toothSystemCount = 0;
MAPcurRev = 0; MAPcurRev = 0;
MAPcount = 0; MAPcount = 0;
currentStatus.rpmDOT = 0; currentStatus.rpmDOT = 0;
@ -1099,15 +1107,6 @@ void loop()
} }
currentStatus.advance = correctionsIgn(currentStatus.advance); currentStatus.advance = correctionsIgn(currentStatus.advance);
/*
//Check for fixed ignition angles
if (configPage2.FixAng != 0) { currentStatus.advance = configPage2.FixAng; } //Check whether the user has set a fixed timing angle
if ( BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK) ) { currentStatus.advance = configPage2.CrankAng; } //Use the fixed cranking ignition angle
//Adjust the advance based on IAT. If the adjustment amount is greater than the current advance, just set advance to 0
byte advanceIATadjust = table2D_getValue(&IATRetardTable, currentStatus.IAT);
if (advanceIATadjust <= currentStatus.advance) { currentStatus.advance -= advanceIATadjust; }
else { currentStatus.advance = 0; }
*/
int injector1StartAngle = 0; int injector1StartAngle = 0;
int injector2StartAngle = 0; int injector2StartAngle = 0;
@ -1154,7 +1153,7 @@ void loop()
long toothDeltaV = (1000000L * angle2 / toothHistory[toothHistoryIndex]) - (1000000L * angle1 / toothHistory[toothHistoryIndex-1]); long toothDeltaV = (1000000L * angle2 / toothHistory[toothHistoryIndex]) - (1000000L * angle1 / toothHistory[toothHistoryIndex-1]);
long toothDeltaT = toothHistory[toothHistoryIndex]; long toothDeltaT = toothHistory[toothHistoryIndex];
//long timeToLastTooth = micros() - toothLastToothTime; //Cannot be unsigned //long timeToLastTooth = micros() - toothLastToothTime;
rpmDelta = (toothDeltaV << 10) / (6 * toothDeltaT); rpmDelta = (toothDeltaV << 10) / (6 * toothDeltaT);
} }
@ -1385,7 +1384,7 @@ void loop()
if( tempCrankAngle < 0) { tempCrankAngle += CRANK_ANGLE_MAX_INJ; } if( tempCrankAngle < 0) { tempCrankAngle += CRANK_ANGLE_MAX_INJ; }
tempStartAngle = injector2StartAngle - channel2InjDegrees; tempStartAngle = injector2StartAngle - channel2InjDegrees;
if ( tempStartAngle < 0) { tempStartAngle += CRANK_ANGLE_MAX_INJ; } if ( tempStartAngle < 0) { tempStartAngle += CRANK_ANGLE_MAX_INJ; }
if ( (tempStartAngle <= tempCrankAngle) && (fuelSchedule1.Status == RUNNING) ) { tempStartAngle += CRANK_ANGLE_MAX_INJ; } if ( (tempStartAngle <= tempCrankAngle) && (fuelSchedule2.Status == RUNNING) ) { tempStartAngle += CRANK_ANGLE_MAX_INJ; }
if ( tempStartAngle > tempCrankAngle ) if ( tempStartAngle > tempCrankAngle )
{ {
setFuelSchedule2( setFuelSchedule2(