Move a chunk of the prediction code out of speeduino.ino into crankMaths
This commit is contained in:
parent
bc94053f10
commit
765e52fce5
|
@ -15,9 +15,14 @@
|
|||
|
||||
unsigned long angleToTime(int16_t, byte);
|
||||
uint16_t timeToAngle(unsigned long, byte);
|
||||
void doCrankSpeedCalcs();
|
||||
|
||||
volatile uint16_t timePerDegree;
|
||||
volatile uint16_t timePerDegreex16;
|
||||
volatile uint16_t degreesPeruSx2048;
|
||||
|
||||
//These are only part of the experimental 2nd deriv calcs
|
||||
byte deltaToothCount = 0; //The last tooth that was used with the deltaV calc
|
||||
int rpmDelta;
|
||||
|
||||
#endif
|
|
@ -1,6 +1,7 @@
|
|||
#include "globals.h"
|
||||
#include "crankMaths.h"
|
||||
#include "decoders.h"
|
||||
#include "timers.h"
|
||||
|
||||
/*
|
||||
* Converts a crank angle into a time from or since that angle occurred.
|
||||
|
@ -76,4 +77,71 @@ uint16_t timeToAngle(unsigned long time, byte method)
|
|||
|
||||
return returnAngle;
|
||||
|
||||
}
|
||||
|
||||
void doCrankSpeedCalcs()
|
||||
{
|
||||
//********************************************************
|
||||
//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 > 0) && (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(true)
|
||||
{
|
||||
//Only recalculate deltaV if the tooth has changed since last time (DeltaV stays the same until the next tooth)
|
||||
//if (deltaToothCount != toothCurrentCount)
|
||||
{
|
||||
deltaToothCount = toothCurrentCount;
|
||||
int angle1, angle2; //These represent the crank angles that are travelled for the last 2 pulses
|
||||
if(configPage4.TrigPattern == 4)
|
||||
{
|
||||
//Special case for 70/110 pattern on 4g63
|
||||
angle2 = triggerToothAngle; //Angle 2 is the most recent
|
||||
if (angle2 == 70) { angle1 = 110; }
|
||||
else { angle1 = 70; }
|
||||
}
|
||||
else if(configPage4.TrigPattern == 0)
|
||||
{
|
||||
//Special case for missing tooth decoder where the missing tooth was one of the last 2 seen
|
||||
if(toothCurrentCount == 1) { angle2 = 2*triggerToothAngle; angle1 = triggerToothAngle; }
|
||||
else if(toothCurrentCount == 2) { angle1 = 2*triggerToothAngle; angle2 = triggerToothAngle; }
|
||||
else { angle1 = triggerToothAngle; angle2 = triggerToothAngle; }
|
||||
}
|
||||
else { angle1 = triggerToothAngle; angle2 = triggerToothAngle; }
|
||||
|
||||
long toothDeltaV = (1000000L * angle2 / toothHistory[toothHistoryIndex]) - (1000000L * angle1 / toothHistory[toothHistoryIndex-1]);
|
||||
long toothDeltaT = toothHistory[toothHistoryIndex];
|
||||
//long timeToLastTooth = micros() - toothLastToothTime;
|
||||
|
||||
rpmDelta = (toothDeltaV << 10) / (6 * toothDeltaT);
|
||||
}
|
||||
|
||||
timePerDegreex16 = ldiv( 2666656L, currentStatus.RPM + rpmDelta).quot; //This give accuracy down to 0.1 of a degree and can provide noticably better timing results on low res triggers
|
||||
timePerDegree = timePerDegreex16 / 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
//If we can, attempt to get the timePerDegree by comparing the times of the last two teeth seen. This is only possible for evenly spaced teeth
|
||||
noInterrupts();
|
||||
if( (triggerToothAngleIsCorrect == true) && (toothLastToothTime > toothLastMinusOneToothTime) )
|
||||
{
|
||||
//noInterrupts();
|
||||
unsigned long tempToothLastToothTime = toothLastToothTime;
|
||||
unsigned long tempToothLastMinusOneToothTime = toothLastMinusOneToothTime;
|
||||
uint16_t tempTriggerToothAngle = triggerToothAngle;
|
||||
interrupts();
|
||||
timePerDegreex16 = (unsigned long)( (tempToothLastToothTime - tempToothLastMinusOneToothTime)*16) / tempTriggerToothAngle;
|
||||
timePerDegree = timePerDegreex16 / 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
//long timeThisRevolution = (micros_safe() - toothOneTime); //micros() is no longer interrupt safe
|
||||
interrupts();
|
||||
//long rpm_adjust = (timeThisRevolution * (long)currentStatus.rpmDOT) / 1000000; //Take into account any likely accleration that has occurred since the last full revolution completed
|
||||
long rpm_adjust = 0;
|
||||
timePerDegreex16 = ldiv( 2666656L, currentStatus.RPM + rpm_adjust).quot; //The use of a x16 value gives accuracy down to 0.1 of a degree and can provide noticably better timing results on low res triggers
|
||||
timePerDegree = timePerDegreex16 / 16;
|
||||
}
|
||||
}
|
||||
degreesPeruSx2048 = 2048 / timePerDegree;
|
||||
}
|
|
@ -74,8 +74,6 @@ unsigned long counter;
|
|||
unsigned long currentLoopTime; //The time the current loop started (uS)
|
||||
unsigned long previousLoopTime; //The time the previous loop started (uS)
|
||||
|
||||
byte deltaToothCount = 0; //The last tooth that was used with the deltaV calc
|
||||
int rpmDelta;
|
||||
byte maxIgnOutputs = 1; //Used for rolling rev limiter
|
||||
byte curRollingCut = 0; //Rolling rev limiter, current ignition channel being cut
|
||||
byte rollingCutCounter = 0; //how many times (revolutions) the ignition has been cut in a row
|
||||
|
@ -209,6 +207,15 @@ void setup()
|
|||
flexBoostTable.values16 = configPage10.flexBoostAdj;
|
||||
flexBoostTable.axisX = configPage10.flexBoostBins;
|
||||
|
||||
knockWindowStartTable.valueSize = SIZE_BYTE;
|
||||
knockWindowStartTable.xSize = 6;
|
||||
knockWindowStartTable.values = configPage10.knock_window_angle;
|
||||
knockWindowStartTable.axisX = configPage10.knock_window_rpms;
|
||||
knockWindowDurationTable.valueSize = SIZE_BYTE;
|
||||
knockWindowDurationTable.xSize = 6;
|
||||
knockWindowDurationTable.values = configPage10.knock_window_dur;
|
||||
knockWindowDurationTable.axisX = configPage10.knock_window_rpms;
|
||||
|
||||
//Setup the calibration tables
|
||||
loadCalibration();
|
||||
|
||||
|
@ -1119,68 +1126,7 @@ void loop()
|
|||
int tempCrankAngle;
|
||||
int tempStartAngle;
|
||||
|
||||
//********************************************************
|
||||
//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 > 0) && (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(true)
|
||||
{
|
||||
//Only recalculate deltaV if the tooth has changed since last time (DeltaV stays the same until the next tooth)
|
||||
//if (deltaToothCount != toothCurrentCount)
|
||||
{
|
||||
deltaToothCount = toothCurrentCount;
|
||||
int angle1, angle2; //These represent the crank angles that are travelled for the last 2 pulses
|
||||
if(configPage4.TrigPattern == 4)
|
||||
{
|
||||
//Special case for 70/110 pattern on 4g63
|
||||
angle2 = triggerToothAngle; //Angle 2 is the most recent
|
||||
if (angle2 == 70) { angle1 = 110; }
|
||||
else { angle1 = 70; }
|
||||
}
|
||||
else if(configPage4.TrigPattern == 0)
|
||||
{
|
||||
//Special case for missing tooth decoder where the missing tooth was one of the last 2 seen
|
||||
if(toothCurrentCount == 1) { angle2 = 2*triggerToothAngle; angle1 = triggerToothAngle; }
|
||||
else if(toothCurrentCount == 2) { angle1 = 2*triggerToothAngle; angle2 = triggerToothAngle; }
|
||||
else { angle1 = triggerToothAngle; angle2 = triggerToothAngle; }
|
||||
}
|
||||
else { angle1 = triggerToothAngle; angle2 = triggerToothAngle; }
|
||||
|
||||
long toothDeltaV = (1000000L * angle2 / toothHistory[toothHistoryIndex]) - (1000000L * angle1 / toothHistory[toothHistoryIndex-1]);
|
||||
long toothDeltaT = toothHistory[toothHistoryIndex];
|
||||
//long timeToLastTooth = micros() - toothLastToothTime;
|
||||
|
||||
rpmDelta = (toothDeltaV << 10) / (6 * toothDeltaT);
|
||||
}
|
||||
|
||||
timePerDegreex16 = ldiv( 2666656L, currentStatus.RPM + rpmDelta).quot; //This give accuracy down to 0.1 of a degree and can provide noticably better timing results on low res triggers
|
||||
timePerDegree = timePerDegreex16 / 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
//If we can, attempt to get the timePerDegree by comparing the times of the last two teeth seen. This is only possible for evenly spaced teeth
|
||||
if( (triggerToothAngleIsCorrect == true) && (toothLastToothTime > toothLastMinusOneToothTime) && false ) //This is currently NOT working. Don't know why yet
|
||||
{
|
||||
noInterrupts();
|
||||
unsigned long tempToothLastToothTime = toothLastToothTime;
|
||||
unsigned long tempToothLastMinusOneToothTime = toothLastMinusOneToothTime;
|
||||
uint16_t tempTriggerToothAngle = triggerToothAngle;
|
||||
interrupts();
|
||||
timePerDegreex16 = (unsigned long)( (tempToothLastToothTime - tempToothLastMinusOneToothTime)*16) / tempTriggerToothAngle;
|
||||
timePerDegree = timePerDegreex16 / 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
long timeThisRevolution = (micros_safe() - toothOneTime); //micros() is no longer interrupt safe
|
||||
long rpm_adjust = (timeThisRevolution * (long)currentStatus.rpmDOT) / 1000000; //Take into account any likely accleration that has occurred since the last full revolution completed
|
||||
rpm_adjust = 0;
|
||||
timePerDegreex16 = ldiv( 2666656L, currentStatus.RPM + rpm_adjust).quot; //The use of a x16 value gives accuracy down to 0.1 of a degree and can provide noticably better timing results on low res triggers
|
||||
timePerDegree = timePerDegreex16 / 16;
|
||||
}
|
||||
|
||||
}
|
||||
degreesPeruSx2048 = 2048 / timePerDegree;
|
||||
doCrankSpeedCalcs(); //In crankMaths.ino
|
||||
|
||||
//Check that the duty cycle of the chosen pulsewidth isn't too high.
|
||||
unsigned long pwLimit = percentage(configPage2.dutyLim, revolutionTime); //The pulsewidth limit is determined to be the duty cycle limit (Eg 85%) by the total time it takes to perform 1 revolution
|
||||
|
|
Loading…
Reference in New Issue