For anything you'd like to see added to Speeduino
#21605
At a very quick look around, the VQ35 appears to use some sort of 30-2-2-2 crank pattern, with a separate cam signal that has notches for cylinder ID.

I'll need to try and get some more info on this. You don't happen to have a photo or timing diagram of it do you?
#21609
The best I have found is located here:
http://forums.linkecu.com/topic/7195-no ... cu-in-g35/

It looks like the crank wheel has 6 sets of 12-2 tooth patterns. Each tooth spaced 10 degrees apart.
The 2 cam wheels look to have an encoded pattern to decide which coil to fire.
I think the cam wheels would create a "cyl_phase" variable and the crank tooth count*10 would add to this to determine current angle.
#21610
The cam triggers can advance. The cam falling edges look to happen before the crank falling edge. This makes sense why it happens during the 20 degrees of missing teeth.

I think 2 cam inputs are needed. Each camTrig fxn will keep track of camTrigTime. This can be used by the PrimTrig fxn to set a variable for the engine_phase and then use crankToothCount*10 to determine the engine cycle angle.

primTrig() //falling edge
{
toothCount++;
crankAngle = cyl_phase*120 + toothCount*10
}

cam1SecTrig() // falling edge
{
switch(cyl_phase)
Case 0:
if(cam2 == TRUE)
cyl_phase = 1
...
}

cam2SecTrig() // falling edge
{
switch(cyl_phase)
Case 0:
if(cam1 == TRUE)
cyl_phase = 1
...
}
#21667
Yes, it is a 36-2-2-2 wheel for the crank trigger.
The cam has a series of 5 teeth with one missing (5-1). I think this is the best place to sync the cam. It allows the missing tooth (gap) to be detected by the leading 2 teeth and the trailing 2 teeth.

I will have to find a diagram that describes cyl TDC relative to the crank teeth.

Only one cam signal is needed so please disregard my earlier post.
#21671
This is what I had in mind. It is a first pass to think about the theory. I did not compile it.
Basically, SecondaryTrig looks for the Cam1 single missing pulse rising edge and declares this a "cam edge".
Then Primary Trig looks for the "cam edge" and the first 2 crank missing teeth and starts counting crank edges.
It counts to 36 and rolls over to 1.


void triggerSetup_Vq35deTooth()
{
triggerToothAngle = 360 / configPage2.triggerTeeth; //The number of degrees that passes from tooth to tooth
if(configPage2.TrigSpeed) { triggerToothAngle = 720 / configPage2.triggerTeeth; } //Account for cam speed missing tooth
triggerActualTeeth = configPage2.triggerTeeth - configPage2.triggerMissingTeeth; //The number of physical teeth on the wheel. Doing this here saves us a calculation each time in the interrupt
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)
curStartOfCam1Bank = false;
curStartOfCam1BankLast = false;
}

void triggerPri_Vq35deTooth()
{
curTime = micros(); // get time of falling edge
curGap = curTime - toothLastToothTime; // Time between this falling edge and last falling edge
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)
toothCurrentCount++; //Increment the tooth counter

addToothLogEntry(curGap);

//Begin the missing tooth detection
targetGap = ((toothLastToothTime - toothLastMinusOneToothTime)) * 2;
//More than 1 tooth missing, Multiply by 2 (Checks for a gap 2x greater than the last one).

if ( curGap > targetGap ) { toothCurrentCount += 2 }; //Increment the tooth counter for the 2 missing teeth

// curGap > targetGap -> this means we have found the tooth AFTER the missing teeth
// If switching Cam cycle (cyl banks), and found missing tooth or counted entire trig wheel -> then reset the toothCurrentCount
if ( (curStartOfCam1Bank == true && curStartOfCam1BankLast == false) && ((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;
currentStatus.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;
toothLastToothTime = curTime;
curStartOfCam1BankLast = curStartOfCam1Bank;
}

// Use rising edge in order to set the StartOfCam1Bank signal BEFORE the 2 missing crank teeth of the 12-2 sequence for cyl 1 (falling *MAY* be too late-race condition)
void triggerSec_Vq35deTooth()
{
curTime = micros(); // get time of edge
curGap = curTime - toothLastToothTime; // Time between this edge and last edge
if ( curGap < triggerFilterTime * 2 ) { return; } //Debounce check. Pulses should never be less than triggerFilterTime, so if they are it means a false trigger.

addToothLogEntry(curGap);

//Begin the missing tooth detection (detect only the single missing tooth)
targetGap = (((toothLastToothTime - toothLastMinusOneToothTime)) * 3) >> 1; // 1 tooth missing, mult by 1.5
targetGapMax = (((toothLastToothTime - toothLastMinusOneToothTime)) * 10) >> 2; // 1 tooth missing, mult by 2.5

if ( (curGap > targetGap) && (curGap < targetGapMax) )
{
// found 1 tooth gap -> send out a pulse so the crank function can reset the counter
curStartOfCam1Bank = true;
}
else
{
if ( curGap < targetGap ) {setFilter(curGap);} //Filter can only be recalc'd for the regular teeth, not the missing one.
curStartOfCam1Bank = false;
}

toothLastMinusOneToothTime = toothLastToothTime;
toothLastToothTime = curTime;
}
#21687
Slight change to the primTrig function detecting the camEdge signal.

This could have also been done much like the 24x wheel logic. In this case, the wheel would have 30 teeth (36-2-2-2). That is, 30 falling edges would be detected per 360 degrees. A tooth to crank degree look up table would be used.
The cam signal would detect the single missing tooth as done in previous code. It would set the camEdge variable. When the primTrig crank function detected the camEdge it would reset the crank tooth count to 0.
The 24x to vq35de logic difference is that the 24x secTrig resets the crank tooth counter directly, and the vq35de secTrig sets a camEdge signal and lets the primTrig reset the crank tooth count. The *important* difference is that this makes the primTrig synchronous with the secTrig. The 24x could be done this way also, but is not necessary since there is a +/-7.5 timing slop between the camEdge and the crankEdge.

void triggerPri_Vq35deTooth()
{
curTime = micros(); // get time of falling edge
curGap = curTime - toothLastToothTime; // Time between this falling edge and last falling edge
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)
toothCurrentCount++; //Increment the tooth counter

addToothLogEntry(curGap);

//Begin the missing tooth detection
targetGap = ((toothLastToothTime - toothLastMinusOneToothTime)) * 2;
//More than 1 tooth missing, Multiply by 2 (Checks for a gap 2x greater than the last one).

if ( curGap > targetGap ) { toothCurrentCount += 2 }; //Increment the tooth counter for the 2 missing teeth

// curGap > targetGap -> this means we have found the tooth AFTER the missing teeth
// If found missing tooth or counted entire trig wheel -> then check if Cam1 start of cycle is valid
if ( ((curGap > targetGap) )
{
// We have found missing teeth, check if Cam1 is at the beginning of 0 to 360 degree cycle OR all crank teeth counted
if ( (curStartOfCam1Bank == true) && (curStartOfCam1BankLast == false) || (toothCurrentCount > triggerActualTeeth) )
{
// 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.
if ( toothCurrentCount < (triggerActualTeeth) && currentStatus.hasSync ) { currentStatus.hasSync = false; return; }
toothCurrentCount = 1;
revolutionOne = !revolutionOne; //Flip sequential revolution tracker
toothOneMinusOneTime = toothOneTime;
toothOneTime = curTime;
currentStatus.hasSync = true;
currentStatus.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;
toothLastToothTime = curTime;
curStartOfCam1BankLast = curStartOfCam1Bank;
}

Had it running for a short period again. Same as […]

Ok, here is the first version of the adapter plate[…]

Ignition Angle doubled?

don't load your old tune in case it is corrupted[…]

Yes, totally wrong setting. Slight noise in TPS ca[…]

Still can't find what you're looking for?