From 35fa068575f43bda71f2cc2e41ecaea8d444f2df Mon Sep 17 00:00:00 2001 From: Josh Stewart Date: Thu, 7 Dec 2017 13:46:04 +1100 Subject: [PATCH] Staged injection (Table and automatic modes) --- speeduino/decoders.h | 1 + speeduino/decoders.ino | 8 ++++++++ speeduino/globals.h | 7 ++++++- speeduino/maths.h | 1 + speeduino/speeduino.ino | 29 +++++++++++++++++++++++++++++ 5 files changed, 45 insertions(+), 1 deletion(-) diff --git a/speeduino/decoders.h b/speeduino/decoders.h index cd5af171..c5c30cdc 100644 --- a/speeduino/decoders.h +++ b/speeduino/decoders.h @@ -59,6 +59,7 @@ volatile unsigned long triggerFilterTime; // The shortest time (in uS) that puls unsigned long triggerSecFilterTime; // The shortest time (in uS) that pulses will be accepted (Used for debounce filtering) for the secondary input unsigned int triggerSecFilterTime_duration; // The shortest valid time (in uS) pulse DURATION volatile int triggerToothAngle; //The number of crank degrees that elapse per tooth +volatile bool triggerToothAngleIsCorrect = false; //Whether or not the triggerToothAngle variable is currently accurate. Some patterns have times when the triggerToothAngle variable cannot be accurately set. 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 bool decoderIsLowRes = false; //Is set true, certain extra calculations are performed for better timing accuracy diff --git a/speeduino/decoders.ino b/speeduino/decoders.ino index 77eb5c7f..ed04ed9b 100644 --- a/speeduino/decoders.ino +++ b/speeduino/decoders.ino @@ -173,6 +173,7 @@ void triggerPri_missingTooth() 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 toothLastMinusOneToothTime = toothLastToothTime; toothLastToothTime = curTime; + triggerToothAngleIsCorrect = false; //The tooth angle is double at this point } } else @@ -181,6 +182,7 @@ void triggerPri_missingTooth() setFilter(curGap); toothLastMinusOneToothTime = toothLastToothTime; toothLastToothTime = curTime; + triggerToothAngleIsCorrect = true; } } @@ -238,6 +240,7 @@ int getCrankAngle_missingTooth(int timePerDegree) //crankAngle += DIV_ROUND_CLOSEST(elapsedTime, timePerDegree); 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; } + //crankAngle += uSToDegrees(elapsedTime); //Sequential check (simply sets whether we're on the first or 2nd revoltuion of the cycle) if (tempRevolutionOne) { crankAngle += 360; } @@ -289,6 +292,7 @@ void triggerSetup_DualWheel() 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; decoderIsSequential = true; + triggerToothAngleIsCorrect = true; //This is always true for this pattern MAX_STALL_TIME = (3333UL * triggerToothAngle); //Minimum 50rpm. (3333uS is the time per degree at 50rpm) } @@ -437,6 +441,7 @@ void triggerSetup_BasicDistributor() decoderIsSequential = false; toothCurrentCount = 0; //Default value decoderHasFixedCrankingTiming = true; + triggerToothAngleIsCorrect = true; if(configPage1.nCylinders <= 4) { MAX_STALL_TIME = (1851UL * triggerToothAngle); }//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. else { MAX_STALL_TIME = (3200UL * triggerToothAngle); } //Minimum 50rpm. (3200uS is the time per degree at 50rpm). @@ -648,6 +653,7 @@ void triggerSetup_4G63() secondDerivEnabled = false; decoderIsSequential = true; decoderHasFixedCrankingTiming = true; + triggerToothAngleIsCorrect = true; MAX_STALL_TIME = 366667UL; //Minimum 50rpm based on the 110 degree tooth spacing if(initialisationComplete == false) { toothLastToothTime = micros(); } //Set a startup value here to avoid filter errors when starting. This MUST have the initi check to prevent the fuel pump just staying on all the time //decoderIsLowRes = true; @@ -1167,6 +1173,7 @@ void triggerSetup_Audi135() MAX_STALL_TIME = (3333UL * triggerToothAngle); //Minimum 50rpm. (3333uS is the time per degree at 50rpm) secondDerivEnabled = false; decoderIsSequential = true; + triggerToothAngleIsCorrect = true; } void triggerPri_Audi135() @@ -1408,6 +1415,7 @@ void triggerSetup_Miata9905() triggerFilterTime = 1500; //10000 rpm, assuming we're triggering on both edges off the crank tooth. triggerSecFilterTime = 0; //Need to figure out something better for this decoderHasFixedCrankingTiming = true; + triggerToothAngleIsCorrect = true; } void triggerPri_Miata9905() diff --git a/speeduino/globals.h b/speeduino/globals.h index 8b9fc8a9..30d797a4 100644 --- a/speeduino/globals.h +++ b/speeduino/globals.h @@ -134,6 +134,9 @@ #define EGO_ALGORITHM_SIMPLE 0 #define EGO_ALGORITHM_PID 2 +#define STAGING_MODE_TABLE 0 +#define STAGING_MODE_AUTO 1 + #define MAX_RPM 18000 //This is the maximum rpm that the ECU will attempt to run at. It is NOT related to the rev limiter, but is instead dictates how fast certain operations will be allowed to run. Lower number gives better performance #define engineSquirtsPerCycle 2 //Would be 1 for a 2 stroke @@ -634,7 +637,9 @@ struct config11 { uint16_t boostSens; byte boostIntv; - byte unused11_28_192[164]; + uint16_t stagedInjSizePri; + uint16_t stagedInjSizeSec; + byte unused11_28_192[160]; #if defined(CORE_AVR) }; diff --git a/speeduino/maths.h b/speeduino/maths.h index 48e799b6..16243fcd 100644 --- a/speeduino/maths.h +++ b/speeduino/maths.h @@ -6,6 +6,7 @@ unsigned long percentage(byte, unsigned long); //#define degreesToUS(degrees) (decoderIsLowRes == true ) ? ((degrees * 166666UL) / currentStatus.RPM) : (degrees * (unsigned long)timePerDegree) #define degreesToUS(degrees) ((degrees * revolutionTime) / 360) +#define fastDegreesToUS(degrees) (degrees * (unsigned long)timePerDegree) //#define degreesToUS(degrees) ((degrees * revolutionTime * 3054198967ULL) >> 40) //Fast version of divide by 360 //#define degreesToUS(degrees) (degrees * (unsigned long)timePerDegree) diff --git a/speeduino/speeduino.ino b/speeduino/speeduino.ino index fd3f96e4..be080906 100644 --- a/speeduino/speeduino.ino +++ b/speeduino/speeduino.ino @@ -51,6 +51,8 @@ struct config10 configPage10; struct config11 configPage11; int req_fuel_uS, inj_opentime_uS; +uint16_t staged_req_fuel_mult_pri; +uint16_t staged_req_fuel_mult_sec; bool ignitionOn = false; //The current state of the ignition system bool fuelOn = false; //The current state of the ignition system @@ -281,6 +283,23 @@ void setup() req_fuel_uS = configPage1.reqFuel * 100; //Convert to uS and an int. This is the only variable to be used in calculations inj_opentime_uS = configPage1.injOpen * 100; //Injector open time. Comes through as ms*10 (Eg 15.5ms = 155). + if(configPage11.stagingEnabled == true) + { + uint32_t totalInjector = configPage11.stagedInjSizePri + configPage11.stagedInjSizeSec; + /* + These values are a percentage of the req_fuel value that would be required for each injector channel to deliver that much fuel. + Eg: + Pri injectors are 250cc + Sec injectors are 500cc + Total injector capacity = 750cc + + staged_req_fuel_mult_pri = 300% (The primary injectors would have to run 3x the overall PW in order to be the equivalent of the full 750cc capacity + staged_req_fuel_mult_sec = 150% (The secondary injectors would have to run 1.5x the overall PW in order to be the equivalent of the full 750cc capacity + */ + staged_req_fuel_mult_pri = (100 * totalInjector) / configPage11.stagedInjSizePri; + staged_req_fuel_mult_sec = (100 * totalInjector) / configPage11.stagedInjSizeSec; + } + //Begin the main crank trigger interrupt pin setup //The interrupt numbering is a bit odd - See here for reference: http://arduino.cc/en/Reference/AttachInterrupt //These assignments are based on the Arduino Mega AND VARY BETWEEN BOARDS. Please confirm the board you are using and update acordingly. @@ -433,6 +452,16 @@ void setup() } if (!configPage1.injTiming) { channel1InjDegrees = channel2InjDegrees = 0; } //For simultaneous, all squirts happen at the same time + //Check if injector staging is enabled + if(configPage11.stagingEnabled == true) + { + channel3InjEnabled = true; + channel4InjEnabled = true; + + channel3InjDegrees = channel1InjDegrees; + channel4InjDegrees = channel2InjDegrees; + } + channel1InjEnabled = true; channel2InjEnabled = true; break;